passenger 3.0.5 → 3.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 (198) hide show
  1. data/NEWS +19 -1
  2. data/build/packaging.rb +0 -1
  3. data/doc/cxxapi/Constants_8h_source.html +1 -1
  4. data/doc/cxxapi/Logging_8h_source.html +3 -3
  5. data/doc/cxxapi/MessageChannel_8h_source.html +2 -2
  6. data/doc/cxxapi/Utils_8h_source.html +407 -397
  7. data/doc/cxxapi/namespacePassenger.html +32 -0
  8. data/doc/cxxapi/namespacemembers.html +56 -1
  9. data/doc/cxxapi/namespacemembers_func.html +3 -0
  10. data/doc/cxxapi/ngx__http__passenger__module_8h_source.html +5 -5
  11. data/ext/apache2/Hooks.cpp +1 -1
  12. data/ext/common/AgentBase.cpp +86 -11
  13. data/ext/common/Constants.h +1 -1
  14. data/ext/common/Logging.h +3 -3
  15. data/ext/common/LoggingAgent/FilterSupport.h +1 -0
  16. data/ext/common/LoggingAgent/Main.cpp +8 -1
  17. data/ext/common/MessageChannel.h +2 -2
  18. data/ext/common/Utils.cpp +27 -3
  19. data/ext/common/Utils.h +10 -0
  20. data/ext/common/Watchdog.cpp +27 -1
  21. data/ext/nginx/HelperAgent.cpp +8 -8
  22. data/ext/oxt/thread.hpp +2 -2
  23. data/lib/phusion_passenger.rb +1 -1
  24. data/lib/phusion_passenger/abstract_installer.rb +6 -0
  25. data/lib/phusion_passenger/abstract_request_handler.rb +13 -2
  26. data/lib/phusion_passenger/analytics_logger.rb +15 -4
  27. data/lib/phusion_passenger/dependencies.rb +11 -26
  28. data/lib/phusion_passenger/platform_info.rb +96 -5
  29. data/lib/phusion_passenger/platform_info/apache.rb +13 -3
  30. data/lib/phusion_passenger/platform_info/compiler.rb +5 -0
  31. data/lib/phusion_passenger/rack/application_spawner.rb +3 -2
  32. data/lib/phusion_passenger/standalone/runtime_installer.rb +0 -1
  33. data/lib/phusion_passenger/standalone/start_command.rb +15 -8
  34. data/lib/phusion_passenger/templates/standalone/config.erb +1 -0
  35. metadata +5 -182
  36. data/doc/rdoc/classes/ConditionVariable.html +0 -215
  37. data/doc/rdoc/classes/Exception.html +0 -120
  38. data/doc/rdoc/classes/GC.html +0 -113
  39. data/doc/rdoc/classes/IO.html +0 -221
  40. data/doc/rdoc/classes/PhusionPassenger.html +0 -397
  41. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +0 -180
  42. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +0 -647
  43. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +0 -654
  44. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/InvalidPassword.html +0 -92
  45. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +0 -97
  46. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +0 -96
  47. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +0 -97
  48. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +0 -96
  49. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +0 -619
  50. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +0 -142
  51. data/doc/rdoc/classes/PhusionPassenger/AdminTools/MemoryStats.html +0 -368
  52. data/doc/rdoc/classes/PhusionPassenger/AdminTools/MemoryStats/Process.html +0 -231
  53. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance.html +0 -588
  54. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/CorruptedDirectoryError.html +0 -92
  55. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/GenerationsAbsentError.html +0 -92
  56. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Group.html +0 -147
  57. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Process.html +0 -279
  58. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/RoleDeniedError.html +0 -92
  59. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/StaleDirectoryError.html +0 -92
  60. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Stats.html +0 -123
  61. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/UnsupportedGenerationStructureVersionError.html +0 -92
  62. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger.html +0 -368
  63. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger/Lock.html +0 -194
  64. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger/Log.html +0 -299
  65. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger/SharedData.html +0 -206
  66. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +0 -155
  67. data/doc/rdoc/classes/PhusionPassenger/AppProcess.html +0 -367
  68. data/doc/rdoc/classes/PhusionPassenger/ClassicRails.html +0 -95
  69. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/ApplicationSpawner.html +0 -351
  70. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/ApplicationSpawner/Error.html +0 -98
  71. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/CGIFixed.html +0 -200
  72. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/FrameworkSpawner.html +0 -410
  73. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/FrameworkSpawner/Error.html +0 -98
  74. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/RequestHandler.html +0 -156
  75. data/doc/rdoc/classes/PhusionPassenger/ClassicRailsExtensions.html +0 -115
  76. data/doc/rdoc/classes/PhusionPassenger/ClassicRailsExtensions/AnalyticsLogging.html +0 -202
  77. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +0 -172
  78. data/doc/rdoc/classes/PhusionPassenger/DebugLogging.html +0 -273
  79. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +0 -145
  80. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +0 -162
  81. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +0 -141
  82. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +0 -92
  83. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +0 -673
  84. data/doc/rdoc/classes/PhusionPassenger/MessageChannel/InvalidHashError.html +0 -92
  85. data/doc/rdoc/classes/PhusionPassenger/MessageClient.html +0 -415
  86. data/doc/rdoc/classes/PhusionPassenger/NativeSupportLoader.html +0 -134
  87. data/doc/rdoc/classes/PhusionPassenger/Packaging.html +0 -129
  88. data/doc/rdoc/classes/PhusionPassenger/PlatformInfo.html +0 -1972
  89. data/doc/rdoc/classes/PhusionPassenger/Plugin.html +0 -237
  90. data/doc/rdoc/classes/PhusionPassenger/Rack.html +0 -91
  91. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +0 -312
  92. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner/Error.html +0 -98
  93. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +0 -218
  94. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions.html +0 -114
  95. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging.html +0 -259
  96. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ACExtension.html +0 -139
  97. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ASBenchmarkableExtension.html +0 -118
  98. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ExceptionLogger.html +0 -135
  99. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +0 -378
  100. data/doc/rdoc/classes/PhusionPassenger/Standalone.html +0 -111
  101. data/doc/rdoc/classes/PhusionPassenger/Standalone/AppFinder.html +0 -252
  102. data/doc/rdoc/classes/PhusionPassenger/Standalone/Command.html +0 -161
  103. data/doc/rdoc/classes/PhusionPassenger/Standalone/ConfigFile.html +0 -368
  104. data/doc/rdoc/classes/PhusionPassenger/Standalone/ConfigFile/DisallowedContextError.html +0 -132
  105. data/doc/rdoc/classes/PhusionPassenger/Standalone/HelpCommand.html +0 -151
  106. data/doc/rdoc/classes/PhusionPassenger/Standalone/Main.html +0 -189
  107. data/doc/rdoc/classes/PhusionPassenger/Standalone/PackageRuntimeCommand.html +0 -177
  108. data/doc/rdoc/classes/PhusionPassenger/Standalone/RuntimeInstaller.html +0 -341
  109. data/doc/rdoc/classes/PhusionPassenger/Standalone/StartCommand.html +0 -203
  110. data/doc/rdoc/classes/PhusionPassenger/Standalone/StatusCommand.html +0 -156
  111. data/doc/rdoc/classes/PhusionPassenger/Standalone/StopCommand.html +0 -168
  112. data/doc/rdoc/classes/PhusionPassenger/Standalone/Utils.html +0 -86
  113. data/doc/rdoc/classes/PhusionPassenger/Standalone/VersionCommand.html +0 -135
  114. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +0 -125
  115. data/doc/rdoc/classes/PhusionPassenger/Utils.html +0 -1543
  116. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher.html +0 -204
  117. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher/DirInfo.html +0 -171
  118. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher/FileInfo.html +0 -140
  119. data/doc/rdoc/classes/PhusionPassenger/Utils/HostsFileParser.html +0 -260
  120. data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +0 -194
  121. data/doc/rdoc/classes/PhusionPassenger/Utils/RewindableInput.html +0 -265
  122. data/doc/rdoc/classes/PhusionPassenger/Utils/RewindableInput/Tempfile.html +0 -120
  123. data/doc/rdoc/classes/PhusionPassenger/Utils/UnseekableSocket.html +0 -561
  124. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +0 -140
  125. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +0 -89
  126. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +0 -182
  127. data/doc/rdoc/classes/Process.html +0 -115
  128. data/doc/rdoc/classes/Signal.html +0 -139
  129. data/doc/rdoc/created.rid +0 -1
  130. data/doc/rdoc/files/DEVELOPERS_TXT.html +0 -280
  131. data/doc/rdoc/files/README.html +0 -157
  132. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +0 -130
  133. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +0 -135
  134. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +0 -126
  135. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +0 -128
  136. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/memory_stats_rb.html +0 -126
  137. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/server_instance_rb.html +0 -132
  138. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +0 -122
  139. data/doc/rdoc/files/lib/phusion_passenger/analytics_logger_rb.html +0 -129
  140. data/doc/rdoc/files/lib/phusion_passenger/app_process_rb.html +0 -127
  141. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/application_spawner_rb.html +0 -141
  142. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/cgi_fixed_rb.html +0 -126
  143. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/framework_spawner_rb.html +0 -146
  144. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/request_handler_rb.html +0 -125
  145. data/doc/rdoc/files/lib/phusion_passenger/classic_rails_extensions/init_rb.html +0 -132
  146. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +0 -126
  147. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +0 -122
  148. data/doc/rdoc/files/lib/phusion_passenger/debug_logging_rb.html +0 -122
  149. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +0 -147
  150. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +0 -122
  151. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +0 -127
  152. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +0 -120
  153. data/doc/rdoc/files/lib/phusion_passenger/message_client_rb.html +0 -127
  154. data/doc/rdoc/files/lib/phusion_passenger/native_support_rb.html +0 -132
  155. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +0 -122
  156. data/doc/rdoc/files/lib/phusion_passenger/platform_info/apache_rb.html +0 -127
  157. data/doc/rdoc/files/lib/phusion_passenger/platform_info/binary_compatibility_rb.html +0 -129
  158. data/doc/rdoc/files/lib/phusion_passenger/platform_info/compiler_rb.html +0 -127
  159. data/doc/rdoc/files/lib/phusion_passenger/platform_info/curl_rb.html +0 -126
  160. data/doc/rdoc/files/lib/phusion_passenger/platform_info/documentation_tools_rb.html +0 -126
  161. data/doc/rdoc/files/lib/phusion_passenger/platform_info/linux_rb.html +0 -126
  162. data/doc/rdoc/files/lib/phusion_passenger/platform_info/operating_system_rb.html +0 -127
  163. data/doc/rdoc/files/lib/phusion_passenger/platform_info/ruby_rb.html +0 -128
  164. data/doc/rdoc/files/lib/phusion_passenger/platform_info/zlib_rb.html +0 -126
  165. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +0 -122
  166. data/doc/rdoc/files/lib/phusion_passenger/plugin_rb.html +0 -127
  167. data/doc/rdoc/files/lib/phusion_passenger/public_api_rb.html +0 -127
  168. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +0 -137
  169. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +0 -125
  170. data/doc/rdoc/files/lib/phusion_passenger/rails3_extensions/init_rb.html +0 -127
  171. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +0 -122
  172. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +0 -160
  173. data/doc/rdoc/files/lib/phusion_passenger/standalone/app_finder_rb.html +0 -127
  174. data/doc/rdoc/files/lib/phusion_passenger/standalone/command_rb.html +0 -136
  175. data/doc/rdoc/files/lib/phusion_passenger/standalone/config_file_rb.html +0 -126
  176. data/doc/rdoc/files/lib/phusion_passenger/standalone/help_command_rb.html +0 -126
  177. data/doc/rdoc/files/lib/phusion_passenger/standalone/main_rb.html +0 -126
  178. data/doc/rdoc/files/lib/phusion_passenger/standalone/package_runtime_command_rb.html +0 -127
  179. data/doc/rdoc/files/lib/phusion_passenger/standalone/runtime_installer_rb.html +0 -133
  180. data/doc/rdoc/files/lib/phusion_passenger/standalone/start_command_rb.html +0 -136
  181. data/doc/rdoc/files/lib/phusion_passenger/standalone/status_command_rb.html +0 -126
  182. data/doc/rdoc/files/lib/phusion_passenger/standalone/stop_command_rb.html +0 -126
  183. data/doc/rdoc/files/lib/phusion_passenger/standalone/utils_rb.html +0 -126
  184. data/doc/rdoc/files/lib/phusion_passenger/standalone/version_command_rb.html +0 -127
  185. data/doc/rdoc/files/lib/phusion_passenger/utils/file_system_watcher_rb.html +0 -126
  186. data/doc/rdoc/files/lib/phusion_passenger/utils/hosts_file_parser_rb.html +0 -120
  187. data/doc/rdoc/files/lib/phusion_passenger/utils/rewindable_input_rb.html +0 -100
  188. data/doc/rdoc/files/lib/phusion_passenger/utils/tmpdir_rb.html +0 -122
  189. data/doc/rdoc/files/lib/phusion_passenger/utils/unseekable_socket_rb.html +0 -126
  190. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +0 -179
  191. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +0 -132
  192. data/doc/rdoc/fr_class_index.html +0 -139
  193. data/doc/rdoc/fr_file_index.html +0 -108
  194. data/doc/rdoc/fr_method_index.html +0 -439
  195. data/doc/rdoc/index.html +0 -26
  196. data/doc/rdoc/rdoc-style.css +0 -187
  197. data/ext/common/libboost_oxt/aggregate.cpp +0 -10
  198. data/ext/common/libpassenger_common/aggregate.cpp +0 -16
@@ -639,11 +639,35 @@ prestartWebApps(const ResourceLocator &locator, const string &serializedprestart
639
639
  }
640
640
  }
641
641
 
642
+ void
643
+ runAndPrintExceptions(const function<void ()> &func, bool toAbort) {
644
+ try {
645
+ func();
646
+ } catch (const boost::thread_interrupted &) {
647
+ throw;
648
+ } catch (const tracable_exception &e) {
649
+ P_ERROR("Exception: " << e.what() << "\n" << e.backtrace());
650
+ if (toAbort) {
651
+ abort();
652
+ }
653
+ }
654
+ }
655
+
656
+ void
657
+ runAndPrintExceptions(const function<void ()> &func) {
658
+ runAndPrintExceptions(func, true);
659
+ }
660
+
642
661
  string
643
662
  getHostName() {
644
- char hostname[HOST_NAME_MAX + 1];
645
- if (gethostname(hostname, sizeof(hostname)) == 0) {
646
- hostname[sizeof(hostname) - 1] = '\0';
663
+ long hostNameMax = HOST_NAME_MAX;
664
+ if (hostNameMax < 255) {
665
+ // https://bugzilla.redhat.com/show_bug.cgi?id=130733
666
+ hostNameMax = 255;
667
+ }
668
+ char hostname[hostNameMax + 1];
669
+ if (gethostname(hostname, hostNameMax) == 0) {
670
+ hostname[hostNameMax] = '\0';
647
671
  return hostname;
648
672
  } else {
649
673
  int e = errno;
@@ -26,6 +26,7 @@
26
26
  #define _PASSENGER_UTILS_H_
27
27
 
28
28
  #include <boost/shared_ptr.hpp>
29
+ #include <boost/function.hpp>
29
30
  #include <sys/types.h>
30
31
  #include <sys/stat.h>
31
32
  #include <string>
@@ -344,6 +345,15 @@ bool verifyWSGIDir(const string &dir, CachedFileStat *cstat = 0,
344
345
 
345
346
  void prestartWebApps(const ResourceLocator &locator, const string &serializedprestartURLs);
346
347
 
348
+ /**
349
+ * Runs the given function and catches any tracable_exceptions. Upon catching such an exception,
350
+ * its message and backtrace will be printed. If toAbort is true then it will call abort(),
351
+ * otherwise the exception is swallowed.
352
+ * thread_interrupted and all other exceptions are silently propagated.
353
+ */
354
+ void runAndPrintExceptions(const function<void ()> &func, bool toAbort);
355
+ void runAndPrintExceptions(const function<void ()> &func);
356
+
347
357
  /**
348
358
  * Returns the system's host name.
349
359
  *
@@ -112,6 +112,18 @@ private:
112
112
  pid = start();
113
113
  }
114
114
  ret = syscalls::waitpid(pid, &status, 0);
115
+ if (ret == -1 && errno == ECHILD) {
116
+ /* If the agent is attached to gdb then waitpid()
117
+ * here can return -1 with errno == ECHILD.
118
+ * Fallback to kill() polling for checking
119
+ * whether the agent is alive.
120
+ */
121
+ ret = pid;
122
+ status = 0;
123
+ P_WARN("waitpid() on " << name() << " return -1 with " <<
124
+ "errno = ECHILD, falling back to kill polling");
125
+ waitpidUsingKillPolling(pid);
126
+ }
115
127
 
116
128
  lock.lock();
117
129
  this->pid = 0;
@@ -120,8 +132,10 @@ private:
120
132
  this_thread::disable_interruption di;
121
133
  this_thread::disable_syscall_interruption dsi;
122
134
  if (ret == -1) {
135
+ int e = errno;
123
136
  P_WARN(name() << " crashed or killed for "
124
- "an unknown reason, restarting it...");
137
+ "an unknown reason (errno = " <<
138
+ strerror(e) << "), restarting it...");
125
139
  } else if (WIFEXITED(status)) {
126
140
  if (WEXITSTATUS(status) == 0) {
127
141
  /* When the web server is gracefully exiting, it will
@@ -244,6 +258,18 @@ protected:
244
258
  return 0; // timed out
245
259
  }
246
260
 
261
+ static void waitpidUsingKillPolling(pid_t pid) {
262
+ bool done = false;
263
+
264
+ while (!done) {
265
+ int ret = syscalls::kill(pid, 0);
266
+ done = ret == -1;
267
+ if (!done) {
268
+ syscalls::usleep(20000);
269
+ }
270
+ }
271
+ }
272
+
247
273
  public:
248
274
  AgentWatcher() {
249
275
  thr = NULL;
@@ -522,7 +522,7 @@ private:
522
522
  session->getConnectPassword().size() + 1);
523
523
  end += session->getConnectPassword().size() + 1;
524
524
 
525
- if (useUnionStation) {
525
+ if (!log->isNull()) {
526
526
  memcpy(end, "PASSENGER_GROUP_NAME", sizeof("PASSENGER_GROUP_NAME"));
527
527
  end += sizeof("PASSENGER_GROUP_NAME");
528
528
 
@@ -606,10 +606,6 @@ private:
606
606
  << " exception: " << e.what() << "\n"
607
607
  << " backtrace:\n" << e.backtrace());
608
608
  abort();
609
- } catch (const std::exception &e) {
610
- P_ERROR("Uncaught exception in PassengerServer client thread:\n"
611
- << " exception: " << e.what() << "\n"
612
- << " backtrace: not available");
613
609
  }
614
610
  }
615
611
 
@@ -638,7 +634,7 @@ public:
638
634
  this->serverSocket = serverSocket;
639
635
  this->analyticsLogger = logger;
640
636
  thr = new oxt::thread(
641
- bind(&Client::threadMain, this),
637
+ boost::bind(&Client::threadMain, this),
642
638
  "Client thread " + toString(number),
643
639
  CLIENT_THREAD_STACK_SIZE
644
640
  );
@@ -864,8 +860,11 @@ public:
864
860
  messageServer->getSocketFilename().c_str(),
865
861
  NULL);
866
862
 
863
+ function<void ()> func = boost::bind(prestartWebApps,
864
+ resourceLocator,
865
+ options.get("prestart_urls"));
867
866
  prestarterThread = ptr(new oxt::thread(
868
- boost::bind(prestartWebApps, resourceLocator, options.get("prestart_urls"))
867
+ boost::bind(runAndPrintExceptions, func, true)
869
868
  ));
870
869
  }
871
870
 
@@ -897,8 +896,9 @@ public:
897
896
  TRACE_POINT();
898
897
 
899
898
  startClientHandlerThreads();
899
+ function<void ()> func = boost::bind(&MessageServer::mainLoop, messageServer.get());
900
900
  messageServerThread = ptr(new oxt::thread(
901
- boost::bind(&MessageServer::mainLoop, messageServer.get()),
901
+ boost::bind(runAndPrintExceptions, func, true),
902
902
  "MessageServer thread", MESSAGE_SERVER_THREAD_STACK_SIZE
903
903
  ));
904
904
 
@@ -83,7 +83,7 @@ private:
83
83
  #endif
84
84
  }
85
85
 
86
- static void thread_main(boost::function<void ()> func, thread_data_ptr data) {
86
+ static void thread_main(const boost::function<void ()> func, thread_data_ptr data) {
87
87
  #ifdef OXT_BACKTRACE_IS_ENABLED
88
88
  initialize_backtrace_support_for_this_thread i(data->name);
89
89
  data->registration = i.registration;
@@ -129,7 +129,7 @@ public:
129
129
  * @throws boost::thread_resource_error Something went wrong during
130
130
  * creation of the thread.
131
131
  */
132
- explicit thread(boost::function<void ()> func, const std::string &name = "", unsigned int stack_size = 0) {
132
+ explicit thread(const boost::function<void ()> func, const std::string &name = "", unsigned int stack_size = 0) {
133
133
  initialize_data(name);
134
134
 
135
135
  set_thread_main_function(boost::bind(thread_main, func, data));
@@ -25,7 +25,7 @@ module PhusionPassenger
25
25
  ###### Version numbers ######
26
26
 
27
27
  # Phusion Passenger version number. Don't forget to edit ext/common/Constants.h too.
28
- VERSION_STRING = '3.0.5'
28
+ VERSION_STRING = '3.0.6'
29
29
 
30
30
  PREFERRED_NGINX_VERSION = '0.8.54'
31
31
  PREFERRED_PCRE_VERSION = '8.10'
@@ -61,6 +61,12 @@ class AbstractInstaller
61
61
  def start
62
62
  before_install
63
63
  install!
64
+ rescue PlatformInfo::RuntimeError => e
65
+ new_screen
66
+ color_puts "<red>An error occurred</red>"
67
+ puts
68
+ puts e.message
69
+ exit 1
64
70
  ensure
65
71
  after_install
66
72
  end
@@ -683,7 +683,8 @@ private
683
683
 
684
684
  def finalize_request(headers, has_error)
685
685
  log = headers[PASSENGER_ANALYTICS_WEB_LOG]
686
- if log
686
+ if log && !log.closed?
687
+ exception_occurred = false
687
688
  begin
688
689
  log.end_measure("app request handler processing", has_error)
689
690
  if OBJECT_SPACE_SUPPORTS_LIVE_OBJECTS
@@ -703,15 +704,25 @@ private
703
704
  GC.clear_stats
704
705
  end
705
706
  Thread.current[PASSENGER_ANALYTICS_WEB_LOG] = nil
707
+ rescue Exception
708
+ # Maybe this exception was raised while communicating
709
+ # with the logging agent. If that is the case then
710
+ # log.close may also raise an exception, but we're only
711
+ # interested in the original exception. So if this
712
+ # situation occurs we must ignore any exceptions raised
713
+ # by log.close.
714
+ exception_occurred = true
715
+ raise
706
716
  ensure
707
717
  # It is important that the following call receives an ACK
708
- # from the logging server and that we don't close the socket
718
+ # from the logging agent and that we don't close the socket
709
719
  # connection until the ACK has been received, otherwise
710
720
  # the helper agent may close the transaction before this
711
721
  # process's openTransaction command is processed.
712
722
  begin
713
723
  log.close
714
724
  rescue
725
+ raise if !exception_occurred
715
726
  end
716
727
  end
717
728
  end
@@ -85,9 +85,10 @@ class AnalyticsLogger
85
85
  yield
86
86
  rescue Exception
87
87
  error = true
88
+ is_closed = closed?
88
89
  raise
89
90
  ensure
90
- end_measure(name, error)
91
+ end_measure(name, error) if !is_closed
91
92
  end
92
93
  end
93
94
 
@@ -125,6 +126,16 @@ class AnalyticsLogger
125
126
  @shared_data = nil
126
127
  end if @shared_data
127
128
  end
129
+
130
+ def closed?
131
+ if @shared_data
132
+ @shared_data.synchronize do
133
+ return !@shared_data.client.connected?
134
+ end
135
+ else
136
+ return nil
137
+ end
138
+ end
128
139
 
129
140
  private
130
141
  def current_timestamp
@@ -168,7 +179,7 @@ class AnalyticsLogger
168
179
  else
169
180
  @max_connect_tries = 1
170
181
  end
171
- @reconnect_timeout = 60
182
+ @reconnect_timeout = 1
172
183
  @next_reconnect_time = Time.utc(1980, 1, 1)
173
184
  end
174
185
 
@@ -234,7 +245,7 @@ class AnalyticsLogger
234
245
  end
235
246
  # Failed to connect.
236
247
  DebugLogging.warn("Cannot connect to the logging agent (#{@server_address}); " +
237
- "retrying in #{@reconnect_timeout} seconds.")
248
+ "retrying in #{@reconnect_timeout} second(s).")
238
249
  @next_reconnect_time = current_time + @reconnect_timeout
239
250
  end
240
251
  return Log.new
@@ -277,7 +288,7 @@ class AnalyticsLogger
277
288
  end
278
289
  # Failed to connect.
279
290
  DebugLogging.warn("Cannot connect to the logging agent (#{@server_address}); " +
280
- "retrying in #{@reconnect_timeout} seconds.")
291
+ "retrying in #{@reconnect_timeout} second(s).")
281
292
  @next_reconnect_time = current_time + @reconnect_timeout
282
293
  end
283
294
  return Log.new
@@ -452,8 +452,8 @@ module Dependencies # :nodoc: all
452
452
  Curl_Dev = Dependency.new do |dep|
453
453
  dep.name = "Curl development headers with SSL support"
454
454
  dep.define_checker do |result|
455
- source_file = '/tmp/passenger-curl-check.c'
456
- output_file = '/tmp/passenger-curl-check'
455
+ source_file = "#{PlatformInfo.tmpexedir}/passenger-curl-check.c"
456
+ output_file = "#{PlatformInfo.tmpexedir}/passenger-curl-check"
457
457
  begin
458
458
  found = true
459
459
  File.open(source_file, 'w') do |f|
@@ -510,8 +510,8 @@ module Dependencies # :nodoc: all
510
510
  OpenSSL_Dev = Dependency.new do |dep|
511
511
  dep.name = "OpenSSL development headers"
512
512
  dep.define_checker do |result|
513
- source_file = '/tmp/passenger-openssl-check.c'
514
- object_file = '/tmp/passenger-openssl-check.o'
513
+ source_file = "#{PlatformInfo.tmpexedir}/passenger-openssl-check.c"
514
+ object_file = "#{PlatformInfo.tmpexedir}/passenger-openssl-check.o"
515
515
  begin
516
516
  File.open(source_file, 'w') do |f|
517
517
  f.write("#include <openssl/ssl.h>")
@@ -542,20 +542,22 @@ module Dependencies # :nodoc: all
542
542
  Zlib_Dev = Dependency.new do |dep|
543
543
  dep.name = "Zlib development headers"
544
544
  dep.define_checker do |result|
545
+ source_file = "#{PlatformInfo.tmpexedir}/zlib-check.c"
546
+ object_file = "#{PlatformInfo.tmpexedir}/zlib-check.o"
545
547
  begin
546
- File.open('/tmp/r8ee-check.c', 'w') do |f|
548
+ File.open(source_file, 'w') do |f|
547
549
  f.write("#include <zlib.h>")
548
550
  end
549
- Dir.chdir('/tmp') do
550
- if system("(g++ -c r8ee-check.c) >/dev/null 2>/dev/null")
551
+ Dir.chdir(File.dirname(source_file)) do
552
+ if system("(g++ -c zlib-check.c) >/dev/null 2>/dev/null")
551
553
  result.found
552
554
  else
553
555
  result.not_found
554
556
  end
555
557
  end
556
558
  ensure
557
- File.unlink('/tmp/r8ee-check.c') rescue nil
558
- File.unlink('/tmp/r8ee-check.o') rescue nil
559
+ File.unlink(source_file) rescue nil
560
+ File.unlink(object_file) rescue nil
559
561
  end
560
562
  end
561
563
  if RUBY_PLATFORM =~ /linux/
@@ -571,23 +573,6 @@ module Dependencies # :nodoc: all
571
573
  dep.website = "http://www.zlib.net/"
572
574
  end
573
575
 
574
- File_Tail = Dependency.new do |dep|
575
- dep.name = "file-tail"
576
- dep.define_checker do |result|
577
- begin
578
- begin
579
- require 'rubygems'
580
- rescue LoadError
581
- end
582
- require 'file/tail'
583
- result.found
584
- rescue LoadError
585
- result.not_found
586
- end
587
- end
588
- dep.install_instructions = "Please install RubyGems first, then run <b>#{PlatformInfo.gem_command || "gem"} install file-tail</b>"
589
- end
590
-
591
576
  Daemon_Controller = Dependency.new do |dep|
592
577
  dep.name = "daemon_controller >= 0.2.5"
593
578
  dep.install_instructions = "Please install RubyGems first, then run " <<
@@ -137,14 +137,18 @@ private
137
137
  private_class_method :read_file
138
138
 
139
139
  public
140
+ class RuntimeError < ::RuntimeError
141
+ end
142
+
140
143
  # Check whether the specified command is in $PATH, and return its
141
144
  # absolute filename. Returns nil if the command is not found.
142
145
  #
143
146
  # This function exists because system('which') doesn't always behave
144
147
  # correctly, for some weird reason.
145
148
  def self.find_command(name)
146
- ENV['PATH'].split(File::PATH_SEPARATOR).detect do |directory|
147
- path = File.join(directory, name.to_s)
149
+ name = name.to_s
150
+ ENV['PATH'].to_s.split(File::PATH_SEPARATOR).detect do |directory|
151
+ path = File.join(directory, name)
148
152
  if File.file?(path) && File.executable?(path)
149
153
  return path
150
154
  end
@@ -156,6 +160,93 @@ public
156
160
  return !ENV[name].nil? && !ENV[name].empty?
157
161
  end
158
162
 
163
+ def self.tmpdir
164
+ result = ENV['TMPDIR']
165
+ if result && !result.empty?
166
+ return result.sub(/\/+\Z/, '')
167
+ else
168
+ return '/tmp'
169
+ end
170
+ end
171
+ memoize :tmpdir
172
+
173
+ # Returns the directory in which test executables should be placed. The
174
+ # returned directory is guaranteed to be writable and guaranteed to
175
+ # not be mounted with the 'noexec' option.
176
+ # If no such directory can be found then it will raise a PlatformInfo::RuntimeError
177
+ # with an appropriate error message.
178
+ def self.tmpexedir
179
+ basename = "test-exe.#{Process.pid}.#{Thread.current.object_id}"
180
+ attempts = []
181
+
182
+ dir = tmpdir
183
+ filename = "#{dir}/#{basename}"
184
+ begin
185
+ File.open(filename, 'w').close
186
+ File.chmod(0700, filename)
187
+ if File.executable?(filename)
188
+ return dir
189
+ else
190
+ attempts << { :dir => dir,
191
+ :error => "This directory's filesystem is mounted with the 'noexec' option." }
192
+ end
193
+ rescue Errno::ENOENT
194
+ attempts << { :dir => dir, :error => "This directory doesn't exist." }
195
+ rescue Errno::EACCES
196
+ attempts << { :dir => dir, :error => "This program doesn't have permission to write to this directory." }
197
+ rescue SystemCallError => e
198
+ attempts << { :dir => dir, :error => e.message }
199
+ ensure
200
+ File.unlink(filename) rescue nil
201
+ end
202
+
203
+ dir = Dir.pwd
204
+ filename = "#{dir}/#{basename}"
205
+ begin
206
+ File.open(filename, 'w').close
207
+ File.chmod(0700, filename)
208
+ if File.executable?(filename)
209
+ return dir
210
+ else
211
+ attempts << { :dir => dir,
212
+ :error => "This directory's filesystem is mounted with the 'noexec' option." }
213
+ end
214
+ rescue Errno::ENOENT
215
+ attempts << { :dir => dir, :error => "This directory doesn't exist." }
216
+ rescue Errno::EACCES
217
+ attempts << { :dir => dir, :error => "This program doesn't have permission to write to this directory." }
218
+ rescue SystemCallError => e
219
+ attempts << { :dir => dir, :error => e.message }
220
+ ensure
221
+ File.unlink(filename) rescue nil
222
+ end
223
+
224
+ message = "In order to run certain tests, this program " +
225
+ "must be able to write temporary\n" +
226
+ "executable files to some directory. However no such " +
227
+ "directory can be found. \n" +
228
+ "The following directories have been tried:\n\n"
229
+ attempts.each do |attempt|
230
+ message << " * #{attempt[:dir]}\n"
231
+ message << " #{attempt[:error]}\n"
232
+ end
233
+ message << "\nYou can solve this problem by telling this program what directory to write\n" <<
234
+ "temporary executable files to.\n" <<
235
+ "\n" <<
236
+ " Set the $TMPDIR environment variable to the desired directory's filename and\n" <<
237
+ " re-run this program.\n" <<
238
+ "\n" <<
239
+ "Notes:\n" <<
240
+ "\n" <<
241
+ " * If you're using 'sudo'/'rvmsudo', remember that 'sudo'/'rvmsudo' unsets all\n" <<
242
+ " environment variables, so you must set the environment variable *after*\n" <<
243
+ " having gained root privileges.\n" <<
244
+ " * The directory you choose must writeable and must not be mounted with the\n" <<
245
+ " 'noexec' option."
246
+ raise RuntimeError, message
247
+ end
248
+ memoize :tmpexedir
249
+
159
250
  def self.cc
160
251
  return ENV['CC'] || "gcc"
161
252
  end
@@ -172,7 +263,7 @@ public
172
263
  else
173
264
  raise ArgumentError,"Unsupported language '#{language}'"
174
265
  end
175
- filename = File.join("/tmp/passenger-compile-check-#{Process.pid}.c")
266
+ filename = File.join("#{tmpexedir}/passenger-compile-check-#{Process.pid}.c")
176
267
  File.open(filename, "w") do |f|
177
268
  f.puts(source)
178
269
  end
@@ -193,7 +284,7 @@ public
193
284
  else
194
285
  raise ArgumentError,"Unsupported language '#{language}'"
195
286
  end
196
- filename = File.join("/tmp/passenger-link-check-#{Process.pid}.c")
287
+ filename = File.join("#{tmpexedir}/passenger-link-check-#{Process.pid}.c")
197
288
  File.open(filename, "w") do |f|
198
289
  f.puts(source)
199
290
  end
@@ -214,7 +305,7 @@ public
214
305
  else
215
306
  raise ArgumentError,"Unsupported language '#{language}'"
216
307
  end
217
- filename = File.join("/tmp/passenger-compile-check-#{Process.pid}.c")
308
+ filename = File.join("#{tmpexedir}/passenger-compile-check-#{Process.pid}.c")
218
309
  File.open(filename, "w") do |f|
219
310
  f.puts(source)
220
311
  end