passenger 5.0.10 → 5.0.11

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 (124) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/CHANGELOG +18 -0
  5. data/CONTRIBUTING.md +3 -3
  6. data/bin/passenger-status +12 -4
  7. data/build/agents.rb +45 -45
  8. data/build/apache2.rb +1 -1
  9. data/build/basics.rb +1 -1
  10. data/build/cxx_tests.rb +12 -12
  11. data/doc/CloudLicensingConfiguration.html +10 -10
  12. data/doc/CloudLicensingConfiguration.txt.md +10 -10
  13. data/doc/DebuggingAndStressTesting.md +3 -3
  14. data/doc/Design and Architecture.html +30 -30
  15. data/doc/Design and Architecture.txt +28 -28
  16. data/doc/ServerOptimizationGuide.html +3 -3
  17. data/doc/ServerOptimizationGuide.txt.md +3 -3
  18. data/doc/Users guide Apache.html +24 -12
  19. data/doc/Users guide Apache.txt +2 -2
  20. data/doc/Users guide Nginx.html +24 -12
  21. data/doc/Users guide Nginx.txt +2 -2
  22. data/doc/Users guide Standalone.html +18 -6
  23. data/doc/images/passenger_architecture.png +0 -0
  24. data/doc/images/passenger_architecture.svg +10 -9
  25. data/doc/images/{helper_agent_core_architecture.png → passenger_core_architecture.png} +0 -0
  26. data/doc/users_guide_snippets/environment_variables.txt +1 -1
  27. data/doc/users_guide_snippets/installation/verify_running_epilogue.txt +1 -1
  28. data/doc/users_guide_snippets/support_information.txt +1 -1
  29. data/doc/users_guide_snippets/tips.txt +2 -2
  30. data/doc/users_guide_snippets/under_the_hood/relationship_with_ruby.txt +1 -1
  31. data/ext/apache2/Bucket.h +5 -5
  32. data/ext/apache2/Configuration.cpp +1 -1
  33. data/ext/apache2/Configuration.hpp +2 -3
  34. data/ext/apache2/ConfigurationFields.hpp +3 -0
  35. data/ext/apache2/ConfigurationFields.hpp.erb +3 -0
  36. data/ext/apache2/Hooks.cpp +42 -34
  37. data/ext/common/Account.h +3 -3
  38. data/ext/common/AgentsStarter.cpp +7 -7
  39. data/ext/common/AgentsStarter.h +20 -20
  40. data/ext/common/ApplicationPool2/Options.h +12 -12
  41. data/ext/common/Constants.h +10 -8
  42. data/ext/common/Logging.cpp +22 -1
  43. data/ext/common/Logging.h +19 -2
  44. data/ext/common/ServerKit/AcceptLoadBalancer.h +3 -3
  45. data/ext/common/ServerKit/Server.h +24 -0
  46. data/ext/common/UnionStation/Connection.h +1 -1
  47. data/ext/common/UnionStation/Core.h +21 -21
  48. data/ext/common/UnionStation/Transaction.h +3 -3
  49. data/ext/common/Utils.cpp +2 -2
  50. data/ext/common/Utils/IOUtils.cpp +5 -1
  51. data/ext/common/{agents → agent}/ApiServerUtils.h +3 -3
  52. data/ext/common/{agents → agent}/Base.cpp +2 -2
  53. data/ext/common/{agents → agent}/Base.h +0 -0
  54. data/ext/common/{agents/HelperAgent → agent/Core}/ApiServer.h +33 -9
  55. data/ext/common/{agents/HelperAgent → agent/Core}/Main.cpp +60 -59
  56. data/ext/common/{agents/HelperAgent → agent/Core}/OptionParser.h +32 -25
  57. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler.h +17 -17
  58. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/AppResponse.h +0 -0
  59. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/BufferBody.cpp +0 -0
  60. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/CheckoutSession.cpp +0 -0
  61. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/Client.h +2 -2
  62. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/ForwardResponse.cpp +0 -0
  63. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/Hooks.cpp +0 -0
  64. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/InitRequest.cpp +4 -3
  65. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/Request.h +1 -1
  66. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/SendRequest.cpp +0 -0
  67. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/TurboCaching.h +1 -1
  68. data/ext/common/{agents/HelperAgent → agent/Core}/RequestHandler/Utils.cpp +0 -0
  69. data/ext/common/{agents/HelperAgent → agent/Core}/ResponseCache.h +0 -0
  70. data/ext/common/{agents → agent}/Main.cpp +9 -9
  71. data/ext/common/{agents → agent}/SpawnPreparer/Main.cpp +0 -0
  72. data/ext/common/{agents/HelperAgent/SystemMetricsTool.cpp → agent/SystemMetrics/Main.cpp} +0 -0
  73. data/ext/common/{agents → agent}/TempDirToucher/Main.cpp +0 -0
  74. data/ext/common/{agents/LoggingAgent → agent/UstRouter}/ApiServer.h +7 -7
  75. data/ext/common/{agents/LoggingAgent → agent/UstRouter}/DataStoreId.h +0 -0
  76. data/ext/common/{agents/LoggingAgent → agent/UstRouter}/FilterSupport.cpp +0 -0
  77. data/ext/common/{agents/LoggingAgent → agent/UstRouter}/FilterSupport.h +0 -0
  78. data/ext/common/{agents/LoggingAgent → agent/UstRouter}/LoggingServer.h +4 -4
  79. data/ext/common/{agents/LoggingAgent → agent/UstRouter}/Main.cpp +45 -45
  80. data/ext/common/{agents/LoggingAgent → agent/UstRouter}/OptionParser.h +20 -20
  81. data/ext/common/{agents/LoggingAgent → agent/UstRouter}/RemoteSender.h +0 -0
  82. data/ext/common/{agents → agent}/Watchdog/AgentWatcher.cpp +0 -0
  83. data/ext/common/{agents → agent}/Watchdog/ApiServer.h +1 -1
  84. data/ext/common/{agents/Watchdog/HelperAgentWatcher.cpp → agent/Watchdog/CoreWatcher.cpp} +14 -10
  85. data/ext/common/{agents → agent}/Watchdog/InstanceDirToucher.cpp +0 -0
  86. data/ext/common/{agents → agent}/Watchdog/Main.cpp +131 -75
  87. data/ext/common/{agents/Watchdog/LoggingAgentWatcher.cpp → agent/Watchdog/UstRouterWatcher.cpp} +13 -9
  88. data/ext/nginx/CacheLocationConfig.c +11 -6
  89. data/ext/nginx/CacheLocationConfig.c.erb +11 -6
  90. data/ext/nginx/Configuration.c +22 -7
  91. data/ext/nginx/Configuration.h +1 -19
  92. data/ext/nginx/ConfigurationFields.h +19 -0
  93. data/ext/nginx/ConfigurationFields.h.erb +19 -0
  94. data/ext/nginx/ContentHandler.c +33 -33
  95. data/ext/nginx/CreateLocationConfig.c +3 -1
  96. data/ext/nginx/CreateLocationConfig.c.erb +3 -1
  97. data/ext/nginx/MergeLocationConfig.c +8 -4
  98. data/ext/nginx/MergeLocationConfig.c.erb +7 -3
  99. data/ext/nginx/ngx_http_passenger_module.c +33 -42
  100. data/helper-scripts/backtrace-sanitizer.rb +2 -2
  101. data/lib/phusion_passenger.rb +1 -1
  102. data/lib/phusion_passenger/admin_tools/instance.rb +2 -2
  103. data/lib/phusion_passenger/admin_tools/instance_registry.rb +7 -3
  104. data/lib/phusion_passenger/common_library.rb +8 -8
  105. data/lib/phusion_passenger/config/about_command.rb +1 -1
  106. data/lib/phusion_passenger/config/api_call_command.rb +3 -3
  107. data/lib/phusion_passenger/config/installation_utils.rb +34 -21
  108. data/lib/phusion_passenger/config/reopen_logs_command.rb +2 -2
  109. data/lib/phusion_passenger/config/restart_app_command.rb +18 -4
  110. data/lib/phusion_passenger/constants.rb +7 -5
  111. data/lib/phusion_passenger/loader_shared_helpers.rb +2 -6
  112. data/lib/phusion_passenger/message_client.rb +8 -8
  113. data/lib/phusion_passenger/platform_info/ruby.rb +1 -2
  114. data/lib/phusion_passenger/preloader_shared_helpers.rb +1 -1
  115. data/lib/phusion_passenger/request_handler.rb +3 -2
  116. data/lib/phusion_passenger/request_handler/thread_handler.rb +4 -4
  117. data/lib/phusion_passenger/standalone/start_command.rb +13 -3
  118. data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +2 -1
  119. data/lib/phusion_passenger/union_station/core.rb +18 -18
  120. data/lib/phusion_passenger/union_station/transaction.rb +5 -5
  121. data/resources/oss-binaries.phusionpassenger.com.crt +0 -84
  122. data/resources/templates/standalone/config.erb +1 -0
  123. metadata +40 -40
  124. metadata.gz.asc +7 -7
@@ -26,7 +26,7 @@ Whenever a Phusion Passenger agent process crashes because of a signal (SIGABRT,
26
26
 
27
27
  * A simple libc-level backtrace of the current thread. This backtrace may or may not correspond to the thread that caused the crash.
28
28
  * A detailed backtrace report, covering all threads. This report even contains the values of variables on the stack. The report is obtained through the [crash-watch](https://github.com/FooBarWidget/crash-watch) tool so you must have it installed. Crash-watch in turn requires gdb, which must also be installed.
29
- * Agent-specific diagnostics information. For example the HelperAgent will report the status of its process pool and its connected clients.
29
+ * Agent-specific diagnostics information. For example the Passenger core will report the status of its process pool and its connected clients.
30
30
 
31
31
  You can change the crash behavior with the following environment variables:
32
32
 
@@ -55,6 +55,6 @@ To enable, set the environment variable `PASSENGER_SIMULATE_SYSCALL_FAILURES`. T
55
55
 
56
56
  `program_nameN` specifies the name of the Phusion Passenger process for which system call failure simulation should be enabled. This is followed by a list of system call `errno` names and the respective probabilities (between 0 and 1). For example:
57
57
 
58
- export PASSENGER_SIMULATE_SYSCALL_FAILURES='watchdog=ENOSPC:0.01;server=EMFILE:0.001,ECONNREFUSED:0.02'
58
+ export PASSENGER_SIMULATE_SYSCALL_FAILURES='PassengerAgent watchdog=ENOSPC:0.01;PassengerAgent core=EMFILE:0.001,ECONNREFUSED:0.02'
59
59
 
60
- This will enable system call failure simulation only for the watchdog and the HTTP server, but not for the logging agent. All system calls in the watchdog will have a 1% probability of throwing ENOSPC. All system calls in the HTTP server will have a 0.1% probability of throwing EMFILE, and a 2% probability of throwing ECONNREFUSED.
60
+ This will enable system call failure simulation only for the watchdog and the core, but not for the UstRouter. All system calls in the watchdog will have a 1% probability of throwing ENOSPC. All system calls in the HTTP server will have a 0.1% probability of throwing EMFILE, and a 2% probability of throwing ECONNREFUSED.
@@ -1091,14 +1091,14 @@ pre {
1091
1091
  <div class="foo toclevel4"><a href="#_the_rationale_behind_reverse_proxying">1.1.2. The rationale behind reverse proxying</a></div>
1092
1092
  <div class="foo toclevel3"><a href="#_phusion_passenger_architecture_overview">1.2. Phusion Passenger architecture overview</a></div>
1093
1093
  <div class="foo toclevel4"><a href="#_web_server_module">1.2.1. Web server module</a></div>
1094
- <div class="foo toclevel4"><a href="#_helperagent">1.2.2. HelperAgent</a></div>
1095
- <div class="foo toclevel4"><a href="#_loggingagent">1.2.3. LoggingAgent</a></div>
1094
+ <div class="foo toclevel4"><a href="#_passenger_core">1.2.2. Passenger core</a></div>
1095
+ <div class="foo toclevel4"><a href="#_ustrouter">1.2.3. UstRouter</a></div>
1096
1096
  <div class="foo toclevel4"><a href="#_watchdog">1.2.4. Watchdog</a></div>
1097
1097
  <div class="foo toclevel4"><a href="#_command_line_tools">1.2.5. Command line tools</a></div>
1098
1098
  <div class="foo toclevel4"><a href="#_passenger_standalone">1.2.6. Passenger Standalone</a></div>
1099
1099
  <div class="foo toclevel3"><a href="#_build_system_and_source_tree">1.3. Build system and source tree</a></div>
1100
1100
  <div class="foo toclevel2"><a href="#_initialization">2. Initialization</a></div>
1101
- <div class="foo toclevel2"><a href="#helper_agent_architecture">3. HelperAgent architecture</a></div>
1101
+ <div class="foo toclevel2"><a href="#passenger_core_architecture">3. Passenger core architecture</a></div>
1102
1102
  <div class="foo toclevel3"><a href="#_request_handling">3.1. Request handling</a></div>
1103
1103
  <div class="foo toclevel4"><a href="#_one_client_per_request">3.1.1. One client per request</a></div>
1104
1104
  <div class="foo toclevel4"><a href="#request_handler_forwarding_to_app">3.1.2. Forwarding to the application</a></div>
@@ -1254,31 +1254,31 @@ end</pre>
1254
1254
  <img src="images/passenger_architecture_overview.png" alt="An overview of Phusion Passenger’s architecture">
1255
1255
  </span></p></div>
1256
1256
  <div class="paragraph"><p>Phusion Passenger is not a single, monolithic entity. Instead, it consists of multiple components and processes that work together. Part of the reason why Phusion Passenger is split like this, is because it’s technically necessary (no other way to implement it). But another part of the reason is stability and robustness. Individual components can crash and can be restarted independently from each other. If we were to put everything inside a single process, then a crash will take down all of Phusion Passenger.</p></div>
1257
- <div class="paragraph"><p>Thus, if the HelperAgent crashes, or if an application process crashes, they can both be restarted without affecting the web server’s stability.</p></div>
1257
+ <div class="paragraph"><p>Thus, if the Passenger core crashes, or if an application process crashes, they can both be restarted without affecting the web server’s stability.</p></div>
1258
1258
  <div class="sect3">
1259
1259
  <span class="anchor_helper" id="_web_server_module"></span><h4 data-anchor="_web_server_module">1.2.1. Web server module</h4>
1260
- <div class="paragraph"><p>When an HTTP client sends a request, it is received by the web server (Nginx or Apache). Both Apache and Nginx can be extended with <strong>modules</strong>. Phusion Passenger provides such a module. The module is loaded into Nginx/Apache. It checks whether the request should be handled by a Phusion Passenger-served web application, and if so, forwards the request to the HelperAgent. The internal wire protocol used during this forwarding, is a modified version of <a href="http://en.wikipedia.org/wiki/SCGI">SCGI</a>.</p></div>
1261
- <div class="paragraph"><p>The Nginx module and Apache module have an entirely different code base. Their code bases are in <span class="monospaced">ext/nginx</span> and <span class="monospaced">ext/apache2</span>, respectively. Both modules are relatively small because they outsource most logic to the HelperAgent, and because they utilize a common library (<span class="monospaced">ext/common</span>). This allows us to support both Nginx and Apache without having to write a lot of things twice.</p></div>
1260
+ <div class="paragraph"><p>When an HTTP client sends a request, it is received by the web server (Nginx or Apache). Both Apache and Nginx can be extended with <strong>modules</strong>. Phusion Passenger provides such a module. The module is loaded into Nginx/Apache. It checks whether the request should be handled by a Phusion Passenger-served web application, and if so, forwards the request to the Passenger core. The internal wire protocol used during this forwarding, is a modified version of <a href="http://en.wikipedia.org/wiki/SCGI">SCGI</a>.</p></div>
1261
+ <div class="paragraph"><p>The Nginx module and Apache module have an entirely different code base. Their code bases are in <span class="monospaced">ext/nginx</span> and <span class="monospaced">ext/apache2</span>, respectively. Both modules are relatively small because they outsource most logic to the Passenger core, and because they utilize a common library (<span class="monospaced">ext/common</span>). This allows us to support both Nginx and Apache without having to write a lot of things twice.</p></div>
1262
1262
  </div>
1263
1263
  <div class="sect3">
1264
- <span class="anchor_helper" id="_helperagent"></span><h4 data-anchor="_helperagent">1.2.2. HelperAgent</h4>
1265
- <div class="paragraph"><p>The <strong>HelperAgent</strong> is Phusion Passenger’s core, where most of the processing is done. The HelperAgent keeps track of which application processes currently exist, and using load balancing rules, determines which process a request should be forwarded to. The HelperAgent also takes care of <strong>application spawning</strong>: if it determines that having more application processes is necessary or beneficial, then it will make that happen. Process spawning is subject to user-configured limits: the HelperAgent will never spawn more processes than a user-configured maximum.</p></div>
1266
- <div class="paragraph"><p>The HelperAgent also has monitoring and statistics gathering capabilities. It constantly keeps track of applications' memory usage, how many requests they’ve handled, etc. This information can later be queried from administration tools. And if an application process crashes, the HelperAgent restarts it.</p></div>
1267
- <div class="paragraph"><p>The HelperAgent is by far the largest and most complex part of the system, but it is itself composed of several smaller subsystems. Most of the <a href="#helper_agent_architecture">HelperAgent architecture</a> chapter is devoted to describing the HelperAgent.</p></div>
1264
+ <span class="anchor_helper" id="_passenger_core"></span><h4 data-anchor="_passenger_core">1.2.2. Passenger core</h4>
1265
+ <div class="paragraph"><p>The <strong>Passenger core</strong> is where most of the processing is done. The core keeps track of which application processes currently exist, and using load balancing rules, determines which process a request should be forwarded to. The core also takes care of <strong>application spawning</strong>: if it determines that having more application processes is necessary or beneficial, then it will make that happen. Process spawning is subject to user-configured limits: the core will never spawn more processes than a user-configured maximum.</p></div>
1266
+ <div class="paragraph"><p>The core also has monitoring and statistics gathering capabilities. It constantly keeps track of applications' memory usage, how many requests they’ve handled, etc. This information can later be queried from administration tools. And if an application process crashes, the core restarts it.</p></div>
1267
+ <div class="paragraph"><p>The core is by far the largest and most complex part of the system, but it is itself composed of several smaller subsystems. Most of the <a href="#passenger_core_architecture">core architecture</a> chapter is devoted to describing the core.</p></div>
1268
1268
  </div>
1269
1269
  <div class="sect3">
1270
- <span class="anchor_helper" id="_loggingagent"></span><h4 data-anchor="_loggingagent">1.2.3. LoggingAgent</h4>
1271
- <div class="paragraph"><p>The HelperAgent cooperates with the <strong>LoggingAgent</strong>. This latter is responsible for sending data to <a href="https://www.unionstationapp.com">Union Station</a>, a monitoring web service. If you didn’t explicitly tell Phusion Passenger to send data to Union Station, then the LoggingAgent sits idle and does not consume resources.</p></div>
1270
+ <span class="anchor_helper" id="_ustrouter"></span><h4 data-anchor="_ustrouter">1.2.3. UstRouter</h4>
1271
+ <div class="paragraph"><p>The core cooperates with the <strong>UstRouter</strong>. This latter is responsible for sending data to <a href="https://www.unionstationapp.com">Union Station</a>, a monitoring web service. If you didn’t explicitly tell Phusion Passenger to send data to Union Station, then the UstRouter sits idle and does not consume resources.</p></div>
1272
1272
  </div>
1273
1273
  <div class="sect3">
1274
1274
  <span class="anchor_helper" id="_watchdog"></span><h4 data-anchor="_watchdog">1.2.4. Watchdog</h4>
1275
- <div class="paragraph"><p>The HelperAgent and the LoggingAgent contain complex logic, so they could contain bugs which could crash them.
1275
+ <div class="paragraph"><p>The core and the UstRouter contain complex logic, so they could contain bugs which could crash them.
1276
1276
  So as a safety measure, they are both monitored by the <strong>Watchdog</strong>. If either of them crash, they are restarted by the Watchdog. This setup seeks to ensure that the system stays up, no matter what.</p></div>
1277
1277
  <div class="paragraph"><p>You might now wonder: what happens if the Watchdog crashes? Shouldn’t the Watchdog be monitored by another Watchdog? We’ve contemplated this possibility, but the Watchdog is very simple, and since 2012 we haven’t seen a single report of the Watchdog crashing, nor have we been able to make it crash since that time. So, for the sake of keeping the codebase as simple as possible, we’ve chosen not to introduce multiple Watchdogs.</p></div>
1278
1278
  </div>
1279
1279
  <div class="sect3">
1280
1280
  <span class="anchor_helper" id="_command_line_tools"></span><h4 data-anchor="_command_line_tools">1.2.5. Command line tools</h4>
1281
- <div class="paragraph"><p>Finally, there is an array of <strong>command line tools</strong> which support Phusion Passenger. The installers — <span class="monospaced">passenger-install-*-module</span> — are responsible for installing Phusion Passenger. There are administrative tools such as <span class="monospaced">passenger-status</span> and <span class="monospaced">passenger-memory-stats</span>. And many more. Some of these tools may communicate with one of the agents. For example, the <span class="monospaced">passenger-status</span> queries the HelperAgent for information that the HelperAgent has collected. How this communication is done, is described in <a href="#instance_state_and_communication">Instance state and communication</a>.</p></div>
1281
+ <div class="paragraph"><p>Finally, there is an array of <strong>command line tools</strong> which support Phusion Passenger. The installers — <span class="monospaced">passenger-install-*-module</span> — are responsible for installing Phusion Passenger. There are administrative tools such as <span class="monospaced">passenger-status</span> and <span class="monospaced">passenger-memory-stats</span>. And many more. Some of these tools may communicate with one of the agents. For example, the <span class="monospaced">passenger-status</span> queries the core for information that the core has collected. How this communication is done, is described in <a href="#instance_state_and_communication">Instance state and communication</a>.</p></div>
1282
1282
  </div>
1283
1283
  <div class="sect3">
1284
1284
  <span class="anchor_helper" id="_passenger_standalone"></span><h4 data-anchor="_passenger_standalone">1.2.6. Passenger Standalone</h4>
@@ -1287,7 +1287,7 @@ So as a safety measure, they are both monitored by the <strong>Watchdog</strong>
1287
1287
  </div>
1288
1288
  <div class="sect2">
1289
1289
  <span class="anchor_helper" id="_build_system_and_source_tree"></span><h3 data-anchor="_build_system_and_source_tree">1.3. Build system and source tree</h3>
1290
- <div class="paragraph"><p>Phusion Passenger is written mostly in C++ and Ruby. The web server modules, HelperAgent, LoggingAgent and Watchdog are written in C++. Most command line tools are written in Ruby. You can find each component here:</p></div>
1290
+ <div class="paragraph"><p>Phusion Passenger is written mostly in C++ and Ruby. The web server modules, core, UstRouter and Watchdog are written in C++. Most command line tools are written in Ruby. You can find each component here:</p></div>
1291
1291
  <div class="ulist"><ul>
1292
1292
  <li>
1293
1293
  <p>
@@ -1296,7 +1296,7 @@ The web server modules can be found in <span class="monospaced">ext/apache2</spa
1296
1296
  </li>
1297
1297
  <li>
1298
1298
  <p>
1299
- The HelperAgent, LoggingAgent and Watchdog can be found in <span class="monospaced">ext/common/agents</span>.
1299
+ The Passenger core, UstRouter and Watchdog can be found in <span class="monospaced">ext/common/agent</span>.
1300
1300
  </p>
1301
1301
  </li>
1302
1302
  <li>
@@ -1346,17 +1346,17 @@ The Phusion Passenger module inside Nginx/Apache proceeds with starting the Watc
1346
1346
  </li>
1347
1347
  <li>
1348
1348
  <p>
1349
- The Watchdog first initializes a <a href="#instance_state_and_communication">"instance directory"</a>, which is a temporary directory containing files that will be used during the life time of this Phusion Passenger instance. For example, the directory contains Unix domain socket files, so that the different Phusion Passenger processes can communicate with each other. The Watchdog is implemented in <span class="monospaced">ext/common/agents/Watchdog/Main.cpp</span>.
1349
+ The Watchdog first initializes a <a href="#instance_state_and_communication">"instance directory"</a>, which is a temporary directory containing files that will be used during the life time of this Phusion Passenger instance. For example, the directory contains Unix domain socket files, so that the different Phusion Passenger processes can communicate with each other. The Watchdog is implemented in <span class="monospaced">ext/common/agent/Watchdog/Main.cpp</span>.
1350
1350
  </p>
1351
1351
  </li>
1352
1352
  <li>
1353
1353
  <p>
1354
- The Watchdog starts the HelperAgent and the LoggingAgent simultaneously. Each performs its own initialization.
1354
+ The Watchdog starts the Passenger core and the UstRouter simultaneously. Each performs its own initialization.
1355
1355
  </p>
1356
1356
  </li>
1357
1357
  <li>
1358
1358
  <p>
1359
- When the HelperAgent is done initializing, it will send a message back to the Watchdog saying that it’s done. The LoggingAgent does something similar. When the Watchdog has received both acknowledgment messages, it finishes initialization. If the Watchdog notices that one of the agents have exited without sending an acknowledgment message, then it enters an error state.
1359
+ When the core is done initializing, it will send a message back to the Watchdog saying that it’s done. The UstRouter does something similar. When the Watchdog has received both acknowledgment messages, it finishes initialization. If the Watchdog notices that one of the agents have exited without sending an acknowledgment message, then it enters an error state.
1360
1360
  </p>
1361
1361
  </li>
1362
1362
  <li>
@@ -1369,19 +1369,19 @@ The Watchdog reports successful startup back to the Phusion Passenger module tha
1369
1369
  </div>
1370
1370
  </div>
1371
1371
  <div class="sect1">
1372
- <span class="anchor_helper" id="helper_agent_architecture"></span><h2 data-anchor="helper_agent_architecture">3. HelperAgent architecture</h2>
1372
+ <span class="anchor_helper" id="passenger_core_architecture"></span><h2 data-anchor="passenger_core_architecture">3. Passenger core architecture</h2>
1373
1373
  <div class="sectionbody">
1374
1374
  <div class="paragraph"><p><span class="image">
1375
- <img src="images/helper_agent_core_architecture.png" alt="HelperAgent architecture">
1375
+ <img src="images/passenger_core_architecture.png" alt="Passenger core architecture">
1376
1376
  </span></p></div>
1377
- <div class="paragraph"><p>The HelperAgent consists of two subsystems. One is the <strong>request handling subsystem</strong>. The other is <strong>the ApplicationPool subsystem</strong>, which performs the bulk of process management. The HelperAgent also uses a number of support libraries. The largest third-party support libraries are shown in the diagram. Many more — internal — support libraries are used, but they’re omitted from the diagram. You can find these internal support libraries in the directory <span class="monospaced">ext/common/Utils</span>.</p></div>
1377
+ <div class="paragraph"><p>The Passenger core consists of two subsystems. One is the <strong>request handling subsystem</strong>. The other is <strong>the ApplicationPool subsystem</strong>, which performs the bulk of process management. The core also uses a number of support libraries. The largest third-party support libraries are shown in the diagram. Many more — internal — support libraries are used, but they’re omitted from the diagram. You can find these internal support libraries in the directory <span class="monospaced">ext/common/Utils</span>.</p></div>
1378
1378
  <div class="sect2">
1379
1379
  <span class="anchor_helper" id="_request_handling"></span><h3 data-anchor="_request_handling">3.1. Request handling</h3>
1380
- <div class="paragraph"><p>Recall that requests are first received from the web server. The web server serializes the request into a slightly modified version of <a href="http://en.wikipedia.org/wiki/SCGI">the SCGI format</a>, and sends it to the HelperAgent’s RequestHandler. The RequestHandler performs some work, and eventually sends back a regular HTTP response. The web server parses the RequestHandler response, and sends a response to the original HTTP client.</p></div>
1380
+ <div class="paragraph"><p>Recall that requests are first received from the web server. The web server serializes the request into a slightly modified version of <a href="http://en.wikipedia.org/wiki/SCGI">the SCGI format</a>, and sends it to the core’s RequestHandler. The RequestHandler performs some work, and eventually sends back a regular HTTP response. The web server parses the RequestHandler response, and sends a response to the original HTTP client.</p></div>
1381
1381
  <div class="paragraph"><p>The RequestHandler listens on a Unix domain socket file. This Unix domain socket file is called <span class="monospaced">request</span>, and is located in <a href="#instance_state_and_communication">the instance directory</a>.</p></div>
1382
1382
  <div class="sect3">
1383
1383
  <span class="anchor_helper" id="_one_client_per_request"></span><h4 data-anchor="_one_client_per_request">3.1.1. One client per request</h4>
1384
- <div class="paragraph"><p>The web server creates a new connection to the HelperAgent on every request. Thus, from the viewpoint of the RequestHandler, its client is the web server. Every time a client connects (i.e. a new request is forwarded), the RequestHandler creates a new Client object which represents that request. All request-specific state is stored inside the Client. After the RequestHandler is done processing a request, it closes the client socket.</p></div>
1384
+ <div class="paragraph"><p>The web server creates a new connection to the core on every request. Thus, from the viewpoint of the RequestHandler, its client is the web server. Every time a client connects (i.e. a new request is forwarded), the RequestHandler creates a new Client object which represents that request. All request-specific state is stored inside the Client. After the RequestHandler is done processing a request, it closes the client socket.</p></div>
1385
1385
  <div class="paragraph"><p>Note that in the diagram, a Client has a 0..1 association with RequestHandler. That’s because when a Client is disconnected, the pointer to the associated RequestHandler is set to NULL. There might be background operations left which still have a pointer to the Client. As soon as those background operations finish, they check whether the Client has a valid pointer to the RequestHandler. If so, they commit their work; if not, they discard their work. The Client is destroyed when all its associated background operations have finished.</p></div>
1386
1386
  </div>
1387
1387
  <div class="sect3">
@@ -1539,7 +1539,7 @@ DummySpawner (not shown in diagram) — only used in unit tests.
1539
1539
  <div class="sect1">
1540
1540
  <span class="anchor_helper" id="app_spawning_and_loading"></span><h2 data-anchor="app_spawning_and_loading">4. Application spawning and loading</h2>
1541
1541
  <div class="sectionbody">
1542
- <div class="paragraph"><p>Application processes are spawned from the HelperAgent process. Spawning a process involves a lot of <strong>preparation work</strong>, such as setting up communication channels, setting up the current working directory, environment variables, etc. This preparation work is done by <a href="#spawner_subsystem">a Spawner object</a>, together with various support executables.</p></div>
1542
+ <div class="paragraph"><p>Application processes are spawned from the Passenger core process. Spawning a process involves a lot of <strong>preparation work</strong>, such as setting up communication channels, setting up the current working directory, environment variables, etc. This preparation work is done by <a href="#spawner_subsystem">a Spawner object</a>, together with various support executables.</p></div>
1543
1543
  <div class="paragraph"><p>When preparation is done, your application’s entry point has to be loaded somehow. That loading is done through a language-specific <strong>loader program</strong>. The loader program communicates with the Spawner through the communication channel that was set up earlier, initializes the language-specific environment, sets up a server, and reports back to the Spawner. This communication is done through a certain <strong>protocol</strong>.</p></div>
1544
1544
  <div class="sect2">
1545
1545
  <span class="anchor_helper" id="_preparation_work"></span><h3 data-anchor="_preparation_work">4.1. Preparation work</h3>
@@ -1553,7 +1553,7 @@ DummySpawner (not shown in diagram) — only used in unit tests.
1553
1553
  </div>
1554
1554
  <div class="sect3">
1555
1555
  <span class="anchor_helper" id="_loading_spawnpreparer_possibly_through_bash"></span><h4 data-anchor="_loading_spawnpreparer_possibly_through_bash">4.1.2. Loading SpawnPreparer, possibly through bash</h4>
1556
- <div class="paragraph"><p>Because the HelperAgent is heavily multi-threaded, the child process has been forked by the Spawner <a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html">may only perform async-signal-safe operations</a>:</p></div>
1556
+ <div class="paragraph"><p>Because the Passenger core is heavily multi-threaded, the child process has been forked by the Spawner <a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html">may only perform async-signal-safe operations</a>:</p></div>
1557
1557
  <div class="quoteblock">
1558
1558
  <div class="content">"A process shall be created with a single thread. If a multi-threaded process calls fork(), the new process shall contain a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called. Fork handlers may be established by means of the pthread_atfork() function in order to maintain application invariants across fork() calls."</div>
1559
1559
  <div class="attribution">
@@ -1772,7 +1772,7 @@ The maximum number of <strong>concurrent connections</strong> the server support
1772
1772
  <div class="olist arabic"><ol class="arabic">
1773
1773
  <li>
1774
1774
  <p>
1775
- Just write the error message to stdout as you normally do, and abort without printing the <span class="monospaced">!&gt; Ready</span> message. The HelperAgent will read everything that the loader has written to stdout, and use it as the error message. This error message is considered to be plain text.
1775
+ Just write the error message to stdout as you normally do, and abort without printing the <span class="monospaced">!&gt; Ready</span> message. The Passenger core will read everything that the loader has written to stdout, and use it as the error message. This error message is considered to be plain text.
1776
1776
  </p>
1777
1777
  </li>
1778
1778
  <li>
@@ -1802,7 +1802,7 @@ No more clients will be routed to this particular process.
1802
1802
  </div>
1803
1803
  <div class="sect3">
1804
1804
  <span class="anchor_helper" id="_stdout_and_stderr_forwarding"></span><h4 data-anchor="_stdout_and_stderr_forwarding">4.2.7. Stdout and stderr forwarding</h4>
1805
- <div class="paragraph"><p>All lines that the loader writes to stdout, and that are not prefixed with `!&gt; `, are forwarded by the HelperAgent to its own stdout. Similarly, everything that the loader writes to stderr, whether prefixed with `!&gt; ` or not, is forwarded by the HelperAgent to its own stdout.</p></div>
1805
+ <div class="paragraph"><p>All lines that the loader writes to stdout, and that are not prefixed with `!&gt; `, are forwarded by the Passenger core to its own stdout. Similarly, everything that the loader writes to stderr, whether prefixed with `!&gt; ` or not, is forwarded by the Passenger core to its own stdout.</p></div>
1806
1806
  <div class="paragraph"><p>While the Spawner is still doing its work, it takes care of this forwarding by itself. Once the Spawner is done, it outsources this work to two PipeWatcher objects, each which spawns a background thread for this purpose.</p></div>
1807
1807
  </div>
1808
1808
  </div>
@@ -1838,7 +1838,7 @@ It sends a response back to the Spawner. This is similar to how the loader does
1838
1838
  </div>
1839
1839
  <div class="sect2">
1840
1840
  <span class="anchor_helper" id="app_types_registry"></span><h3 data-anchor="app_types_registry">4.4. The AppTypes registry</h3>
1841
- <div class="paragraph"><p>When the web server receives a request, the Phusion Passenger module inside it autodetects the type of application that the request belongs to. It does that by examening the filesystem and checking which one of the startup files exist. For example, if <span class="monospaced">config.ru</span> exists, then it assumes that it’s a Ruby app. Or if <span class="monospaced">app.js</span> exists, then it assumes that it’s a Node.js app. The Phusion Passenger module forwards the inferred application type to the HelperAgent.</p></div>
1841
+ <div class="paragraph"><p>When the web server receives a request, the Phusion Passenger module inside it autodetects the type of application that the request belongs to. It does that by examening the filesystem and checking which one of the startup files exist. For example, if <span class="monospaced">config.ru</span> exists, then it assumes that it’s a Ruby app. Or if <span class="monospaced">app.js</span> exists, then it assumes that it’s a Node.js app. The Phusion Passenger module forwards the inferred application type to the Passenger core.</p></div>
1842
1842
  <div class="paragraph"><p>Given an application type, the associated loader and preloader can be looked up.</p></div>
1843
1843
  <div class="paragraph"><p>Information about the supported application types, startup files, loaders and preloaders are defined in the following places:</p></div>
1844
1844
  <div class="ulist"><ul>
@@ -1869,7 +1869,7 @@ The method <span class="monospaced">looks_like_app_directory?</span> in the file
1869
1869
  <div class="sect1">
1870
1870
  <span class="anchor_helper" id="instance_state_and_communication"></span><h2 data-anchor="instance_state_and_communication">5. Instance state and communication</h2>
1871
1871
  <div class="sectionbody">
1872
- <div class="paragraph"><p>Every time you start Phusion Passenger, you’ve created a new <strong>instance</strong>. Every instance consists of multiple processes that work together (Watchdog, HelperAgent, LoggingAgent, application processes). All those processes have to be able to communicate with each other. Those processes must also <strong>not</strong> communicate with the processes belonging to other instances. For example, if you start Apache+Passenger <strong>and</strong> Nginx+Passenger, then we don’t want the HelperAgent that’s started from Apache to use LoggingAgent that’s started from Nginx.</p></div>
1872
+ <div class="paragraph"><p>Every time you start Phusion Passenger, you’ve created a new <strong>instance</strong>. Every instance consists of multiple processes that work together (Watchdog, Passenger core, UstRouter, application processes). All those processes have to be able to communicate with each other. Those processes must also <strong>not</strong> communicate with the processes belonging to other instances. For example, if you start Apache+Passenger <strong>and</strong> Nginx+Passenger, then we don’t want the Passenger core that’s started from Apache to use UstRouter that’s started from Nginx.</p></div>
1873
1873
  <div class="paragraph"><p>Clearly, the processes can’t listen on a specific TCP port for communication. Nor can they listen on a fixed Unix domain socket filename.</p></div>
1874
1874
  <div class="paragraph"><p>That is where the <em>instance directory</em> comes in. Every Phusion Passenger instance has its own, unique temporary directory. That directory is removed when the instance halts. The directory contains Unix domain socket files that the processes listen on. Every Phusion Passenger related process knows where its own instance directory is, and thus, knows how to communicate with other processes belonging to the same instance. The instance directory is implemented in <span class="monospaced">ext/common/InstanceDirectory.h</span>.</p></div>
1875
1875
  <div class="paragraph"><p>Administration tools such as <span class="monospaced">passenger-status</span> query information using instance directories. First, they check which instance directories exist on the system. If they find only one, then they query the sockets inside that sole instance directory. Otherwise, they abort with an error and ask the user to specifically select the instance to query.</p></div>
@@ -92,36 +92,36 @@ image:images/passenger_architecture_overview.png[An overview of Phusion Passenge
92
92
 
93
93
  Phusion Passenger is not a single, monolithic entity. Instead, it consists of multiple components and processes that work together. Part of the reason why Phusion Passenger is split like this, is because it's technically necessary (no other way to implement it). But another part of the reason is stability and robustness. Individual components can crash and can be restarted independently from each other. If we were to put everything inside a single process, then a crash will take down all of Phusion Passenger.
94
94
 
95
- Thus, if the HelperAgent crashes, or if an application process crashes, they can both be restarted without affecting the web server's stability.
95
+ Thus, if the Passenger core crashes, or if an application process crashes, they can both be restarted without affecting the web server's stability.
96
96
 
97
97
  ==== Web server module
98
98
 
99
- When an HTTP client sends a request, it is received by the web server (Nginx or Apache). Both Apache and Nginx can be extended with **modules**. Phusion Passenger provides such a module. The module is loaded into Nginx/Apache. It checks whether the request should be handled by a Phusion Passenger-served web application, and if so, forwards the request to the HelperAgent. The internal wire protocol used during this forwarding, is a modified version of link:http://en.wikipedia.org/wiki/SCGI[SCGI].
99
+ When an HTTP client sends a request, it is received by the web server (Nginx or Apache). Both Apache and Nginx can be extended with **modules**. Phusion Passenger provides such a module. The module is loaded into Nginx/Apache. It checks whether the request should be handled by a Phusion Passenger-served web application, and if so, forwards the request to the Passenger core. The internal wire protocol used during this forwarding, is a modified version of link:http://en.wikipedia.org/wiki/SCGI[SCGI].
100
100
 
101
- The Nginx module and Apache module have an entirely different code base. Their code bases are in `ext/nginx` and `ext/apache2`, respectively. Both modules are relatively small because they outsource most logic to the HelperAgent, and because they utilize a common library (`ext/common`). This allows us to support both Nginx and Apache without having to write a lot of things twice.
101
+ The Nginx module and Apache module have an entirely different code base. Their code bases are in `ext/nginx` and `ext/apache2`, respectively. Both modules are relatively small because they outsource most logic to the Passenger core, and because they utilize a common library (`ext/common`). This allows us to support both Nginx and Apache without having to write a lot of things twice.
102
102
 
103
- ==== HelperAgent
103
+ ==== Passenger core
104
104
 
105
- The **HelperAgent** is Phusion Passenger's core, where most of the processing is done. The HelperAgent keeps track of which application processes currently exist, and using load balancing rules, determines which process a request should be forwarded to. The HelperAgent also takes care of **application spawning**: if it determines that having more application processes is necessary or beneficial, then it will make that happen. Process spawning is subject to user-configured limits: the HelperAgent will never spawn more processes than a user-configured maximum.
105
+ The **Passenger core** is where most of the processing is done. The core keeps track of which application processes currently exist, and using load balancing rules, determines which process a request should be forwarded to. The core also takes care of **application spawning**: if it determines that having more application processes is necessary or beneficial, then it will make that happen. Process spawning is subject to user-configured limits: the core will never spawn more processes than a user-configured maximum.
106
106
 
107
- The HelperAgent also has monitoring and statistics gathering capabilities. It constantly keeps track of applications' memory usage, how many requests they've handled, etc. This information can later be queried from administration tools. And if an application process crashes, the HelperAgent restarts it.
107
+ The core also has monitoring and statistics gathering capabilities. It constantly keeps track of applications' memory usage, how many requests they've handled, etc. This information can later be queried from administration tools. And if an application process crashes, the core restarts it.
108
108
 
109
- The HelperAgent is by far the largest and most complex part of the system, but it is itself composed of several smaller subsystems. Most of the <<helper_agent_architecture,HelperAgent architecture>> chapter is devoted to describing the HelperAgent.
109
+ The core is by far the largest and most complex part of the system, but it is itself composed of several smaller subsystems. Most of the <<passenger_core_architecture,core architecture>> chapter is devoted to describing the core.
110
110
 
111
- ==== LoggingAgent
111
+ ==== UstRouter
112
112
 
113
- The HelperAgent cooperates with the **LoggingAgent**. This latter is responsible for sending data to link:https://www.unionstationapp.com[Union Station], a monitoring web service. If you didn't explicitly tell Phusion Passenger to send data to Union Station, then the LoggingAgent sits idle and does not consume resources.
113
+ The core cooperates with the **UstRouter**. This latter is responsible for sending data to link:https://www.unionstationapp.com[Union Station], a monitoring web service. If you didn't explicitly tell Phusion Passenger to send data to Union Station, then the UstRouter sits idle and does not consume resources.
114
114
 
115
115
  ==== Watchdog
116
116
 
117
- The HelperAgent and the LoggingAgent contain complex logic, so they could contain bugs which could crash them.
117
+ The core and the UstRouter contain complex logic, so they could contain bugs which could crash them.
118
118
  So as a safety measure, they are both monitored by the **Watchdog**. If either of them crash, they are restarted by the Watchdog. This setup seeks to ensure that the system stays up, no matter what.
119
119
 
120
120
  You might now wonder: what happens if the Watchdog crashes? Shouldn't the Watchdog be monitored by another Watchdog? We've contemplated this possibility, but the Watchdog is very simple, and since 2012 we haven't seen a single report of the Watchdog crashing, nor have we been able to make it crash since that time. So, for the sake of keeping the codebase as simple as possible, we've chosen not to introduce multiple Watchdogs.
121
121
 
122
122
  ==== Command line tools
123
123
 
124
- Finally, there is an array of **command line tools** which support Phusion Passenger. The installers -- `passenger-install-*-module` -- are responsible for installing Phusion Passenger. There are administrative tools such as `passenger-status` and `passenger-memory-stats`. And many more. Some of these tools may communicate with one of the agents. For example, the `passenger-status` queries the HelperAgent for information that the HelperAgent has collected. How this communication is done, is described in <<instance_state_and_communication,Instance state and communication>>.
124
+ Finally, there is an array of **command line tools** which support Phusion Passenger. The installers -- `passenger-install-*-module` -- are responsible for installing Phusion Passenger. There are administrative tools such as `passenger-status` and `passenger-memory-stats`. And many more. Some of these tools may communicate with one of the agents. For example, the `passenger-status` queries the core for information that the core has collected. How this communication is done, is described in <<instance_state_and_communication,Instance state and communication>>.
125
125
 
126
126
  ==== Passenger Standalone
127
127
 
@@ -129,10 +129,10 @@ You might have noticed that Phusion Passenger Standalone is not part of the diag
129
129
 
130
130
  === Build system and source tree
131
131
 
132
- Phusion Passenger is written mostly in C\++ and Ruby. The web server modules, HelperAgent, LoggingAgent and Watchdog are written in C++. Most command line tools are written in Ruby. You can find each component here:
132
+ Phusion Passenger is written mostly in C\++ and Ruby. The web server modules, core, UstRouter and Watchdog are written in C++. Most command line tools are written in Ruby. You can find each component here:
133
133
 
134
134
  * The web server modules can be found in `ext/apache2` and `ext/nginx`.
135
- * The HelperAgent, LoggingAgent and Watchdog can be found in `ext/common/agents`.
135
+ * The Passenger core, UstRouter and Watchdog can be found in `ext/common/agent`.
136
136
  * The command line tools can be found in `bin`, with some parts of their code in `lib`.
137
137
 
138
138
  More information can be found in the link:https://github.com/phusion/passenger/blob/master/CONTRIBUTING.md[Contributors Guide]. This guide also teaches you how to compile Phusion Passenger.
@@ -152,33 +152,33 @@ Phusion Passenger initializes as follows.
152
152
  * `ext/apache2/Hooks.cpp`, in the constructor for the `Hooks` class.
153
153
  * `ext/common/AgentsStarter.h` and `AgentsStarter.cpp`. Most of the logic pertaining starting the Watchdog is in this file.
154
154
 
155
- 3. The Watchdog first initializes a <<instance_state_and_communication,"instance directory">>, which is a temporary directory containing files that will be used during the life time of this Phusion Passenger instance. For example, the directory contains Unix domain socket files, so that the different Phusion Passenger processes can communicate with each other. The Watchdog is implemented in `ext/common/agents/Watchdog/Main.cpp`.
155
+ 3. The Watchdog first initializes a <<instance_state_and_communication,"instance directory">>, which is a temporary directory containing files that will be used during the life time of this Phusion Passenger instance. For example, the directory contains Unix domain socket files, so that the different Phusion Passenger processes can communicate with each other. The Watchdog is implemented in `ext/common/agent/Watchdog/Main.cpp`.
156
156
 
157
- 4. The Watchdog starts the HelperAgent and the LoggingAgent simultaneously. Each performs its own initialization.
157
+ 4. The Watchdog starts the Passenger core and the UstRouter simultaneously. Each performs its own initialization.
158
158
 
159
- 5. When the HelperAgent is done initializing, it will send a message back to the Watchdog saying that it's done. The LoggingAgent does something similar. When the Watchdog has received both acknowledgment messages, it finishes initialization. If the Watchdog notices that one of the agents have exited without sending an acknowledgment message, then it enters an error state.
159
+ 5. When the core is done initializing, it will send a message back to the Watchdog saying that it's done. The UstRouter does something similar. When the Watchdog has received both acknowledgment messages, it finishes initialization. If the Watchdog notices that one of the agents have exited without sending an acknowledgment message, then it enters an error state.
160
160
 
161
161
  6. The Watchdog reports successful startup back to the Phusion Passenger module that's running inside Nginx/Apache. Or, if initialization didn't success, the Watchdog reports back an error. The Phusion Passenger module inside Nginx/Apache then logs the error.
162
162
 
163
163
  After initialization, Phusion Passenger is ready to receive and to process requests.
164
164
 
165
165
 
166
- [[helper_agent_architecture]]
167
- == HelperAgent architecture
166
+ [[passenger_core_architecture]]
167
+ == Passenger core architecture
168
168
 
169
- image:images/helper_agent_core_architecture.png[HelperAgent architecture]
169
+ image:images/passenger_core_architecture.png[Passenger core architecture]
170
170
 
171
- The HelperAgent consists of two subsystems. One is the *request handling subsystem*. The other is *the ApplicationPool subsystem*, which performs the bulk of process management. The HelperAgent also uses a number of support libraries. The largest third-party support libraries are shown in the diagram. Many more -- internal -- support libraries are used, but they're omitted from the diagram. You can find these internal support libraries in the directory `ext/common/Utils`.
171
+ The Passenger core consists of two subsystems. One is the *request handling subsystem*. The other is *the ApplicationPool subsystem*, which performs the bulk of process management. The core also uses a number of support libraries. The largest third-party support libraries are shown in the diagram. Many more -- internal -- support libraries are used, but they're omitted from the diagram. You can find these internal support libraries in the directory `ext/common/Utils`.
172
172
 
173
173
  === Request handling
174
174
 
175
- Recall that requests are first received from the web server. The web server serializes the request into a slightly modified version of link:http://en.wikipedia.org/wiki/SCGI[the SCGI format], and sends it to the HelperAgent's RequestHandler. The RequestHandler performs some work, and eventually sends back a regular HTTP response. The web server parses the RequestHandler response, and sends a response to the original HTTP client.
175
+ Recall that requests are first received from the web server. The web server serializes the request into a slightly modified version of link:http://en.wikipedia.org/wiki/SCGI[the SCGI format], and sends it to the core's RequestHandler. The RequestHandler performs some work, and eventually sends back a regular HTTP response. The web server parses the RequestHandler response, and sends a response to the original HTTP client.
176
176
 
177
177
  The RequestHandler listens on a Unix domain socket file. This Unix domain socket file is called `request`, and is located in <<instance_state_and_communication,the instance directory>>.
178
178
 
179
179
  ==== One client per request
180
180
 
181
- The web server creates a new connection to the HelperAgent on every request. Thus, from the viewpoint of the RequestHandler, its client is the web server. Every time a client connects (i.e. a new request is forwarded), the RequestHandler creates a new Client object which represents that request. All request-specific state is stored inside the Client. After the RequestHandler is done processing a request, it closes the client socket.
181
+ The web server creates a new connection to the core on every request. Thus, from the viewpoint of the RequestHandler, its client is the web server. Every time a client connects (i.e. a new request is forwarded), the RequestHandler creates a new Client object which represents that request. All request-specific state is stored inside the Client. After the RequestHandler is done processing a request, it closes the client socket.
182
182
 
183
183
  Note that in the diagram, a Client has a 0..1 association with RequestHandler. That's because when a Client is disconnected, the pointer to the associated RequestHandler is set to NULL. There might be background operations left which still have a pointer to the Client. As soon as those background operations finish, they check whether the Client has a valid pointer to the RequestHandler. If so, they commit their work; if not, they discard their work. The Client is destroyed when all its associated background operations have finished.
184
184
 
@@ -257,7 +257,7 @@ The details of the spawning process is described in <<app_spawning_and_loading,A
257
257
  [[app_spawning_and_loading]]
258
258
  == Application spawning and loading
259
259
 
260
- Application processes are spawned from the HelperAgent process. Spawning a process involves a lot of **preparation work**, such as setting up communication channels, setting up the current working directory, environment variables, etc. This preparation work is done by <<spawner_subsystem,a Spawner object>>, together with various support executables.
260
+ Application processes are spawned from the Passenger core process. Spawning a process involves a lot of **preparation work**, such as setting up communication channels, setting up the current working directory, environment variables, etc. This preparation work is done by <<spawner_subsystem,a Spawner object>>, together with various support executables.
261
261
 
262
262
  When preparation is done, your application's entry point has to be loaded somehow. That loading is done through a language-specific **loader program**. The loader program communicates with the Spawner through the communication channel that was set up earlier, initializes the language-specific environment, sets up a server, and reports back to the Spawner. This communication is done through a certain **protocol**.
263
263
 
@@ -274,7 +274,7 @@ The communication channel in question is -- from the viewpoint of the (pre)loade
274
274
 
275
275
  ==== Loading SpawnPreparer, possibly through bash
276
276
 
277
- Because the HelperAgent is heavily multi-threaded, the child process has been forked by the Spawner link:http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html[may only perform async-signal-safe operations]:
277
+ Because the Passenger core is heavily multi-threaded, the child process has been forked by the Spawner link:http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html[may only perform async-signal-safe operations]:
278
278
 
279
279
  [quote, The Open Group's POSIX specification, fork() man page]
280
280
  "A process shall be created with a single thread. If a multi-threaded process calls fork(), the new process shall contain a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called. Fork handlers may be established by means of the pthread_atfork() function in order to maintain application invariants across fork() calls."
@@ -417,7 +417,7 @@ After reporting readiness, the loader can <<loader_main_loop,enter a main loop a
417
417
 
418
418
  If something goes wrong in any of the stages, the loader can report an error in two ways:
419
419
 
420
- 1. Just write the error message to stdout as you normally do, and abort without printing the `!> Ready` message. The HelperAgent will read everything that the loader has written to stdout, and use it as the error message. This error message is considered to be plain text.
420
+ 1. Just write the error message to stdout as you normally do, and abort without printing the `!> Ready` message. The Passenger core will read everything that the loader has written to stdout, and use it as the error message. This error message is considered to be plain text.
421
421
  2. Abort after printing a special `!> Error` message. The loader can signal that the message is HTML. The RequestHandler will format the error message as HTML.
422
422
 
423
423
  [[loader_main_loop]]
@@ -434,7 +434,7 @@ If the server was listening on a Unix domain socket file, then the loader doesn'
434
434
 
435
435
  ==== Stdout and stderr forwarding
436
436
 
437
- All lines that the loader writes to stdout, and that are not prefixed with `!> `, are forwarded by the HelperAgent to its own stdout. Similarly, everything that the loader writes to stderr, whether prefixed with `!> ` or not, is forwarded by the HelperAgent to its own stdout.
437
+ All lines that the loader writes to stdout, and that are not prefixed with `!> `, are forwarded by the Passenger core to its own stdout. Similarly, everything that the loader writes to stderr, whether prefixed with `!> ` or not, is forwarded by the Passenger core to its own stdout.
438
438
 
439
439
  While the Spawner is still doing its work, it takes care of this forwarding by itself. Once the Spawner is done, it outsources this work to two PipeWatcher objects, each which spawns a background thread for this purpose.
440
440
 
@@ -459,7 +459,7 @@ When a spawn command is received, the preloader forks off a child process (which
459
459
  [[app_types_registry]]
460
460
  === The AppTypes registry
461
461
 
462
- When the web server receives a request, the Phusion Passenger module inside it autodetects the type of application that the request belongs to. It does that by examening the filesystem and checking which one of the startup files exist. For example, if `config.ru` exists, then it assumes that it's a Ruby app. Or if `app.js` exists, then it assumes that it's a Node.js app. The Phusion Passenger module forwards the inferred application type to the HelperAgent.
462
+ When the web server receives a request, the Phusion Passenger module inside it autodetects the type of application that the request belongs to. It does that by examening the filesystem and checking which one of the startup files exist. For example, if `config.ru` exists, then it assumes that it's a Ruby app. Or if `app.js` exists, then it assumes that it's a Node.js app. The Phusion Passenger module forwards the inferred application type to the Passenger core.
463
463
 
464
464
  Given an application type, the associated loader and preloader can be looked up.
465
465
 
@@ -474,7 +474,7 @@ Information about the supported application types, startup files, loaders and pr
474
474
  [[instance_state_and_communication]]
475
475
  == Instance state and communication
476
476
 
477
- Every time you start Phusion Passenger, you've created a new *instance*. Every instance consists of multiple processes that work together (Watchdog, HelperAgent, LoggingAgent, application processes). All those processes have to be able to communicate with each other. Those processes must also *not* communicate with the processes belonging to other instances. For example, if you start Apache+Passenger *and* Nginx+Passenger, then we don't want the HelperAgent that's started from Apache to use LoggingAgent that's started from Nginx.
477
+ Every time you start Phusion Passenger, you've created a new *instance*. Every instance consists of multiple processes that work together (Watchdog, Passenger core, UstRouter, application processes). All those processes have to be able to communicate with each other. Those processes must also *not* communicate with the processes belonging to other instances. For example, if you start Apache+Passenger *and* Nginx+Passenger, then we don't want the Passenger core that's started from Apache to use UstRouter that's started from Nginx.
478
478
 
479
479
  Clearly, the processes can't listen on a specific TCP port for communication. Nor can they listen on a fixed Unix domain socket filename.
480
480
 
@@ -566,15 +566,15 @@ PassengerThreadCount 195
566
566
 
567
567
  <p>In certain situations, using the builtin HTTP engine in Passenger Standalone may yield some performance benefits because it skips a layer of processing.</p>
568
568
 
569
- <p>Passenger normally works by integrating into Nginx or Apache. As described in the <a href="Design%20and%20architecture.html">Design &amp; Architecture</a> document, requests are first handled by Nginx or Apache, and then forwarded to the Passenger core process (the HelperAgent) and the application process. This architecture provides various benefits, such as security benefits (Nginx and Apache's HTTP connection handling routines are thoroughly battle-tested and secure) and feature benefits (e.g. Gzip compression, superb static file handling).</p>
569
+ <p>Passenger normally works by integrating into Nginx or Apache. As described in the <a href="Design%20and%20Architecture.html">Design &amp; Architecture</a> document, requests are first handled by Nginx or Apache, and then forwarded to the Passenger core process (the Passenger core) and the application process. This architecture provides various benefits, such as security benefits (Nginx and Apache's HTTP connection handling routines are thoroughly battle-tested and secure) and feature benefits (e.g. Gzip compression, superb static file handling).</p>
570
570
 
571
571
  <p>This is even true if you use the Standalone mode. Although it acts standalone, it is implemented under the hood by running Passenger in a builtin Nginx engine.</p>
572
572
 
573
573
  <p>However, the fact that all requests go through Nginx or Apache means that there is a slight overhead, which can be avoided. This overhead is small (much smaller than typical application and network overhead), and using Nginx or Apache is very useful, but in certain special situations it may be beneficial to skip this layer.</p>
574
574
 
575
575
  <ul>
576
- <li>In <strong>microbenchmarks</strong>, the overhead of Nginx and Apache are very noticeable. Removing Nginx and Apache from the setup, and benchmarking against the Passenger HelperAgent directly, will yield much better results.</li>
577
- <li>In some <strong>multi-server setups</strong>, Nginx and Apache may be redundant. Recall that in typical multi-server setups there is a load balancer which forwards requests to one of the many web servers. Each web server in this setup runs Passenger. But the load balancer is sometimes already responsible for many of the tasks that Nginx and Apache perform, e.g. the secure handling of HTTP connections, buffering, slow client protection or even static file serving. In these cases, removing Nginx and Apache from the web servers and load balancing to the Passenger HelperAgent directly may have a minor improvement on performance.</li>
576
+ <li>In <strong>microbenchmarks</strong>, the overhead of Nginx and Apache are very noticeable. Removing Nginx and Apache from the setup, and benchmarking against the Passenger core directly, will yield much better results.</li>
577
+ <li>In some <strong>multi-server setups</strong>, Nginx and Apache may be redundant. Recall that in typical multi-server setups there is a load balancer which forwards requests to one of the many web servers. Each web server in this setup runs Passenger. But the load balancer is sometimes already responsible for many of the tasks that Nginx and Apache perform, e.g. the secure handling of HTTP connections, buffering, slow client protection or even static file serving. In these cases, removing Nginx and Apache from the web servers and load balancing to the Passenger core directly may have a minor improvement on performance.</li>
578
578
  </ul>
579
579
 
580
580
 
@@ -360,14 +360,14 @@ Phusion Passenger supports out-of-band garbage collection for Ruby apps. With th
360
360
 
361
361
  In certain situations, using the builtin HTTP engine in Passenger Standalone may yield some performance benefits because it skips a layer of processing.
362
362
 
363
- Passenger normally works by integrating into Nginx or Apache. As described in the [Design & Architecture](Design%20and%20architecture.html) document, requests are first handled by Nginx or Apache, and then forwarded to the Passenger core process (the HelperAgent) and the application process. This architecture provides various benefits, such as security benefits (Nginx and Apache's HTTP connection handling routines are thoroughly battle-tested and secure) and feature benefits (e.g. Gzip compression, superb static file handling).
363
+ Passenger normally works by integrating into Nginx or Apache. As described in the [Design & Architecture](Design%20and%20Architecture.html) document, requests are first handled by Nginx or Apache, and then forwarded to the Passenger core process (the Passenger core) and the application process. This architecture provides various benefits, such as security benefits (Nginx and Apache's HTTP connection handling routines are thoroughly battle-tested and secure) and feature benefits (e.g. Gzip compression, superb static file handling).
364
364
 
365
365
  This is even true if you use the Standalone mode. Although it acts standalone, it is implemented under the hood by running Passenger in a builtin Nginx engine.
366
366
 
367
367
  However, the fact that all requests go through Nginx or Apache means that there is a slight overhead, which can be avoided. This overhead is small (much smaller than typical application and network overhead), and using Nginx or Apache is very useful, but in certain special situations it may be beneficial to skip this layer.
368
368
 
369
- * In **microbenchmarks**, the overhead of Nginx and Apache are very noticeable. Removing Nginx and Apache from the setup, and benchmarking against the Passenger HelperAgent directly, will yield much better results.
370
- * In some **multi-server setups**, Nginx and Apache may be redundant. Recall that in typical multi-server setups there is a load balancer which forwards requests to one of the many web servers. Each web server in this setup runs Passenger. But the load balancer is sometimes already responsible for many of the tasks that Nginx and Apache perform, e.g. the secure handling of HTTP connections, buffering, slow client protection or even static file serving. In these cases, removing Nginx and Apache from the web servers and load balancing to the Passenger HelperAgent directly may have a minor improvement on performance.
369
+ * In **microbenchmarks**, the overhead of Nginx and Apache are very noticeable. Removing Nginx and Apache from the setup, and benchmarking against the Passenger core directly, will yield much better results.
370
+ * In some **multi-server setups**, Nginx and Apache may be redundant. Recall that in typical multi-server setups there is a load balancer which forwards requests to one of the many web servers. Each web server in this setup runs Passenger. But the load balancer is sometimes already responsible for many of the tasks that Nginx and Apache perform, e.g. the secure handling of HTTP connections, buffering, slow client protection or even static file serving. In these cases, removing Nginx and Apache from the web servers and load balancing to the Passenger core directly may have a minor improvement on performance.
371
371
 
372
372
  Nginx and Apache can be removed by using Passenger's builtin HTTP engine. By using this engine, Passenger will listen directly on a socket for HTTP requests, without using Nginx or Apache.
373
373
 
@@ -1441,7 +1441,7 @@ width:100%;
1441
1441
  <td class="tableblock halign-left valign-top"><p class="tableblock">2.6</p></td>
1442
1442
  </tr>
1443
1443
  <tr>
1444
- <td class="tableblock halign-left valign-top"><p class="tableblock">Node.js</p></td>
1444
+ <td class="tableblock halign-left valign-top"><p class="tableblock">Node.js/io.js</p></td>
1445
1445
  <td class="tableblock halign-left valign-top"><p class="tableblock">0.10</p></td>
1446
1446
  </tr>
1447
1447
  <tr>
@@ -2048,7 +2048,7 @@ kill PID_OF_FLYING_PASSENGER</pre>
2048
2048
  <pre>passenger-memory-stats</pre>
2049
2049
  </div>
2050
2050
  </div>
2051
- <div class="paragraph"><p>You should see the web server processes as well as a number of Phusion Passenger processes (e.g. PassengerWatchdog, PassengerHelperAgent). Congratulations, Phusion Passenger is now installed and running!</p></div>
2051
+ <div class="paragraph"><p>You should see the web server processes as well as a number of Phusion Passenger processes (e.g. PassengerAgent watchdog, PassengerAgent core). Congratulations, Phusion Passenger is now installed and running!</p></div>
2052
2052
  <div class="paragraph"><p>If the output is not as expected, then please refer to the <a href="#troubleshooting">Troubleshooting</a> section.</p></div>
2053
2053
  </div>
2054
2054
  <div class="sect2">
@@ -2137,7 +2137,7 @@ configuration file. However, it doesn’t copy any files to outside the Phusion
2137
2137
  <pre>./bin/passenger-memory-stats</pre>
2138
2138
  </div>
2139
2139
  </div>
2140
- <div class="paragraph"><p>You should see the web server processes as well as a number of Phusion Passenger processes (e.g. PassengerWatchdog, PassengerHelperAgent). Congratulations, Phusion Passenger is now installed and running!</p></div>
2140
+ <div class="paragraph"><p>You should see the web server processes as well as a number of Phusion Passenger processes (e.g. PassengerAgent watchdog, PassengerAgent core). Congratulations, Phusion Passenger is now installed and running!</p></div>
2141
2141
  <div class="paragraph"><p>If the output is not as expected, then please refer to the <a href="#troubleshooting">Troubleshooting</a> section.</p></div>
2142
2142
  </div>
2143
2143
  <div class="sect2">
@@ -4078,7 +4078,7 @@ In a virtual host configuration block.
4078
4078
  <a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><span class="anchor_helper" id="PassengerLoadShellEnvvars"></span><h4 data-comment-topic="passengerloadshellenvvars-on-off--1290yz1" data-anchor="PassengerLoadShellEnvvars">7.4.14. PassengerLoadShellEnvvars &lt;on|off&gt;</h4>
4079
4079
  <div class="paragraph"><p><strong>Introduced in version 4.0.20.</strong></p></div>
4080
4080
  <div class="paragraph"><p>Enables or disables the loading of shell environment variables before spawning the application.</p></div>
4081
- <div class="paragraph"><p>If this option is turned on, and the user’s shell is <span class="monospaced">bash</span>, then applications are loaded by running them with <span class="monospaced">bash -l -c</span>. Otherwise, they are loaded by running them directly from the <span class="monospaced">PassengerHelperAgent</span> process.</p></div>
4081
+ <div class="paragraph"><p>If this option is turned on, and the user’s shell is <span class="monospaced">bash</span>, then applications are loaded by running them with <span class="monospaced">bash -l -c</span>. Otherwise, they are loaded by running them directly from the <span class="monospaced">PassengerAgent core</span> process.</p></div>
4082
4082
  <div class="paragraph"><p>This option may occur in the following places:</p></div>
4083
4083
  <div class="ulist"><ul>
4084
4084
  <li>
@@ -4868,7 +4868,7 @@ In <em>.htaccess</em>, if <span class="monospaced">AllowOverride Limits</span> i
4868
4868
  queries <span class="monospaced">/proc</span> to obtain additional memory usage information that’s
4869
4869
  not obtainable through <span class="monospaced">ps</span>. You should ensure that the <span class="monospaced">ps</span> works
4870
4870
  correctly and that the <span class="monospaced">/proc</span> filesystem is accessible by the
4871
- <span class="monospaced">PassengerHelperAgent</span> process.</p></div>
4871
+ <span class="monospaced">PassengerAgent core</span> process.</p></div>
4872
4872
  </td>
4873
4873
  </tr></table>
4874
4874
  </div>
@@ -7044,7 +7044,7 @@ Attached process 28303 for app /webapps/foobar.
7044
7044
  <div class="sect3">
7045
7045
  <a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><span class="anchor_helper" id="_blocking_and_concurrency"></span><h4 data-comment-topic="blocking-and-concurrency-cxpbyu" data-anchor="_blocking_and_concurrency">10.9.3. Blocking and concurrency</h4>
7046
7046
  <div class="paragraph"><p>Except when otherwise documented, all hooks block in the background. That is, while your hook command is running, Phusion Passenger can still handle web requests, but the background thread which is running your hook will be blocked and won’t be able to perform any further operations. For example, if you wrote a hook script for the <span class="monospaced">attached_process</span> event, then Phusion Passenger won’t be able to attach further processes until your hook script finishes. You should therefore be careful when writing hook scripts.</p></div>
7047
- <div class="paragraph"><p>If you have a bug in your script and it blocks, then you will be able to see that using the command <span class="monospaced">passenger-status --show=backtraces</span> which prints the backtraces of all threads in the Phusion Passenger HelperAgent. Look for the <span class="monospaced">runSingleHookScript</span> function in the backtrace. The following example shows at line 2 that Phusion Passenger is waiting for the hook script <span class="monospaced">/home/phusion/badscript.sh</span>.</p></div>
7047
+ <div class="paragraph"><p>If you have a bug in your script and it blocks, then you will be able to see that using the command <span class="monospaced">passenger-status --show=backtraces</span> which prints the backtraces of all threads in the Phusion Passenger core. Look for the <span class="monospaced">runSingleHookScript</span> function in the backtrace. The following example shows at line 2 that Phusion Passenger is waiting for the hook script <span class="monospaced">/home/phusion/badscript.sh</span>.</p></div>
7048
7048
  <div class="listingblock">
7049
7049
  <div class="content monospaced">
7050
7050
  <pre>Thread 'Group process spawner: /home/phusion/webapp.test#default' (0x1062d4000):
@@ -7071,7 +7071,7 @@ Attached process 28303 for app /webapps/foobar.
7071
7071
  </dt>
7072
7072
  <dd>
7073
7073
  <p>
7074
- Called at the very beginning of Phusion Passenger’s life cycle, during the start of the Watchdog process. The first hook is called before initialization is performed (before the HelperAgent is started). Errors in the hook script cause Phusion Passenger to abort.
7074
+ Called at the very beginning of Phusion Passenger’s life cycle, during the start of the Watchdog process. The first hook is called before initialization is performed (before the Passenger core is started). Errors in the hook script cause Phusion Passenger to abort.
7075
7075
  </p>
7076
7076
  </dd>
7077
7077
  <dt class="hdlist1">
@@ -7578,13 +7578,25 @@ Phusion Passenger’s installer, build system and administration tools are writt
7578
7578
  <p>
7579
7579
  Certain internally used tools, such as the crash handler (which generates a backtrace in case Phusion Passenger crash) and the prespawn script (used to implement
7580
7580
  <a href="#PassengerPreStart">PassengerPreStart</a>)
7581
+ are written in Ruby as well.
7582
+ </p>
7583
+ </li>
7584
+ <li>
7585
+ <p>
7586
+ Ruby web application support is implemented in Ruby.
7587
+ </p>
7588
+ </li>
7589
+ <li>
7590
+ <p>
7591
+ If you use <a href="#flying_passenger">Flying Passenger</a>, then the Flying Passenger daemon is written in Ruby. The daemon is a small (less than 500 lines of code) and offloads most tasks to the C++ core.
7592
+ </p>
7593
+ </li>
7594
+ <li>
7595
+ <p>
7596
+ If you use <a href="Users%20guide%20Standalone.html">Phusion Passenger Standalone</a>, then the frontend (the <span class="monospaced">passenger</span> command) is written in Ruby. The frontend is small (less than 1500 lines of code) and offloads most tasks to the C++ core.
7581
7597
  </p>
7582
7598
  </li>
7583
7599
  </ul></div>
7584
- <div class="paragraph"><p>are written in Ruby as well.
7585
- * Ruby web application support is implemented in Ruby.
7586
- * If you use <a href="#flying_passenger">Flying Passenger</a>, then the Flying Passenger daemon is written in Ruby. The daemon is a small (less than 500 lines of code) and offloads most tasks to the C<span class="monospaced"> core.
7587
- * If you use <a href="Users%20guide%20Standalone.html">Phusion Passenger Standalone</a>, then the frontend (the <span class="monospaced">passenger</span> command) is written in Ruby. The frontend is small (less than 1500 lines of code) and offloads most tasks to the C</span> core.</p></div>
7588
7600
  <div class="paragraph"><p>Other than the aforementioned aspects, Phusion Passenger does not use Ruby during normal operation. For example, if you run Python WSGI web applications on Phusion Passenger, then there will be (almost) no Ruby code running on the system.</p></div>
7589
7601
  </div>
7590
7602
  <div class="sect3">
@@ -8380,7 +8392,7 @@ NOTE: Make sure your <span class="monospaced">~/.bashrc</span> is actually inclu
8380
8392
  </div>
8381
8393
  <div class="paragraph"><p>On Debian and Ubuntu, with an Apache installed through apt, Apache environment variables are defined in the file <span class="monospaced">/etc/apache2/envvars</span>. This is a shell script so environment variables must be specified with the shell syntax.</p></div>
8382
8394
  <div class="paragraph"><p>On Red Hat, Fedora, CentOS and ScientificLinux, with an Apache installed through YUM, Apache environment variables are defined in <span class="monospaced">/etc/sysconfig/httpd</span>.</p></div>
8383
- <div class="paragraph"><p>On OS X they are defined in <span class="monospaced">/System/Library/LaunchDaemons/org.apache.httpd.plist</span>, as explained <a href="/System/Library/LaunchDaemons/org.apache.httpd.plist">here on Stack Overflow</a>.</p></div>
8395
+ <div class="paragraph"><p>On OS X they are defined in <span class="monospaced">/System/Library/LaunchDaemons/org.apache.httpd.plist</span>, as explained <a href="http://stackoverflow.com/questions/6833939/path-environment-variable-for-apache2-on-mac">here on Stack Overflow</a>.</p></div>
8384
8396
  <div class="paragraph"><p>On other systems, or if you did not install Apache through the system’s package manager, the configuration file for environment variables is specific to the vendor that supplied Apache. There may not even be such a configuration file. You should contact the vendor for support.</p></div>
8385
8397
  </div>
8386
8398
  <div class="sect3">