passenger 4.0.48 → 4.0.49

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (218) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +36 -2
  5. data/.travis.yml +1 -1
  6. data/CHANGELOG +16 -0
  7. data/Rakefile +0 -1
  8. data/build/apache2.rb +4 -4
  9. data/build/common_library.rb +18 -18
  10. data/build/cplusplus_support.rb +2 -2
  11. data/build/documentation.rb +1 -1
  12. data/build/integration_tests.rb +12 -4
  13. data/build/misc.rb +12 -7
  14. data/build/packaging.rb +14 -14
  15. data/build/preprocessor.rb +10 -10
  16. data/build/rake_extensions.rb +11 -11
  17. data/build/ruby_extension.rb +2 -2
  18. data/dev/ci/inituidgid +24 -0
  19. data/dev/ci/run_jenkins.sh +57 -0
  20. data/dev/ci/run_rpm_tests.sh +77 -0
  21. data/dev/{run_travis.sh → ci/run_travis.sh} +60 -4
  22. data/doc/Users guide Nginx.txt +2 -2
  23. data/doc/users_guide_snippets/environment_variables.txt +0 -2
  24. data/doc/users_guide_snippets/tips.txt +20 -1
  25. data/ext/apache2/Bucket.cpp +18 -18
  26. data/ext/apache2/Bucket.h +4 -4
  27. data/ext/apache2/Configuration.cpp +7 -7
  28. data/ext/apache2/Configuration.hpp +43 -43
  29. data/ext/apache2/DirectoryMapper.h +5 -5
  30. data/ext/apache2/Hooks.cpp +142 -142
  31. data/ext/apache2/MergeDirConfig.cpp +40 -40
  32. data/ext/common/Account.h +17 -17
  33. data/ext/common/AccountsDatabase.h +9 -9
  34. data/ext/common/AgentsStarter.cpp +2 -2
  35. data/ext/common/AgentsStarter.h +40 -40
  36. data/ext/common/ApplicationPool2/Common.h +10 -6
  37. data/ext/common/ApplicationPool2/ComponentInfo.h +2 -2
  38. data/ext/common/ApplicationPool2/DirectSpawner.h +17 -17
  39. data/ext/common/ApplicationPool2/DummySpawner.h +5 -5
  40. data/ext/common/ApplicationPool2/Group.h +54 -38
  41. data/ext/common/ApplicationPool2/Implementation.cpp +76 -49
  42. data/ext/common/ApplicationPool2/Options.h +98 -91
  43. data/ext/common/ApplicationPool2/Pool.h +70 -69
  44. data/ext/common/ApplicationPool2/Process.h +21 -21
  45. data/ext/common/ApplicationPool2/Session.h +11 -11
  46. data/ext/common/ApplicationPool2/SmartSpawner.h +60 -60
  47. data/ext/common/ApplicationPool2/Socket.h +19 -19
  48. data/ext/common/ApplicationPool2/Spawner.h +64 -72
  49. data/ext/common/ApplicationPool2/SpawnerFactory.h +4 -4
  50. data/ext/common/ApplicationPool2/SuperGroup.h +41 -41
  51. data/ext/common/BackgroundEventLoop.cpp +1 -1
  52. data/ext/common/BackgroundEventLoop.h +2 -2
  53. data/ext/common/Constants.h +1 -1
  54. data/ext/common/EventedBufferedInput.h +5 -5
  55. data/ext/common/EventedClient.h +51 -51
  56. data/ext/common/EventedMessageServer.h +39 -39
  57. data/ext/common/EventedServer.h +32 -32
  58. data/ext/common/Exceptions.h +23 -23
  59. data/ext/common/FileDescriptor.h +18 -18
  60. data/ext/common/Logging.cpp +1 -1
  61. data/ext/common/MessageClient.h +27 -27
  62. data/ext/common/MessageReadersWriters.h +79 -79
  63. data/ext/common/MessageServer.h +59 -59
  64. data/ext/common/RandomGenerator.h +12 -12
  65. data/ext/common/ResourceLocator.h +8 -8
  66. data/ext/common/SafeLibev.h +54 -25
  67. data/ext/common/ServerInstanceDir.h +31 -31
  68. data/ext/common/StaticString.h +50 -48
  69. data/ext/common/Utils.cpp +73 -78
  70. data/ext/common/Utils.h +6 -6
  71. data/ext/common/Utils/Base64.cpp +3 -3
  72. data/ext/common/Utils/Base64.h +7 -7
  73. data/ext/common/Utils/BlockingQueue.h +9 -9
  74. data/ext/common/Utils/BufferedIO.h +17 -17
  75. data/ext/common/Utils/CachedFileStat.hpp +16 -16
  76. data/ext/common/Utils/Dechunker.h +25 -25
  77. data/ext/common/Utils/FileChangeChecker.h +10 -10
  78. data/ext/common/Utils/MemZeroGuard.h +5 -5
  79. data/ext/common/Utils/MemoryBarrier.h +1 -1
  80. data/ext/common/Utils/MessageIO.h +61 -61
  81. data/ext/common/Utils/ProcessMetricsCollector.h +40 -40
  82. data/ext/common/Utils/ScopeGuard.h +7 -7
  83. data/ext/common/Utils/SpeedMeter.h +1 -1
  84. data/ext/common/Utils/StrIntUtils.cpp +13 -13
  85. data/ext/common/Utils/StrIntUtils.h +3 -3
  86. data/ext/common/Utils/StringScanning.h +5 -5
  87. data/ext/common/Utils/SystemMetricsCollector.h +2 -2
  88. data/ext/common/Utils/SystemTime.h +10 -10
  89. data/ext/common/Utils/Template.h +2 -2
  90. data/ext/common/Utils/Timer.h +6 -6
  91. data/ext/common/Utils/VariantMap.h +29 -29
  92. data/ext/common/agents/Base.cpp +19 -19
  93. data/ext/common/agents/HelperAgent/AgentOptions.h +1 -1
  94. data/ext/common/agents/HelperAgent/FileBackedPipe.h +6 -6
  95. data/ext/common/agents/HelperAgent/Main.cpp +44 -43
  96. data/ext/common/agents/HelperAgent/RequestHandler.cpp +4 -4
  97. data/ext/common/agents/HelperAgent/RequestHandler.h +29 -28
  98. data/ext/common/agents/HelperAgent/ScgiRequestParser.h +56 -50
  99. data/ext/common/agents/LoggingAgent/AdminController.h +8 -8
  100. data/ext/common/agents/LoggingAgent/DataStoreId.h +17 -17
  101. data/ext/common/agents/LoggingAgent/FilterSupport.h +167 -167
  102. data/ext/common/agents/LoggingAgent/LoggingServer.h +122 -122
  103. data/ext/common/agents/LoggingAgent/Main.cpp +7 -7
  104. data/ext/common/agents/LoggingAgent/RemoteSender.h +54 -54
  105. data/ext/common/agents/SpawnPreparer.cpp +4 -4
  106. data/ext/common/agents/TempDirToucher.c +2 -2
  107. data/ext/common/agents/Watchdog/AgentWatcher.cpp +47 -47
  108. data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +7 -7
  109. data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +7 -7
  110. data/ext/common/agents/Watchdog/Main.cpp +22 -22
  111. data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +9 -9
  112. data/ext/libeio/eio.c +1 -1
  113. data/ext/nginx/Configuration.c +30 -30
  114. data/ext/nginx/Configuration.h +1 -1
  115. data/ext/nginx/ContentHandler.c +54 -54
  116. data/ext/nginx/ContentHandler.h +3 -3
  117. data/ext/nginx/StaticContentHandler.c +2 -2
  118. data/ext/nginx/ngx_http_passenger_module.c +21 -21
  119. data/ext/oxt/detail/backtrace_enabled.hpp +1 -1
  120. data/ext/oxt/detail/context.hpp +1 -1
  121. data/ext/oxt/detail/spin_lock_darwin.hpp +4 -4
  122. data/ext/oxt/detail/spin_lock_gcc_x86.hpp +3 -3
  123. data/ext/oxt/detail/spin_lock_pthreads.hpp +4 -4
  124. data/ext/oxt/detail/tracable_exception_disabled.hpp +1 -1
  125. data/ext/oxt/dynamic_thread_group.hpp +18 -18
  126. data/ext/oxt/implementation.cpp +9 -8
  127. data/ext/oxt/macros.hpp +2 -2
  128. data/ext/oxt/system_calls.cpp +11 -11
  129. data/ext/oxt/system_calls.hpp +13 -13
  130. data/ext/oxt/thread.hpp +22 -14
  131. data/ext/ruby/passenger_native_support.c +55 -55
  132. data/lib/phusion_passenger.rb +24 -24
  133. data/lib/phusion_passenger/common_library.rb +2 -0
  134. data/lib/phusion_passenger/loader_shared_helpers.rb +18 -18
  135. data/lib/phusion_passenger/packaging.rb +9 -4
  136. data/lib/phusion_passenger/platform_info/apache.rb +45 -31
  137. data/lib/phusion_passenger/platform_info/compiler.rb +11 -11
  138. data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
  139. data/lib/phusion_passenger/request_handler/thread_handler.rb +8 -8
  140. data/lib/phusion_passenger/standalone/app_finder.rb +16 -16
  141. data/lib/phusion_passenger/standalone/command.rb +22 -22
  142. data/packaging/rpm/LICENSE.txt +19 -0
  143. data/packaging/rpm/Makefile +13 -0
  144. data/packaging/rpm/README.md +41 -0
  145. data/packaging/rpm/Vagrantfile +38 -0
  146. data/{rpm/Vagrantfile → packaging/rpm/Vagrantfile.centos} +0 -0
  147. data/packaging/rpm/build +170 -0
  148. data/packaging/rpm/create_project +41 -0
  149. data/packaging/rpm/git_update +88 -0
  150. data/packaging/rpm/image/Dockerfile +37 -0
  151. data/packaging/rpm/image/Gemfile +3 -0
  152. data/packaging/rpm/image/Gemfile.lock +12 -0
  153. data/packaging/rpm/image/RPM-GPG-KEY-amazon-ga +19 -0
  154. data/packaging/rpm/image/amazon2014-i386.cfg +96 -0
  155. data/packaging/rpm/image/amazon2014-x86_64.cfg +96 -0
  156. data/packaging/rpm/image/site-defaults.cfg +168 -0
  157. data/packaging/rpm/internal/build_tasks.rb +238 -0
  158. data/packaging/rpm/internal/dummygpg +11 -0
  159. data/packaging/rpm/internal/exec_build +42 -0
  160. data/packaging/rpm/internal/get_distro_arch +14 -0
  161. data/packaging/rpm/internal/get_distro_id +10 -0
  162. data/packaging/rpm/internal/git_update +27 -0
  163. data/packaging/rpm/internal/inituidgid +17 -0
  164. data/packaging/rpm/internal/my_init +344 -0
  165. data/packaging/rpm/internal/python27 +3 -0
  166. data/packaging/rpm/internal/repo_update +46 -0
  167. data/packaging/rpm/internal/setuser +26 -0
  168. data/packaging/rpm/internal/tracking_helper +40 -0
  169. data/packaging/rpm/jenkins_release +99 -0
  170. data/packaging/rpm/lib/build_tasks_support.rb +402 -0
  171. data/packaging/rpm/lib/preprocessor.rb +341 -0
  172. data/packaging/rpm/nginx_spec/404.html +119 -0
  173. data/packaging/rpm/nginx_spec/50x.html +119 -0
  174. data/packaging/rpm/nginx_spec/index.html +116 -0
  175. data/packaging/rpm/nginx_spec/nginx-auto-cc-gcc.patch +13 -0
  176. data/packaging/rpm/nginx_spec/nginx-logo.png +0 -0
  177. data/packaging/rpm/nginx_spec/nginx-upgrade +13 -0
  178. data/packaging/rpm/nginx_spec/nginx-upgrade.8 +151 -0
  179. data/packaging/rpm/nginx_spec/nginx.conf +131 -0
  180. data/packaging/rpm/nginx_spec/nginx.init +144 -0
  181. data/packaging/rpm/nginx_spec/nginx.logrotate +13 -0
  182. data/packaging/rpm/nginx_spec/nginx.service +15 -0
  183. data/packaging/rpm/nginx_spec/nginx.spec.template +559 -0
  184. data/packaging/rpm/nginx_spec/nginx.sysconfig +4 -0
  185. data/packaging/rpm/nginx_spec/passenger.conf +9 -0
  186. data/packaging/rpm/nginx_spec/poweredby.png +0 -0
  187. data/{rpm → packaging/rpm/passenger_spec}/apache-passenger.conf.in +0 -0
  188. data/{rpm → packaging/rpm/passenger_spec}/config.json +0 -0
  189. data/{rpm → packaging/rpm/passenger_spec}/passenger.logrotate +0 -0
  190. data/{rpm → packaging/rpm/passenger_spec}/passenger.spec.template +58 -31
  191. data/{rpm → packaging/rpm/passenger_spec}/passenger_dynamic_thread_group.patch +0 -0
  192. data/{rpm → packaging/rpm/passenger_spec}/passenger_tests_default_config_example.patch +0 -0
  193. data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-GLIBC_HAVE_LONG_LONG.patch +0 -0
  194. data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-gcc47-include-sys_types.patch +0 -0
  195. data/packaging/rpm/repo_update +114 -0
  196. data/packaging/rpm/setup-system +60 -0
  197. data/packaging/rpm/shell +10 -0
  198. data/resources/templates/standalone/config.erb +3 -1
  199. data/test/config.json.rpm-automation +1 -1
  200. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +11 -11
  201. data/test/cxx/ApplicationPool2/OptionsTest.cpp +5 -5
  202. data/test/cxx/ApplicationPool2/PoolTest.cpp +129 -89
  203. data/test/cxx/ApplicationPool2/ProcessTest.cpp +15 -15
  204. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +22 -22
  205. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +11 -11
  206. data/test/cxx/ScgiRequestParserTest.cpp +75 -61
  207. data/test/cxx/UtilsTest.cpp +86 -85
  208. data/test/gdbinit.example +3 -0
  209. data/test/integration_tests/nginx_tests.rb +3 -3
  210. data/test/integration_tests/source_packaging_test.rb +3 -1
  211. data/test/stub/nginx/nginx.conf.erb +8 -1
  212. data/test/support/nginx_controller.rb +7 -7
  213. metadata +62 -17
  214. metadata.gz.asc +7 -7
  215. data/build/rpm.rb +0 -128
  216. data/dev/rpmtool +0 -21
  217. data/dev/test_rpm_packaging.sh +0 -28
  218. data/rpm/get_distro_id.py +0 -4
@@ -35,6 +35,7 @@
35
35
  #include <UnionStation/Transaction.h>
36
36
  #include <ApplicationPool2/Options.h>
37
37
  #include <Utils/StringMap.h>
38
+ #include <Utils/VariantMap.h>
38
39
 
39
40
  namespace tut {
40
41
  struct ApplicationPool2_PoolTest;
@@ -119,17 +120,17 @@ enum DisableResult {
119
120
  // The process has been successfully disabled.
120
121
  // Returned by functions and passed to the callback.
121
122
  DR_SUCCESS,
122
-
123
+
123
124
  // The disabling of the process was canceled before completion.
124
125
  // The process still exists.
125
126
  // Only passed to the callback.
126
127
  DR_CANCELED,
127
-
128
+
128
129
  // Nothing happened: the requested process does not exist (anymore)
129
130
  // or was already disabled.
130
131
  // Returned by functions and passed to the callback.
131
132
  DR_NOOP,
132
-
133
+
133
134
  // The disabling of the process failed: an error occurred.
134
135
  // Returned by functions and passed to the callback.
135
136
  DR_ERROR,
@@ -169,7 +170,7 @@ typedef boost::function<void ()> Callback;
169
170
  struct GetWaiter {
170
171
  Options options;
171
172
  GetCallback callback;
172
-
173
+
173
174
  GetWaiter(const Options &o, const GetCallback &cb)
174
175
  : options(o),
175
176
  callback(cb)
@@ -186,8 +187,9 @@ struct Ticket {
186
187
  };
187
188
 
188
189
  struct SpawnerConfig {
189
- // Used by error pages.
190
+ // Used by error pages and hooks.
190
191
  ResourceLocator resourceLocator;
192
+ const VariantMap *agentsOptions;
191
193
 
192
194
  // Used for Union Station logging.
193
195
  UnionStation::CorePtr unionStationCore;
@@ -203,8 +205,10 @@ struct SpawnerConfig {
203
205
 
204
206
  SpawnerConfig(const ResourceLocator &_resourceLocator,
205
207
  const UnionStation::CorePtr &_unionStationCore = UnionStation::CorePtr(),
206
- const RandomGeneratorPtr &randomGenerator = RandomGeneratorPtr())
208
+ const RandomGeneratorPtr &randomGenerator = RandomGeneratorPtr(),
209
+ const VariantMap *_agentsOptions = NULL)
207
210
  : resourceLocator(_resourceLocator),
211
+ agentsOptions(_agentsOptions),
208
212
  unionStationCore(_unionStationCore),
209
213
  concurrency(1),
210
214
  spawnerCreationSleepTime(0),
@@ -36,10 +36,10 @@ using namespace std;
36
36
  struct ComponentInfo {
37
37
  string name;
38
38
  bool isDefault;
39
-
39
+
40
40
  /****************/
41
41
  /****************/
42
-
42
+
43
43
  ComponentInfo() {
44
44
  isDefault = false;
45
45
  /******************/
@@ -46,12 +46,12 @@ private:
46
46
  pthread_t thr;
47
47
  pthread_attr_t attr;
48
48
  size_t stack_size = 96 * 1024;
49
-
49
+
50
50
  unsigned long min_stack_size;
51
51
  bool stack_min_size_defined;
52
52
  bool round_stack_size;
53
53
  int ret;
54
-
54
+
55
55
  #ifdef PTHREAD_STACK_MIN
56
56
  // PTHREAD_STACK_MIN may not be a constant macro so we need
57
57
  // to evaluate it dynamically.
@@ -68,7 +68,7 @@ private:
68
68
  } else {
69
69
  round_stack_size = true;
70
70
  }
71
-
71
+
72
72
  if (round_stack_size) {
73
73
  // Round stack size up to page boundary.
74
74
  long page_size;
@@ -87,7 +87,7 @@ private:
87
87
  stack_size = stack_size - (stack_size % page_size) + page_size;
88
88
  }
89
89
  }
90
-
90
+
91
91
  pthread_attr_init(&attr);
92
92
  pthread_attr_setdetachstate(&attr, 1);
93
93
  pthread_attr_setstacksize(&attr, stack_size);
@@ -95,25 +95,25 @@ private:
95
95
  pthread_attr_destroy(&attr);
96
96
  return ret;
97
97
  }
98
-
98
+
99
99
  static void *detachProcessMain(void *arg) {
100
100
  this_thread::disable_syscall_interruption dsi;
101
101
  pid_t pid = (pid_t) (long) arg;
102
102
  syscalls::waitpid(pid, NULL, 0);
103
103
  return NULL;
104
104
  }
105
-
105
+
106
106
  void detachProcess(pid_t pid) {
107
107
  startBackgroundThread(detachProcessMain, (void *) (long) pid);
108
108
  }
109
-
109
+
110
110
  vector<string> createCommand(const Options &options, const SpawnPreparationInfo &preparation,
111
111
  shared_array<const char *> &args) const
112
112
  {
113
113
  vector<string> startCommandArgs;
114
114
  string agentsDir = config->resourceLocator.getAgentsDir();
115
115
  vector<string> command;
116
-
116
+
117
117
  split(options.getStartCommand(config->resourceLocator), '\t', startCommandArgs);
118
118
  if (startCommandArgs.empty()) {
119
119
  throw RuntimeException("No startCommand given");
@@ -138,11 +138,11 @@ private:
138
138
  for (unsigned int i = 1; i < startCommandArgs.size(); i++) {
139
139
  command.push_back(startCommandArgs[i]);
140
140
  }
141
-
141
+
142
142
  createCommandArgs(command, args);
143
143
  return command;
144
144
  }
145
-
145
+
146
146
  public:
147
147
  DirectSpawner(const ServerInstanceDir::GenerationPtr &_generation,
148
148
  const SpawnerConfigPtr &_config)
@@ -150,7 +150,7 @@ public:
150
150
  {
151
151
  generation = _generation;
152
152
  }
153
-
153
+
154
154
  virtual ProcessPtr spawn(const Options &options) {
155
155
  TRACE_POINT();
156
156
  this_thread::disable_interruption di;
@@ -165,7 +165,7 @@ public:
165
165
  Pipe errorPipe = createPipe();
166
166
  DebugDirPtr debugDir = boost::make_shared<DebugDir>(preparation.uid, preparation.gid);
167
167
  pid_t pid;
168
-
168
+
169
169
  pid = syscalls::fork();
170
170
  if (pid == 0) {
171
171
  setenv("PASSENGER_DEBUG_DIR", debugDir->getPath().c_str(), 1);
@@ -183,7 +183,7 @@ public:
183
183
  switchUser(preparation);
184
184
  setWorkingDirectory(preparation);
185
185
  execvp(args[0], (char * const *) args.get());
186
-
186
+
187
187
  int e = errno;
188
188
  printf("!> Error\n");
189
189
  printf("!> \n");
@@ -194,18 +194,18 @@ public:
194
194
  fflush(stdout);
195
195
  fflush(stderr);
196
196
  _exit(1);
197
-
197
+
198
198
  } else if (pid == -1) {
199
199
  int e = errno;
200
200
  throw SystemException("Cannot fork a new process", e);
201
-
201
+
202
202
  } else {
203
203
  UPDATE_TRACE_POINT();
204
204
  ScopeGuard guard(boost::bind(nonInterruptableKillAndWaitpid, pid));
205
205
  P_DEBUG("Process forked for appRoot=" << options.appRoot << ": PID " << pid);
206
206
  adminSocket.first.close();
207
207
  errorPipe.second.close();
208
-
208
+
209
209
  NegotiationDetails details;
210
210
  details.preparation = &preparation;
211
211
  details.stderrCapturer =
@@ -221,7 +221,7 @@ public:
221
221
  details.errorPipe = errorPipe.first;
222
222
  details.options = &options;
223
223
  details.debugDir = debugDir;
224
-
224
+
225
225
  ProcessPtr process;
226
226
  {
227
227
  this_thread::restore_interruption ri(di);
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2013 Phusion
3
+ * Copyright (c) 2011-2014 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -39,17 +39,17 @@ class DummySpawner: public Spawner {
39
39
  private:
40
40
  boost::mutex lock;
41
41
  unsigned int count;
42
-
42
+
43
43
  public:
44
44
  unsigned int cleanCount;
45
-
45
+
46
46
  DummySpawner(const SpawnerConfigPtr &_config)
47
47
  : Spawner(_config)
48
48
  {
49
49
  count = 0;
50
50
  cleanCount = 0;
51
51
  }
52
-
52
+
53
53
  virtual ProcessPtr spawn(const Options &options) {
54
54
  TRACE_POINT();
55
55
  possiblyRaiseInternalError(options);
@@ -58,7 +58,7 @@ public:
58
58
  SocketListPtr sockets = boost::make_shared<SocketList>();
59
59
  sockets->add("main", "tcp://127.0.0.1:1234", "session", config->concurrency);
60
60
  syscalls::usleep(config->spawnTime);
61
-
61
+
62
62
  boost::lock_guard<boost::mutex> l(lock);
63
63
  count++;
64
64
  ProcessPtr process = boost::make_shared<Process>(
@@ -67,16 +67,16 @@ class Group: public boost::enable_shared_from_this<Group> {
67
67
  public:
68
68
  friend class Pool;
69
69
  friend class SuperGroup;
70
-
70
+
71
71
  struct GetAction {
72
72
  GetCallback callback;
73
73
  SessionPtr session;
74
74
  };
75
-
75
+
76
76
  struct DisableWaiter {
77
77
  ProcessPtr process;
78
78
  DisableCallback callback;
79
-
79
+
80
80
  DisableWaiter(const ProcessPtr &_process, const DisableCallback &_callback)
81
81
  : process(_process),
82
82
  callback(_callback)
@@ -92,7 +92,7 @@ public:
92
92
  finished(_finished)
93
93
  { }
94
94
  };
95
-
95
+
96
96
  /**
97
97
  * Protects `lifeStatus`.
98
98
  */
@@ -102,7 +102,7 @@ public:
102
102
  *
103
103
  * Do not access directly, always use `isAlive()`/`getLifeStatus()` or
104
104
  * through `lifetimeSyncher`.
105
- *
105
+ *
106
106
  * Invariant:
107
107
  * if lifeStatus != ALIVE:
108
108
  * enabledCount == 0
@@ -181,8 +181,8 @@ public:
181
181
  boost::condition_variable detachedProcessesCheckerCond;
182
182
  Callback shutdownCallback;
183
183
  GroupPtr selfPointer;
184
-
185
-
184
+
185
+
186
186
  static void _onSessionInitiateFailure(Session *session) {
187
187
  ProcessPtr process = session->getProcess();
188
188
  assert(process != NULL);
@@ -194,8 +194,9 @@ public:
194
194
  assert(process != NULL);
195
195
  process->getGroup()->onSessionClose(process, session);
196
196
  }
197
-
197
+
198
198
  static string generateSecret(const SuperGroupPtr &superGroup);
199
+ static string generateUuid(const SuperGroupPtr &superGroup);
199
200
  void onSessionInitiateFailure(const ProcessPtr &process, Session *session);
200
201
  void onSessionClose(const ProcessPtr &process, Session *session);
201
202
 
@@ -231,7 +232,7 @@ public:
231
232
 
232
233
  void verifyInvariants() const {
233
234
  // !a || b: logical equivalent of a IMPLIES b.
234
-
235
+
235
236
  assert(enabledCount >= 0);
236
237
  assert(disablingCount >= 0);
237
238
  assert(disabledCount >= 0);
@@ -245,7 +246,7 @@ public:
245
246
  assert(!( !getWaitlist.empty() ) || ( enabledProcesses.empty() || verifyNoRequestsOnGetWaitlistAreRoutable() ));
246
247
  assert(!( enabledProcesses.empty() && !m_spawning && !restarting() && !poolAtFullCapacity() ) || ( getWaitlist.empty() ));
247
248
  assert(!( !getWaitlist.empty() ) || ( !enabledProcesses.empty() || m_spawning || restarting() || poolAtFullCapacity() ));
248
-
249
+
249
250
  // Verify disableWaitlist invariants.
250
251
  assert((int) disableWaitlist.size() >= disablingCount);
251
252
 
@@ -319,7 +320,7 @@ public:
319
320
  return true;
320
321
  }
321
322
  #endif
322
-
323
+
323
324
  /**
324
325
  * Sets options for this Group. Called at creation time and at restart time.
325
326
  */
@@ -328,8 +329,9 @@ public:
328
329
  options.persist(newOptions);
329
330
  options.clearPerRequestFields();
330
331
  options.groupSecret = secret;
332
+ options.groupUuid = uuid;
331
333
  }
332
-
334
+
333
335
  /**
334
336
  * Merges some of the new options from the latest get() request into this Group.
335
337
  */
@@ -339,7 +341,7 @@ public:
339
341
  options.statThrottleRate = other.statThrottleRate;
340
342
  options.maxPreloaderIdleTime = other.maxPreloaderIdleTime;
341
343
  }
342
-
344
+
343
345
  static void runAllActions(const vector<Callback> &actions) {
344
346
  vector<Callback>::const_iterator it, end = actions.end();
345
347
  for (it = actions.begin(); it != end; it++) {
@@ -556,7 +558,7 @@ public:
556
558
  it->callback(it->session, ExceptionPtr());
557
559
  }
558
560
  }
559
-
561
+
560
562
  void assignSessionsToGetWaiters(vector<Callback> &postLockActions) {
561
563
  unsigned int i = 0;
562
564
  bool done = false;
@@ -596,7 +598,7 @@ public:
596
598
  }
597
599
  clearDisableWaitlist(DR_ERROR, postLockActions);
598
600
  }
599
-
601
+
600
602
  void removeFromDisableWaitlist(const ProcessPtr &p, DisableResult result,
601
603
  vector<Callback> &postLockActions)
602
604
  {
@@ -657,7 +659,7 @@ public:
657
659
  }
658
660
  selfPointer.reset();
659
661
  }
660
-
662
+
661
663
  public:
662
664
  Options options;
663
665
  /** This name uniquely identifies this Group within its Pool. It can also be used as the display name. */
@@ -666,8 +668,13 @@ public:
666
668
  * intra-group process communication.
667
669
  */
668
670
  const string secret;
671
+ /** A UUID that's generated on Group initialization, and changes every time
672
+ * the Group receives a restart command. Allows Union Station to track app
673
+ * restarts. This information is public.
674
+ */
675
+ string uuid;
669
676
  ComponentInfo componentInfo;
670
-
677
+
671
678
  /**
672
679
  * Processes are categorized as enabled, disabling or disabled.
673
680
  *
@@ -743,35 +750,35 @@ public:
743
750
  * process.pqHandle == NULL
744
751
  */
745
752
  ProcessList detachedProcesses;
746
-
753
+
747
754
  /**
748
755
  * get() requests for this group that cannot be immediately satisfied are
749
756
  * put on this wait list, which must be processed as soon as the necessary
750
757
  * resources have become free.
751
- *
758
+ *
752
759
  * ### Invariant 1 (safety)
753
- *
760
+ *
754
761
  * If requests are queued in the getWaitlist, then that's because there are
755
762
  * no processes that can serve them.
756
- *
763
+ *
757
764
  * if getWaitlist is non-empty:
758
765
  * enabledProcesses.empty() || (no request in getWaitlist is routeable)
759
766
  *
760
767
  * Here, "routeable" is defined as `route(options).process != NULL`.
761
- *
768
+ *
762
769
  * ### Invariant 2 (progress)
763
770
  *
764
771
  * The only reason why there are no enabled processes, while at the same time we're
765
772
  * not spawning or waiting for pool capacity, is because there is nothing to do.
766
- *
773
+ *
767
774
  * if enabledProcesses.empty() && !m_spawning && !restarting() && !poolAtFullCapacity():
768
775
  * getWaitlist is empty
769
- *
776
+ *
770
777
  * Equivalently:
771
778
  * If requests are queued in the getWaitlist, then either we have processes that can process
772
779
  * them (some time in the future), or we're actively trying to spawn processes, unless we're
773
780
  * unable to do that because of resource limits.
774
- *
781
+ *
775
782
  * if getWaitlist is non-empty:
776
783
  * !enabledProcesses.empty() || m_spawning || restarting() || poolAtFullCapacity()
777
784
  */
@@ -785,7 +792,7 @@ public:
785
792
  * disableWaitlist.size() >= disablingCount
786
793
  */
787
794
  deque<DisableWaiter> disableWaitlist;
788
-
795
+
789
796
  /**
790
797
  * Invariant:
791
798
  * (lifeStatus == ALIVE) == (spawner != NULL)
@@ -840,19 +847,19 @@ public:
840
847
  SuperGroupPtr getSuperGroup() const {
841
848
  return superGroup.lock();
842
849
  }
843
-
850
+
844
851
  void setSuperGroup(const SuperGroupPtr &superGroup) {
845
852
  assert(this->superGroup.lock() == NULL);
846
853
  this->superGroup = superGroup;
847
854
  }
848
-
855
+
849
856
  /**
850
857
  * Thread-safe.
851
858
  * @pre getLifeState() != SHUT_DOWN
852
859
  * @post result != NULL
853
860
  */
854
861
  PoolPtr getPool() const;
855
-
862
+
856
863
  // Thread-safe.
857
864
  bool isAlive() const {
858
865
  boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
@@ -900,7 +907,7 @@ public:
900
907
  }
901
908
  }
902
909
  }
903
-
910
+
904
911
  if (OXT_UNLIKELY(newOptions.noop)) {
905
912
  ProcessPtr process = boost::make_shared<Process>(
906
913
  0, string(), string(),
@@ -911,7 +918,7 @@ public:
911
918
  process->setGroup(shared_from_this());
912
919
  return boost::make_shared<Session>(process, (Socket *) NULL);
913
920
  }
914
-
921
+
915
922
  if (OXT_UNLIKELY(enabledCount == 0)) {
916
923
  /* We don't have any processes yet, but they're on the way.
917
924
  *
@@ -972,6 +979,7 @@ public:
972
979
  * afterwards if necessary, e.g. by calling `assignSessionsToGetWaiters()`.
973
980
  */
974
981
  AttachResult attach(const ProcessPtr &process, vector<Callback> &postLockActions) {
982
+ TRACE_POINT();
975
983
  assert(process->getGroup() == NULL || process->getGroup().get() == this);
976
984
  assert(process->isAlive());
977
985
  assert(isAlive());
@@ -1032,10 +1040,16 @@ public:
1032
1040
  * that method over this one.
1033
1041
  */
1034
1042
  void detach(const ProcessPtr &process, vector<Callback> &postLockActions) {
1043
+ TRACE_POINT();
1035
1044
  assert(process->getGroup().get() == this);
1036
1045
  assert(process->isAlive());
1037
1046
  assert(isAlive());
1038
1047
 
1048
+ if (process->enabled == Process::DETACHED) {
1049
+ P_DEBUG("Detaching process " << process->inspect() << ", which was already being detached");
1050
+ return;
1051
+ }
1052
+
1039
1053
  const ProcessPtr p = process; // Keep an extra reference just in case.
1040
1054
  P_DEBUG("Detaching process " << process->inspect());
1041
1055
 
@@ -1048,6 +1062,7 @@ public:
1048
1062
  removeFromDisableWaitlist(process, DR_NOOP, postLockActions);
1049
1063
  }
1050
1064
  } else {
1065
+ assert(process->enabled == Process::DISABLED);
1051
1066
  assert(!disabledProcesses.empty());
1052
1067
  removeProcessFromList(process, disabledProcesses);
1053
1068
  }
@@ -1057,7 +1072,7 @@ public:
1057
1072
 
1058
1073
  postLockActions.push_back(boost::bind(&Group::runDetachHooks, this, process));
1059
1074
  }
1060
-
1075
+
1061
1076
  /**
1062
1077
  * Detaches all processes from this Group. This function doesn't touch
1063
1078
  * getWaitlist so be sure to fix its invariants afterwards if necessary.
@@ -1076,7 +1091,7 @@ public:
1076
1091
  foreach (ProcessPtr process, disabledProcesses) {
1077
1092
  addProcessToList(process, detachedProcesses);
1078
1093
  }
1079
-
1094
+
1080
1095
  enabledProcesses.clear();
1081
1096
  disablingProcesses.clear();
1082
1097
  disabledProcesses.clear();
@@ -1087,7 +1102,7 @@ public:
1087
1102
  clearDisableWaitlist(DR_NOOP, postLockActions);
1088
1103
  startCheckingDetachedProcesses(false);
1089
1104
  }
1090
-
1105
+
1091
1106
  /**
1092
1107
  * Marks the given process as enabled. This function doesn't touch getWaitlist
1093
1108
  * so be sure to fix its invariants afterwards if necessary.
@@ -1110,7 +1125,7 @@ public:
1110
1125
  P_DEBUG("Enabling ENABLED process " << process->inspect());
1111
1126
  }
1112
1127
  }
1113
-
1128
+
1114
1129
  /**
1115
1130
  * Marks the given process as disabled. Returns DR_SUCCESS, DR_DEFERRED
1116
1131
  * or DR_NOOP. If the result is DR_DEFERRED, then the callback will be
@@ -1271,7 +1286,7 @@ public:
1271
1286
  (unsigned long long) options.getMaxPreloaderIdleTime() * 1000000; */
1272
1287
  return false;
1273
1288
  }
1274
-
1289
+
1275
1290
  /** Whether a new process should be spawned for this group. */
1276
1291
  bool shouldSpawn() const;
1277
1292
  /** Whether a new process should be spawned for this group in the
@@ -1288,7 +1303,7 @@ public:
1288
1303
  && !processUpperLimitsReached()
1289
1304
  && !poolAtFullCapacity();
1290
1305
  }
1291
-
1306
+
1292
1307
  bool needsRestart(const Options &options) {
1293
1308
  if (m_restarting) {
1294
1309
  return false;
@@ -1316,6 +1331,7 @@ public:
1316
1331
  stream << "<app_root>" << escapeForXml(options.appRoot) << "</app_root>";
1317
1332
  stream << "<app_type>" << escapeForXml(options.appType) << "</app_type>";
1318
1333
  stream << "<environment>" << escapeForXml(options.environment) << "</environment>";
1334
+ stream << "<uuid>" << toString(uuid) << "</uuid>";
1319
1335
  stream << "<enabled_process_count>" << enabledCount << "</enabled_process_count>";
1320
1336
  stream << "<disabling_process_count>" << disablingCount << "</disabling_process_count>";
1321
1337
  stream << "<disabled_process_count>" << disabledCount << "</disabled_process_count>";
@@ -1351,7 +1367,7 @@ public:
1351
1367
  stream << "</options>";
1352
1368
 
1353
1369
  stream << "<processes>";
1354
-
1370
+
1355
1371
  for (it = enabledProcesses.begin(); it != enabledProcesses.end(); it++) {
1356
1372
  stream << "<process>";
1357
1373
  (*it)->inspectXml(stream, includeSecrets);