passenger 4.0.5 → 4.0.6

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 (162) hide show
  1. data.tar.gz.asc +7 -7
  2. data/.travis.yml +1 -2
  3. data/CONTRIBUTING.md +20 -5
  4. data/CONTRIBUTORS +67 -0
  5. data/LICENSE +1 -1
  6. data/NEWS +48 -0
  7. data/Rakefile +2 -2
  8. data/bin/passenger-config +18 -0
  9. data/bin/passenger-install-apache2-module +2 -0
  10. data/bin/passenger-install-nginx-module +11 -12
  11. data/bin/passenger-memory-stats +2 -0
  12. data/bin/passenger-status +152 -69
  13. data/build/agents.rb +1 -5
  14. data/build/basics.rb +26 -13
  15. data/build/cplusplus_support.rb +9 -0
  16. data/build/debian.rb +129 -0
  17. data/build/documentation.rb +6 -2
  18. data/build/integration_tests.rb +13 -2
  19. data/build/misc.rb +16 -0
  20. data/build/packaging.rb +67 -51
  21. data/build/preprocessor.rb +314 -0
  22. data/build/test_basics.rb +1 -0
  23. data/{debian → debian.template}/README.Debian +0 -0
  24. data/{debian → debian.template}/changelog +131 -0
  25. data/debian.template/compat +1 -0
  26. data/debian.template/control +71 -0
  27. data/debian.template/copyright +385 -0
  28. data/debian.template/libapache2-mod-passenger.install +3 -0
  29. data/{debian → debian.template}/libapache2-mod-passenger.postinst +0 -0
  30. data/{debian → debian.template}/libapache2-mod-passenger.prerm +0 -0
  31. data/debian.template/locations.ini +12 -0
  32. data/debian.template/passenger.conf +4 -0
  33. data/{debian → debian.template}/passenger.load +0 -0
  34. data/debian.template/patches/series +0 -0
  35. data/debian.template/repack.sh +42 -0
  36. data/debian.template/ruby-passenger-dev.install +3 -0
  37. data/debian.template/ruby-passenger-doc.install +2 -0
  38. data/debian.template/ruby-passenger.docs +4 -0
  39. data/debian.template/ruby-passenger.install +11 -0
  40. data/debian.template/ruby-passenger.manpages +4 -0
  41. data/debian.template/rules.template +35 -0
  42. data/debian.template/source/format +1 -0
  43. data/debian.template/watch +3 -0
  44. data/dev/run_travis.sh +46 -46
  45. data/doc/Architectural overview.html +2 -2
  46. data/doc/Packaging.html +27 -18
  47. data/doc/Packaging.txt.md +27 -18
  48. data/doc/Security of user switching support.html +2 -2
  49. data/doc/Users guide Apache.html +881 -95
  50. data/doc/Users guide Apache.idmap.txt +48 -6
  51. data/doc/Users guide Apache.txt +13 -1
  52. data/doc/Users guide Nginx.html +1063 -190
  53. data/doc/Users guide Nginx.idmap.txt +89 -45
  54. data/doc/Users guide Nginx.txt +45 -0
  55. data/doc/Users guide Standalone.html +7 -7
  56. data/doc/users_guide_snippets/alternative_for_flying_passenger.txt +1 -0
  57. data/doc/users_guide_snippets/environment_variables.txt +221 -0
  58. data/doc/users_guide_snippets/installation.txt +66 -17
  59. data/doc/users_guide_snippets/support_information.txt +3 -3
  60. data/doc/users_guide_snippets/tips.txt +352 -40
  61. data/ext/common/Account.h +4 -3
  62. data/ext/common/AccountsDatabase.h +6 -6
  63. data/ext/common/AgentsStarter.h +1 -13
  64. data/ext/common/ApplicationPool2/DirectSpawner.h +4 -4
  65. data/ext/common/ApplicationPool2/DummySpawner.h +1 -1
  66. data/ext/common/ApplicationPool2/Group.h +9 -4
  67. data/ext/common/ApplicationPool2/Implementation.cpp +6 -1
  68. data/ext/common/ApplicationPool2/Options.h +65 -37
  69. data/ext/common/ApplicationPool2/Pool.h +91 -41
  70. data/ext/common/ApplicationPool2/Process.h +6 -6
  71. data/ext/common/ApplicationPool2/SmartSpawner.h +14 -14
  72. data/ext/common/ApplicationPool2/Socket.h +1 -1
  73. data/ext/common/ApplicationPool2/Spawner.h +24 -16
  74. data/ext/common/ApplicationPool2/SpawnerFactory.h +9 -1
  75. data/ext/common/ApplicationPool2/SuperGroup.h +1 -1
  76. data/ext/common/Constants.h +1 -1
  77. data/ext/common/Logging.cpp +12 -7
  78. data/ext/common/MessageServer.h +7 -12
  79. data/ext/common/MultiLibeio.cpp +5 -5
  80. data/ext/common/ResourceLocator.h +2 -6
  81. data/ext/common/ServerInstanceDir.h +37 -10
  82. data/ext/common/UnionStation.h +10 -10
  83. data/ext/common/Utils.cpp +30 -4
  84. data/ext/common/Utils.h +7 -0
  85. data/ext/common/Utils/BlockingQueue.h +2 -2
  86. data/ext/common/Utils/Lock.h +2 -2
  87. data/ext/common/Utils/MessagePassing.h +2 -2
  88. data/ext/common/Utils/Timer.h +4 -4
  89. data/ext/common/agents/HelperAgent/AgentOptions.h +2 -0
  90. data/ext/common/agents/HelperAgent/Main.cpp +57 -16
  91. data/ext/common/agents/HelperAgent/RequestHandler.h +4 -1
  92. data/ext/common/agents/LoggingAgent/AdminController.h +91 -0
  93. data/ext/common/agents/LoggingAgent/LoggingServer.h +46 -29
  94. data/ext/common/agents/LoggingAgent/Main.cpp +43 -16
  95. data/ext/common/agents/LoggingAgent/RemoteSender.h +7 -7
  96. data/ext/common/agents/Watchdog/AgentWatcher.cpp +11 -11
  97. data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +3 -1
  98. data/ext/common/agents/Watchdog/Main.cpp +62 -0
  99. data/ext/libeio/config.guess +206 -167
  100. data/ext/libeio/config.sub +142 -68
  101. data/ext/libev/config.guess +304 -290
  102. data/ext/libev/config.sub +198 -77
  103. data/ext/nginx/config +4 -0
  104. data/ext/nginx/ngx_http_passenger_module.c +1 -0
  105. data/ext/oxt/implementation.cpp +4 -4
  106. data/lib/phusion_passenger.rb +14 -5
  107. data/lib/phusion_passenger/abstract_installer.rb +41 -0
  108. data/lib/phusion_passenger/admin_tools/server_instance.rb +48 -39
  109. data/lib/phusion_passenger/message_client.rb +31 -7
  110. data/lib/phusion_passenger/native_support.rb +35 -12
  111. data/lib/phusion_passenger/packaging.rb +16 -2
  112. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +6 -31
  113. data/lib/phusion_passenger/platform_info/operating_system.rb +1 -1
  114. data/lib/phusion_passenger/preloader_shared_helpers.rb +3 -1
  115. data/lib/phusion_passenger/request_handler.rb +1 -1
  116. data/lib/phusion_passenger/standalone/command.rb +6 -6
  117. data/lib/phusion_passenger/standalone/main.rb +23 -8
  118. data/lib/phusion_passenger/standalone/package_runtime_command.rb +9 -5
  119. data/lib/phusion_passenger/standalone/runtime_installer.rb +9 -10
  120. data/lib/phusion_passenger/standalone/start_command.rb +20 -4
  121. data/resources/templates/installer_common/freebsd9_broken_cxx_runtime.txt.erb +19 -0
  122. data/resources/templates/installer_common/low_amount_of_memory_warning.txt.erb +22 -0
  123. data/resources/templates/standalone/config.erb +3 -2
  124. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +4 -4
  125. data/test/cxx/ApplicationPool2/PoolTest.cpp +1 -1
  126. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +7 -7
  127. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +9 -9
  128. data/test/cxx/EventedBufferedInputTest.cpp +17 -17
  129. data/test/cxx/RequestHandlerTest.cpp +5 -5
  130. data/test/cxx/ServerInstanceDirTest.cpp +3 -1
  131. data/test/cxx/TestSupport.h +4 -4
  132. data/test/cxx/UnionStationTest.cpp +3 -1
  133. data/test/cxx/UtilsTest.cpp +2 -0
  134. data/test/integration_tests/apache2_tests.rb +2 -2
  135. data/test/integration_tests/native_packaging_spec.rb +170 -0
  136. data/test/ruby/spec_helper.rb +0 -1
  137. data/test/stub/apache2/httpd.conf.erb +1 -1
  138. data/test/stub/nginx/nginx.conf.erb +1 -0
  139. data/test/support/apache2_controller.rb +1 -1
  140. data/test/support/placebo-preloader.rb +1 -1
  141. data/test/support/test_helper.rb +5 -2
  142. metadata +32 -26
  143. metadata.gz.asc +7 -7
  144. data/debian/compat +0 -1
  145. data/debian/control +0 -49
  146. data/debian/copyright +0 -20
  147. data/debian/libapache2-mod-passenger.install +0 -1
  148. data/debian/passenger-common.install +0 -4
  149. data/debian/passenger.conf +0 -4
  150. data/debian/prerm +0 -2
  151. data/debian/rules +0 -37
  152. data/debian/watch +0 -3
  153. data/dev/googlecode_upload.py +0 -265
  154. data/ext/common/agents/HelperAgent/BacktracesServer.h +0 -60
  155. data/resources/templates/nginx/not_available_when_natively_packaged.txt.erb +0 -8
  156. data/test/stub/rails3.1/app/assets/javascripts/application.js +0 -9
  157. data/test/stub/rails3.2/app/assets/javascripts/application.js +0 -15
  158. data/test/stub/rails_apps/2.3/mycook/public/javascripts/application.js +0 -2
  159. data/test/stub/rails_apps/2.3/mycook/public/javascripts/controls.js +0 -963
  160. data/test/stub/rails_apps/2.3/mycook/public/javascripts/dragdrop.js +0 -973
  161. data/test/stub/rails_apps/2.3/mycook/public/javascripts/effects.js +0 -1128
  162. data/test/stub/rails_apps/2.3/mycook/public/javascripts/prototype.js +0 -4320
@@ -384,25 +384,25 @@ public:
384
384
 
385
385
  // Thread-safe.
386
386
  bool isAlive() const {
387
- lock_guard<boost::mutex> lock(lifetimeSyncher);
387
+ boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
388
388
  return lifeStatus == ALIVE;
389
389
  }
390
390
 
391
391
  // Thread-safe.
392
392
  bool hasTriggeredShutdown() const {
393
- lock_guard<boost::mutex> lock(lifetimeSyncher);
393
+ boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
394
394
  return lifeStatus == SHUTDOWN_TRIGGERED;
395
395
  }
396
396
 
397
397
  // Thread-safe.
398
398
  bool isDead() const {
399
- lock_guard<boost::mutex> lock(lifetimeSyncher);
399
+ boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
400
400
  return lifeStatus == DEAD;
401
401
  }
402
402
 
403
403
  // Thread-safe.
404
404
  LifeStatus getLifeStatus() const {
405
- lock_guard<boost::mutex> lock(lifetimeSyncher);
405
+ boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
406
406
  return lifeStatus;
407
407
  }
408
408
 
@@ -413,7 +413,7 @@ public:
413
413
  void triggerShutdown() {
414
414
  assert(canTriggerShutdown());
415
415
  {
416
- lock_guard<boost::mutex> lock(lifetimeSyncher);
416
+ boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
417
417
  assert(lifeStatus == ALIVE);
418
418
  lifeStatus = SHUTDOWN_TRIGGERED;
419
419
  shutdownStartTime = SystemTime::get();
@@ -447,7 +447,7 @@ public:
447
447
  }
448
448
  }
449
449
 
450
- lock_guard<boost::mutex> lock(lifetimeSyncher);
450
+ boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
451
451
  lifeStatus = DEAD;
452
452
  }
453
453
 
@@ -110,9 +110,9 @@ private:
110
110
  string agentsDir = resourceLocator.getAgentsDir();
111
111
  vector<string> command;
112
112
 
113
- if (options.loadShellEnvvars) {
114
- command.push_back("bash");
115
- command.push_back("bash");
113
+ if (shouldLoadShellEnvvars(options, preparation)) {
114
+ command.push_back(preparation.shell);
115
+ command.push_back(preparation.shell);
116
116
  command.push_back("-lc");
117
117
  command.push_back("exec \"$@\"");
118
118
  command.push_back("SpawnPreparerShell");
@@ -279,7 +279,7 @@ private:
279
279
  }
280
280
  this->adminSocket = adminSocket.second;
281
281
  {
282
- lock_guard<boost::mutex> l(simpleFieldSyncher);
282
+ boost::lock_guard<boost::mutex> l(simpleFieldSyncher);
283
283
  this->pid = pid;
284
284
  }
285
285
 
@@ -324,7 +324,7 @@ private:
324
324
  syscalls::unlink(filename.c_str());
325
325
  }
326
326
  {
327
- lock_guard<boost::mutex> l(simpleFieldSyncher);
327
+ boost::lock_guard<boost::mutex> l(simpleFieldSyncher);
328
328
  pid = -1;
329
329
  }
330
330
  socketAddress.clear();
@@ -342,7 +342,7 @@ private:
342
342
 
343
343
  vector<string> args;
344
344
  vector<string>::const_iterator it, end;
345
- details.options->toVector(args, resourceLocator);
345
+ details.options->toVector(args, resourceLocator, Options::SPAWN_OPTIONS);
346
346
  for (it = args.begin(); it != args.end(); it++) {
347
347
  const string &key = *it;
348
348
  it++;
@@ -615,7 +615,7 @@ private:
615
615
  vector<string>::const_iterator it;
616
616
 
617
617
  writeExact(fd, "spawn\n", &timeout);
618
- options.toVector(args, resourceLocator);
618
+ options.toVector(args, resourceLocator, Options::SPAWN_OPTIONS);
619
619
  for (it = args.begin(); it != args.end(); it++) {
620
620
  const string &key = *it;
621
621
  it++;
@@ -722,7 +722,7 @@ public:
722
722
  }
723
723
 
724
724
  virtual ~SmartSpawner() {
725
- lock_guard<boost::mutex> l(syncher);
725
+ boost::lock_guard<boost::mutex> l(syncher);
726
726
  stopPreloader();
727
727
  }
728
728
 
@@ -735,11 +735,11 @@ public:
735
735
  possiblyRaiseInternalError(options);
736
736
 
737
737
  {
738
- lock_guard<boost::mutex> l(simpleFieldSyncher);
738
+ boost::lock_guard<boost::mutex> l(simpleFieldSyncher);
739
739
  m_lastUsed = SystemTime::getUsec();
740
740
  }
741
741
  UPDATE_TRACE_POINT();
742
- lock_guard<boost::mutex> l(syncher);
742
+ boost::lock_guard<boost::mutex> l(syncher);
743
743
  if (!preloaderStarted()) {
744
744
  UPDATE_TRACE_POINT();
745
745
  startPreloader();
@@ -779,20 +779,20 @@ public:
779
779
  virtual void cleanup() {
780
780
  TRACE_POINT();
781
781
  {
782
- lock_guard<boost::mutex> l(simpleFieldSyncher);
782
+ boost::lock_guard<boost::mutex> l(simpleFieldSyncher);
783
783
  m_lastUsed = SystemTime::getUsec();
784
784
  }
785
- lock_guard<boost::mutex> lock(syncher);
785
+ boost::lock_guard<boost::mutex> lock(syncher);
786
786
  stopPreloader();
787
787
  }
788
788
 
789
789
  virtual unsigned long long lastUsed() const {
790
- lock_guard<boost::mutex> lock(simpleFieldSyncher);
790
+ boost::lock_guard<boost::mutex> lock(simpleFieldSyncher);
791
791
  return m_lastUsed;
792
792
  }
793
793
 
794
794
  pid_t getPreloaderPid() const {
795
- lock_guard<boost::mutex> lock(simpleFieldSyncher);
795
+ boost::lock_guard<boost::mutex> lock(simpleFieldSyncher);
796
796
  return pid;
797
797
  }
798
798
  };
@@ -145,7 +145,7 @@ public:
145
145
  * Failure to do so will result in a resource leak.
146
146
  */
147
147
  Connection checkoutConnection() {
148
- lock_guard<boost::mutex> l(connectionPoolLock);
148
+ boost::lock_guard<boost::mutex> l(connectionPoolLock);
149
149
 
150
150
  if (!idleConnections.empty()) {
151
151
  Connection connection = idleConnections.back();
@@ -143,7 +143,7 @@ protected:
143
143
  }
144
144
  } else {
145
145
  {
146
- lock_guard<boost::mutex> l(dataSyncher);
146
+ boost::lock_guard<boost::mutex> l(dataSyncher);
147
147
  data.append(buf, ret);
148
148
  }
149
149
  UPDATE_TRACE_POINT();
@@ -200,13 +200,13 @@ protected:
200
200
  thr->interrupt_and_join();
201
201
  delete thr;
202
202
  thr = NULL;
203
- lock_guard<boost::mutex> l(dataSyncher);
203
+ boost::lock_guard<boost::mutex> l(dataSyncher);
204
204
  return data;
205
205
  }
206
206
 
207
207
  void appendToBuffer(const StaticString &dataToAdd) {
208
208
  TRACE_POINT();
209
- lock_guard<boost::mutex> l(dataSyncher);
209
+ boost::lock_guard<boost::mutex> l(dataSyncher);
210
210
  data.append(dataToAdd.data(), dataToAdd.size());
211
211
  }
212
212
  };
@@ -222,19 +222,18 @@ protected:
222
222
  string path;
223
223
 
224
224
  DebugDir(uid_t uid, gid_t gid) {
225
- path = "/tmp/passenger.spawn-debug.";
226
- path.append(toString(getpid()));
227
- path.append("-");
228
- path.append(pointerToIntString(this));
229
-
230
- if (syscalls::mkdir(path.c_str(), 0700) == -1) {
225
+ char buf[PATH_MAX] = "/tmp/passenger.spawn-debug.XXXXXXXXXX";
226
+ const char *result = mkdtemp(buf);
227
+ if (result == NULL) {
231
228
  int e = errno;
232
- throw FileSystemException("Cannot create directory '" +
233
- path + "'", e, path);
229
+ throw SystemException("Cannot create a temporary directory "
230
+ "in the format of '/tmp/passenger-spawn-debug.XXX'", e);
231
+ } else {
232
+ path = result;
233
+ this_thread::disable_interruption di;
234
+ this_thread::disable_syscall_interruption dsi;
235
+ syscalls::chown(result, uid, gid);
234
236
  }
235
- this_thread::disable_interruption di;
236
- this_thread::disable_syscall_interruption dsi;
237
- syscalls::chown(path.c_str(), uid, gid);
238
237
  }
239
238
 
240
239
  ~DebugDir() {
@@ -391,7 +390,7 @@ private:
391
390
 
392
391
  vector<string> args;
393
392
  vector<string>::const_iterator it, end;
394
- details.options->toVector(args, resourceLocator);
393
+ details.options->toVector(args, resourceLocator, Options::SPAWN_OPTIONS);
395
394
  for (it = args.begin(); it != args.end(); it++) {
396
395
  const string &key = *it;
397
396
  it++;
@@ -740,7 +739,7 @@ protected:
740
739
  }
741
740
  }
742
741
  }
743
-
742
+
744
743
  SpawnPreparationInfo prepareSpawn(const Options &options) const {
745
744
  TRACE_POINT();
746
745
  SpawnPreparationInfo info;
@@ -925,6 +924,15 @@ protected:
925
924
 
926
925
  assert(info.appRootPathsInsideChroot.back() == info.appRootInsideChroot);
927
926
  }
927
+
928
+ bool shouldLoadShellEnvvars(const Options &options, const SpawnPreparationInfo &preparation) const {
929
+ if (options.loadShellEnvvars) {
930
+ string shellName = extractBaseName(preparation.shell);
931
+ return shellName == "bash" || shellName == "zsh" || shellName == "ksh";
932
+ } else {
933
+ return false;
934
+ }
935
+ }
928
936
 
929
937
  string serializeEnvvarsFromPoolOptions(const Options &options) const {
930
938
  vector< pair<StaticString, StaticString> >::const_iterator it, end;
@@ -108,7 +108,7 @@ public:
108
108
  * set debugging options on the spawner.
109
109
  */
110
110
  DummySpawnerPtr getDummySpawner() {
111
- lock_guard<boost::mutex> l(syncher);
111
+ boost::lock_guard<boost::mutex> l(syncher);
112
112
  if (dummySpawner == NULL) {
113
113
  dummySpawner = make_shared<DummySpawner>(resourceLocator, config);
114
114
  }
@@ -121,6 +121,14 @@ public:
121
121
  SpawnerConfigPtr getConfig() const {
122
122
  return config;
123
123
  }
124
+
125
+ RandomGeneratorPtr getRandomGenerator() const {
126
+ return randomGenerator;
127
+ }
128
+
129
+ const ResourceLocator &getResourceLocator() const {
130
+ return resourceLocator;
131
+ }
124
132
  };
125
133
 
126
134
  typedef shared_ptr<SpawnerFactory> SpawnerFactoryPtr;
@@ -251,7 +251,7 @@ private:
251
251
  // This function is either called from the pool event loop or directly from
252
252
  // the detachAllGroups post lock actions. In both cases getPool() is never NULL.
253
253
  PoolPtr pool = self->getPool();
254
- lock_guard<boost::mutex> lock(self->getPoolSyncher(pool));
254
+ boost::lock_guard<boost::mutex> lock(self->getPoolSyncher(pool));
255
255
 
256
256
  vector<GroupPtr>::iterator it, end = self->detachedGroups.end();
257
257
  for (it = self->detachedGroups.begin(); it != end; it++) {
@@ -70,7 +70,7 @@
70
70
 
71
71
  #define PROCESS_SHUTDOWN_TIMEOUT_DISPLAY "1 minute"
72
72
 
73
- #define PASSENGER_VERSION "4.0.5"
73
+ #define PASSENGER_VERSION "4.0.6"
74
74
 
75
75
  #define SERVER_INSTANCE_DIR_STRUCTURE_MAJOR_VERSION 1
76
76
 
@@ -28,6 +28,7 @@
28
28
  #include <unistd.h>
29
29
  #include <Logging.h>
30
30
  #include <Utils/StrIntUtils.h>
31
+ #include <Utils/IOUtils.h>
31
32
 
32
33
  namespace Passenger {
33
34
 
@@ -87,13 +88,17 @@ _prepareLogEntry(std::stringstream &sstream, const char *file, unsigned int line
87
88
 
88
89
  void
89
90
  _writeLogEntry(const std::string &str) {
90
- size_t written = 0;
91
- do {
92
- ssize_t ret = write(_logOutput, str.data() + written, str.size() - written);
93
- if (ret != -1) {
94
- written += ret;
95
- }
96
- } while (written < str.size());
91
+ try {
92
+ writeExact(_logOutput, str.data(), str.size());
93
+ } catch (const SystemException &) {
94
+ /* The most likely reason why this fails is when the user has setup
95
+ * Apache to log to a pipe (e.g. to a log rotation script). Upon
96
+ * restarting the web server, the process that reads from the pipe
97
+ * shuts down, so we can't write to it anymore. That's why we
98
+ * just ignore write errors. It doesn't make sense to abort for
99
+ * something like this.
100
+ */
101
+ }
97
102
  }
98
103
 
99
104
  } // namespace Passenger
@@ -127,7 +127,7 @@ using namespace oxt;
127
127
  * };
128
128
  *
129
129
  * MessageServer::ClientContextPtr newClient(MessageServer::CommonClientContext &commonContext) {
130
- * return MessageServer::ClientContextPtr(new MyContext());
130
+ * return make_shared<MyContext>();
131
131
  * }
132
132
  *
133
133
  * bool processMessage(MessageServer::CommonClientContext &commonContext,
@@ -157,13 +157,7 @@ using namespace oxt;
157
157
  */
158
158
  class MessageServer {
159
159
  public:
160
- static const unsigned int CLIENT_THREAD_STACK_SIZE =
161
- #ifdef __FreeBSD__
162
- // localtime() on FreeBSD needs some more stack space.
163
- 1024 * 96;
164
- #else
165
- 1024 * 64;
166
- #endif
160
+ static const unsigned int CLIENT_THREAD_STACK_SIZE = 1024 * 128;
167
161
 
168
162
  /** Interface for client context objects. */
169
163
  class ClientContext {
@@ -186,9 +180,10 @@ public:
186
180
  AccountPtr account;
187
181
 
188
182
 
189
- CommonClientContext(FileDescriptor &theFd, AccountPtr &theAccount)
190
- : fd(theFd), account(theAccount)
191
- { }
183
+ CommonClientContext(FileDescriptor &_fd, AccountPtr &_account)
184
+ : fd(_fd),
185
+ account(_account)
186
+ { }
192
187
 
193
188
  /** Returns a string representation for this client context. */
194
189
  string name() {
@@ -196,7 +191,7 @@ public:
196
191
  }
197
192
 
198
193
  /**
199
- * Checks whether this client has all of the rights in <tt>rights</tt>. The
194
+ * Checks whether this client has all of the rights in `rights`. The
200
195
  * client will be notified about the result of this check, by sending it a
201
196
  * message.
202
197
  *
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011 Phusion
3
+ * Copyright (c) 2011-2013 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -89,7 +89,7 @@ threadMain() {
89
89
 
90
90
  static void
91
91
  wantPoll() {
92
- lock_guard<boost::mutex> l(syncher);
92
+ boost::lock_guard<boost::mutex> l(syncher);
93
93
  shouldPoll = true;
94
94
  cond.notify_one();
95
95
  }
@@ -97,7 +97,7 @@ wantPoll() {
97
97
  static int
98
98
  dispatch(eio_req *req) {
99
99
  auto_ptr<Data> data((Data *) req->data);
100
- assert(data->libev != NULL); // Check for strange bug.
100
+ assert(data->libev != NULL);
101
101
  data->libev->runLater(boost::bind(data->callback, *req));
102
102
  return 0;
103
103
  }
@@ -113,13 +113,13 @@ executeWrapper(eio_req *req) {
113
113
 
114
114
  static void
115
115
  lockedPread(int fd, void *buf, size_t length, off_t offset, eio_req *req) {
116
- lock_guard<boost::mutex> l(preadWriteLock);
116
+ boost::lock_guard<boost::mutex> l(preadWriteLock);
117
117
  req->result = pread(fd, buf, length, offset);
118
118
  }
119
119
 
120
120
  static void
121
121
  lockedPwrite(int fd, void *buf, size_t length, off_t offset, eio_req *req) {
122
- lock_guard<boost::mutex> l(preadWriteLock);
122
+ boost::lock_guard<boost::mutex> l(preadWriteLock);
123
123
  req->result = pwrite(fd, buf, length, offset);
124
124
  }
125
125
  #endif
@@ -70,11 +70,11 @@ public:
70
70
  helperScriptsDir = getOption(file, options, "helper_scripts");
71
71
  resourcesDir = getOption(file, options, "resources");
72
72
  docDir = getOption(file, options, "doc");
73
- rubyLibDir = getOption(file, options, "rubylib");
73
+ rubyLibDir = getOption(file, options, "rubylibdir");
74
74
  } else {
75
75
  string root = rootOrFile;
76
76
  binDir = root + "/bin";
77
- agentsDir = root + "/agents";
77
+ agentsDir = root + "/buildout/agents";
78
78
  helperScriptsDir = root + "/helper-scripts";
79
79
  resourcesDir = root + "/resources";
80
80
  docDir = root + "/doc";
@@ -94,10 +94,6 @@ public:
94
94
  return helperScriptsDir;
95
95
  }
96
96
 
97
- string getSpawnServerFilename() const {
98
- return getHelperScriptsDir() + "/passenger-spawn-server";
99
- }
100
-
101
97
  string getResourcesDir() const {
102
98
  return resourcesDir;
103
99
  }
@@ -30,6 +30,7 @@
30
30
  #include <oxt/backtrace.hpp>
31
31
 
32
32
  #include <sys/types.h>
33
+ #include <sys/stat.h>
33
34
  #include <dirent.h>
34
35
  #include <unistd.h>
35
36
  #include <pwd.h>
@@ -92,7 +93,7 @@ public:
92
93
  * anybody except the owner. The individual files and subdirectories
93
94
  * decide for themselves whether they're readable by anybody.
94
95
  */
95
- makeDirTree(path, "u=rwxs,g=x,o=x");
96
+ makeDirTree(path, "u=rwx,g=x,o=x");
96
97
 
97
98
  /* Write structure version file. */
98
99
  string structureVersionFile = path + "/structure_version.txt";
@@ -107,10 +108,10 @@ public:
107
108
  * directory.
108
109
  */
109
110
  if (runningAsRoot) {
110
- makeDirTree(path + "/buffered_uploads", "u=rwxs,g=,o=",
111
+ makeDirTree(path + "/buffered_uploads", "u=rwx,g=,o=",
111
112
  webServerWorkerUid, webServerWorkerGid);
112
113
  } else {
113
- makeDirTree(path + "/buffered_uploads", "u=rwxs,g=,o=");
114
+ makeDirTree(path + "/buffered_uploads", "u=rwx,g=,o=");
114
115
  }
115
116
 
116
117
  /* The web server must be able to directly connect to a backend. */
@@ -121,7 +122,7 @@ public:
121
122
  * However we don't want everybody to be able to know the
122
123
  * sockets' filenames, so the directory is not readable.
123
124
  */
124
- makeDirTree(path + "/backends", "u=rwxs,g=wx,o=wx");
125
+ makeDirTree(path + "/backends", "u=rwx,g=wx,o=wx,+t");
125
126
  } else {
126
127
  /* All backend processes are running as defaultUser/defaultGroup,
127
128
  * so make defaultUser/defaultGroup the owner and group of the
@@ -131,13 +132,13 @@ public:
131
132
  * nobody should be able to know the sockets' filenames without
132
133
  * having access to the application pool.
133
134
  */
134
- makeDirTree(path + "/backends", "u=rwxs,g=x,o=x", defaultUid, defaultGid);
135
+ makeDirTree(path + "/backends", "u=rwx,g=x,o=x", defaultUid, defaultGid);
135
136
  }
136
137
  } else {
137
138
  /* All backend processes are running as the same user as the web server,
138
139
  * so only allow access for this user.
139
140
  */
140
- makeDirTree(path + "/backends", "u=rwxs,g=,o=");
141
+ makeDirTree(path + "/backends", "u=rwx,g=,o=");
141
142
  }
142
143
 
143
144
  /* The helper server (containing the application pool) must be able to access
@@ -148,16 +149,16 @@ public:
148
149
  /* Both the helper server and the spawn server are
149
150
  * running as root.
150
151
  */
151
- makeDirTree(path + "/spawn-server", "u=rwxs,g=,o=");
152
+ makeDirTree(path + "/spawn-server", "u=rwx,g=,o=");
152
153
  } else {
153
154
  /* Both the helper server and the spawn server are
154
155
  * running as defaultUser/defaultGroup.
155
156
  */
156
- makeDirTree(path + "/spawn-server", "u=rwxs,g=,o=",
157
+ makeDirTree(path + "/spawn-server", "u=rwx,g=,o=",
157
158
  defaultUid, defaultGid);
158
159
  }
159
160
  } else {
160
- makeDirTree(path + "/spawn-server", "u=rwxs,g=,o=");
161
+ makeDirTree(path + "/spawn-server", "u=rwx,g=,o=");
161
162
  }
162
163
 
163
164
  owner = true;
@@ -214,7 +215,33 @@ private:
214
215
  * rights though, because we want admin tools to be able to list the available
215
216
  * generations no matter what user they're running as.
216
217
  */
217
- makeDirTree(path, "u=rwxs,g=rx,o=rx");
218
+ if (owner) {
219
+ switch (getFileType(path)) {
220
+ case FT_NONEXISTANT:
221
+ createDirectory(path);
222
+ break;
223
+ case FT_DIRECTORY:
224
+ removeDirTree(path);
225
+ createDirectory(path);
226
+ break;
227
+ default:
228
+ throw RuntimeException("'" + path + "' already exists, and is not a directory");
229
+ }
230
+ } else if (getFileType(path) != FT_DIRECTORY) {
231
+ throw RuntimeException("Server instance directory '" + path +
232
+ "' does not exist");
233
+ }
234
+ }
235
+
236
+ void createDirectory(const string &path) const {
237
+ // We do not use makeDirTree() here. If an attacker creates a directory
238
+ // just before we do, then we want to abort because we want the directory
239
+ // to have specific permissions.
240
+ if (mkdir(path.c_str(), parseModeString("u=rwx,g=rx,o=rx")) == -1) {
241
+ int e = errno;
242
+ throw FileSystemException("Cannot create server instance directory '" +
243
+ path + "'", e, path);
244
+ }
218
245
  }
219
246
 
220
247
  bool isDirectory(const string &dir, struct dirent *entry) const {