passenger 5.0.8 → 5.0.9

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 (168) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +20 -0
  5. data/CHANGELOG +21 -0
  6. data/bin/passenger-install-apache2-module +3 -1
  7. data/build/agents.rb +7 -5
  8. data/build/basics.rb +3 -3
  9. data/build/common_library.rb +52 -30
  10. data/build/cxx_tests.rb +20 -13
  11. data/build/misc.rb +5 -5
  12. data/doc/Design and Architecture.html +1 -1
  13. data/doc/Design and Architecture.txt +1 -1
  14. data/doc/Packaging.html +4 -4
  15. data/doc/Packaging.txt.md +4 -4
  16. data/doc/Users guide Apache.html +22 -9
  17. data/doc/Users guide Apache.idmap.txt +4 -2
  18. data/doc/Users guide Apache.txt +2 -0
  19. data/doc/Users guide Nginx.html +22 -9
  20. data/doc/Users guide Nginx.idmap.txt +4 -2
  21. data/doc/Users guide Nginx.txt +2 -0
  22. data/doc/Users guide Standalone.html +14 -9
  23. data/doc/Users guide Standalone.idmap.txt +4 -2
  24. data/doc/users_guide_snippets/installation.txt +10 -6
  25. data/ext/apache2/Hooks.cpp +13 -2
  26. data/ext/common/ApplicationPool2/Pool/Inspection.h +8 -3
  27. data/ext/common/BackgroundEventLoop.cpp +249 -67
  28. data/ext/common/BackgroundEventLoop.h +5 -5
  29. data/ext/common/Constants.h +1 -1
  30. data/ext/common/InstanceDirectory.h +8 -6
  31. data/ext/common/ServerKit/Context.h +8 -2
  32. data/ext/common/ServerKit/FileBufferedChannel.h +262 -226
  33. data/ext/common/ServerKit/HeaderTable.h +28 -3
  34. data/ext/common/ServerKit/HttpHeaderParser.h +37 -13
  35. data/ext/common/ServerKit/HttpServer.h +17 -1
  36. data/ext/common/ServerKit/Implementation.cpp +2 -0
  37. data/ext/common/ServerKit/Server.h +25 -28
  38. data/ext/common/Utils/IOUtils.cpp +11 -0
  39. data/ext/common/Utils/ProcessMetricsCollector.h +4 -0
  40. data/ext/common/Utils/StrIntUtils.cpp +11 -7
  41. data/ext/common/Utils/StrIntUtils.h +1 -1
  42. data/ext/common/Utils/StrIntUtilsNoStrictAliasing.cpp +21 -16
  43. data/ext/common/agents/Base.cpp +6 -0
  44. data/ext/common/agents/Base.h +2 -0
  45. data/ext/common/agents/HelperAgent/AdminServer.h +25 -25
  46. data/ext/common/agents/HelperAgent/Main.cpp +37 -12
  47. data/ext/common/agents/HelperAgent/RequestHandler.h +18 -20
  48. data/ext/common/agents/HelperAgent/RequestHandler/AppResponse.h +4 -0
  49. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +10 -6
  50. data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +2 -0
  51. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +1 -1
  52. data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +1 -1
  53. data/ext/common/agents/HelperAgent/RequestHandler/Utils.cpp +9 -2
  54. data/ext/common/agents/HelperAgent/ResponseCache.h +11 -11
  55. data/ext/common/agents/LoggingAgent/AdminServer.h +8 -8
  56. data/ext/common/agents/LoggingAgent/Main.cpp +6 -5
  57. data/ext/common/agents/Watchdog/AdminServer.h +13 -13
  58. data/ext/common/agents/Watchdog/Main.cpp +8 -3
  59. data/ext/libuv/.gitignore +72 -0
  60. data/ext/libuv/AUTHORS +199 -0
  61. data/ext/libuv/ChangeLog +2023 -0
  62. data/ext/libuv/LICENSE +46 -0
  63. data/ext/libuv/Makefile.am +336 -0
  64. data/ext/libuv/README.md +197 -0
  65. data/ext/libuv/checksparse.sh +233 -0
  66. data/ext/libuv/common.gypi +210 -0
  67. data/ext/libuv/configure.ac +67 -0
  68. data/ext/libuv/gyp_uv.py +96 -0
  69. data/ext/libuv/include/android-ifaddrs.h +54 -0
  70. data/ext/libuv/include/pthread-fixes.h +72 -0
  71. data/ext/libuv/include/tree.h +768 -0
  72. data/ext/libuv/include/uv-aix.h +32 -0
  73. data/ext/libuv/include/uv-bsd.h +34 -0
  74. data/ext/libuv/include/uv-darwin.h +61 -0
  75. data/ext/libuv/include/uv-errno.h +418 -0
  76. data/ext/libuv/include/uv-linux.h +34 -0
  77. data/ext/libuv/include/uv-sunos.h +44 -0
  78. data/ext/libuv/include/uv-threadpool.h +37 -0
  79. data/ext/libuv/include/uv-unix.h +383 -0
  80. data/ext/libuv/include/uv-version.h +39 -0
  81. data/ext/libuv/include/uv.h +1455 -0
  82. data/ext/libuv/libuv.pc.in +11 -0
  83. data/ext/libuv/m4/.gitignore +4 -0
  84. data/ext/libuv/m4/as_case.m4 +21 -0
  85. data/ext/libuv/m4/libuv-check-flags.m4 +319 -0
  86. data/ext/libuv/src/fs-poll.c +255 -0
  87. data/ext/libuv/src/heap-inl.h +245 -0
  88. data/ext/libuv/src/inet.c +313 -0
  89. data/ext/libuv/src/queue.h +92 -0
  90. data/ext/libuv/src/threadpool.c +303 -0
  91. data/ext/libuv/src/unix/aix.c +1240 -0
  92. data/ext/libuv/src/unix/android-ifaddrs.c +703 -0
  93. data/ext/libuv/src/unix/async.c +284 -0
  94. data/ext/libuv/src/unix/atomic-ops.h +60 -0
  95. data/ext/libuv/src/unix/core.c +985 -0
  96. data/ext/libuv/src/unix/darwin-proctitle.c +206 -0
  97. data/ext/libuv/src/unix/darwin.c +331 -0
  98. data/ext/libuv/src/unix/dl.c +83 -0
  99. data/ext/libuv/src/unix/freebsd.c +435 -0
  100. data/ext/libuv/src/unix/fs.c +1189 -0
  101. data/ext/libuv/src/unix/fsevents.c +899 -0
  102. data/ext/libuv/src/unix/getaddrinfo.c +202 -0
  103. data/ext/libuv/src/unix/getnameinfo.c +120 -0
  104. data/ext/libuv/src/unix/internal.h +314 -0
  105. data/ext/libuv/src/unix/kqueue.c +418 -0
  106. data/ext/libuv/src/unix/linux-core.c +876 -0
  107. data/ext/libuv/src/unix/linux-inotify.c +257 -0
  108. data/ext/libuv/src/unix/linux-syscalls.c +471 -0
  109. data/ext/libuv/src/unix/linux-syscalls.h +158 -0
  110. data/ext/libuv/src/unix/loop-watcher.c +63 -0
  111. data/ext/libuv/src/unix/loop.c +135 -0
  112. data/ext/libuv/src/unix/netbsd.c +368 -0
  113. data/ext/libuv/src/unix/openbsd.c +384 -0
  114. data/ext/libuv/src/unix/pipe.c +288 -0
  115. data/ext/libuv/src/unix/poll.c +113 -0
  116. data/ext/libuv/src/unix/process.c +551 -0
  117. data/ext/libuv/src/unix/proctitle.c +102 -0
  118. data/ext/libuv/src/unix/pthread-fixes.c +103 -0
  119. data/ext/libuv/src/unix/signal.c +465 -0
  120. data/ext/libuv/src/unix/spinlock.h +53 -0
  121. data/ext/libuv/src/unix/stream.c +1598 -0
  122. data/ext/libuv/src/unix/sunos.c +763 -0
  123. data/ext/libuv/src/unix/tcp.c +327 -0
  124. data/ext/libuv/src/unix/thread.c +519 -0
  125. data/ext/libuv/src/unix/timer.c +172 -0
  126. data/ext/libuv/src/unix/tty.c +265 -0
  127. data/ext/libuv/src/unix/udp.c +833 -0
  128. data/ext/libuv/src/uv-common.c +544 -0
  129. data/ext/libuv/src/uv-common.h +214 -0
  130. data/ext/libuv/src/version.c +49 -0
  131. data/ext/libuv/uv.gyp +487 -0
  132. data/ext/nginx/ContentHandler.c +21 -10
  133. data/ext/nginx/ngx_http_passenger_module.c +7 -0
  134. data/ext/oxt/implementation.cpp +9 -2
  135. data/ext/oxt/initialize.hpp +5 -1
  136. data/lib/phusion_passenger.rb +3 -3
  137. data/lib/phusion_passenger/admin_tools/instance.rb +10 -6
  138. data/lib/phusion_passenger/admin_tools/instance_registry.rb +6 -2
  139. data/lib/phusion_passenger/packaging.rb +3 -4
  140. data/lib/phusion_passenger/platform_info.rb +13 -1
  141. data/lib/phusion_passenger/platform_info/apache.rb +15 -4
  142. data/lib/phusion_passenger/platform_info/apache_detector.rb +5 -1
  143. data/lib/phusion_passenger/rack/thread_handler_extension.rb +184 -99
  144. data/lib/phusion_passenger/request_handler/thread_handler.rb +13 -6
  145. data/lib/phusion_passenger/standalone/start_command.rb +2 -2
  146. data/resources/templates/apache2/apache_install_broken.txt.erb +2 -1
  147. metadata +99 -22
  148. metadata.gz.asc +7 -7
  149. data/ext/libeio/Changes +0 -76
  150. data/ext/libeio/LICENSE +0 -36
  151. data/ext/libeio/Makefile.am +0 -15
  152. data/ext/libeio/Makefile.in +0 -694
  153. data/ext/libeio/aclocal.m4 +0 -9418
  154. data/ext/libeio/autogen.sh +0 -3
  155. data/ext/libeio/config.guess +0 -1540
  156. data/ext/libeio/config.h.in +0 -136
  157. data/ext/libeio/config.sub +0 -1779
  158. data/ext/libeio/configure +0 -14822
  159. data/ext/libeio/configure.ac +0 -22
  160. data/ext/libeio/demo.c +0 -194
  161. data/ext/libeio/ecb.h +0 -714
  162. data/ext/libeio/eio.c +0 -2818
  163. data/ext/libeio/eio.h +0 -414
  164. data/ext/libeio/install-sh +0 -520
  165. data/ext/libeio/libeio.m4 +0 -195
  166. data/ext/libeio/ltmain.sh +0 -9636
  167. data/ext/libeio/missing +0 -376
  168. data/ext/libeio/xthread.h +0 -166
@@ -1638,4 +1638,10 @@ initializeAgentOptions(const char *processName, VariantMap &options,
1638
1638
  }
1639
1639
  }
1640
1640
 
1641
+ void
1642
+ shutdownAgent(VariantMap *agentOptions) {
1643
+ delete agentOptions;
1644
+ oxt::shutdown();
1645
+ }
1646
+
1641
1647
  } // namespace Passenger
@@ -48,6 +48,8 @@ void initializeAgentOptions(const char *processName, VariantMap &options,
48
48
  void installAgentAbortHandler();
49
49
  void installDiagnosticsDumper(DiagnosticsDumper func, void *userData);
50
50
 
51
+ void shutdownAgent(VariantMap *agentOptions);
52
+
51
53
  }
52
54
 
53
55
  #endif /* _PASSENGER_AGENT_BASE_H_ */
@@ -197,7 +197,7 @@ private:
197
197
  P_WARN(threadNumber);
198
198
  if (threadNumber < 1 || (unsigned int) threadNumber > requestHandlers.size()) {
199
199
  HeaderTable headers;
200
- headers.insert(req->pool, "content-type", "application/json");
200
+ headers.insert(req->pool, "Content-Type", "application/json");
201
201
  writeSimpleResponse(client, 400, &headers,
202
202
  "{ \"status\": \"error\", \"reason\": \"Invalid thread number\" }");
203
203
  if (!req->ended()) {
@@ -210,7 +210,7 @@ private:
210
210
  disconnectClient, requestHandlers[threadNumber - 1], results.str(1)));
211
211
 
212
212
  HeaderTable headers;
213
- headers.insert(req->pool, "content-type", "application/json");
213
+ headers.insert(req->pool, "Content-Type", "application/json");
214
214
  writeSimpleResponse(client, 200, &headers,
215
215
  "{ \"status\": \"ok\" }");
216
216
  if (!req->ended()) {
@@ -228,7 +228,7 @@ private:
228
228
  void processServerStatus(Client *client, Request *req) {
229
229
  if (authorize(client, req, READONLY)) {
230
230
  HeaderTable headers;
231
- headers.insert(req->pool, "content-type", "application/json");
231
+ headers.insert(req->pool, "Content-Type", "application/json");
232
232
 
233
233
  Json::Value doc;
234
234
  doc["threads"] = (Json::UInt) requestHandlers.size();
@@ -256,7 +256,7 @@ private:
256
256
  try {
257
257
  VariantMap params = parseQueryString(req->getQueryString());
258
258
  HeaderTable headers;
259
- headers.insert(req->pool, "content-type", "text/xml");
259
+ headers.insert(req->pool, "Content-Type", "text/xml");
260
260
  writeSimpleResponse(client, 200, &headers,
261
261
  psg_pstrdup(req->pool, appPool->toXml(
262
262
  params.getBool("secrets", false, false))));
@@ -277,7 +277,7 @@ private:
277
277
  ApplicationPool2::Pool::InspectOptions options(
278
278
  parseQueryString(req->getQueryString()));
279
279
  HeaderTable headers;
280
- headers.insert(req->pool, "content-type", "text/plain");
280
+ headers.insert(req->pool, "Content-Type", "text/plain");
281
281
  writeSimpleResponse(client, 200, &headers,
282
282
  psg_pstrdup(req->pool, appPool->inspect(options)));
283
283
  } catch (const SyntaxError &e) {
@@ -308,8 +308,8 @@ private:
308
308
  HeaderTable headers;
309
309
  RestartMethod method = ApplicationPool2::RM_DEFAULT;
310
310
 
311
- headers.insert(req->pool, "content-type", "application/json");
312
- headers.insert(req->pool, "cache-control", "no-cache, no-store, must-revalidate");
311
+ headers.insert(req->pool, "Content-Type", "application/json");
312
+ headers.insert(req->pool, "Cache-Control", "no-cache, no-store, must-revalidate");
313
313
 
314
314
  if (!req->jsonBody.isMember("name")) {
315
315
  endAsBadRequest(&client, &req, "Name required");
@@ -358,8 +358,8 @@ private:
358
358
  HeaderTable headers;
359
359
  const char *response;
360
360
 
361
- headers.insert(req->pool, "content-type", "application/json");
362
- headers.insert(req->pool, "cache-control", "no-cache, no-store, must-revalidate");
361
+ headers.insert(req->pool, "Content-Type", "application/json");
362
+ headers.insert(req->pool, "Cache-Control", "no-cache, no-store, must-revalidate");
363
363
 
364
364
  if (req->jsonBody.isMember("pid")) {
365
365
  pid_t pid = (pid_t) req->jsonBody["pid"].asUInt();
@@ -380,7 +380,7 @@ private:
380
380
  void processBacktraces(Client *client, Request *req) {
381
381
  if (authorize(client, req, READONLY)) {
382
382
  HeaderTable headers;
383
- headers.insert(req->pool, "content-type", "text/plain");
383
+ headers.insert(req->pool, "Content-Type", "text/plain");
384
384
  writeSimpleResponse(client, 200, &headers,
385
385
  psg_pstrdup(req->pool, oxt::thread::all_backtraces()));
386
386
  if (!req->ended()) {
@@ -394,8 +394,8 @@ private:
394
394
  void processPing(Client *client, Request *req) {
395
395
  if (authorize(client, req, READONLY)) {
396
396
  HeaderTable headers;
397
- headers.insert(req->pool, "cache-control", "no-cache, no-store, must-revalidate");
398
- headers.insert(req->pool, "content-type", "application/json");
397
+ headers.insert(req->pool, "Cache-Control", "no-cache, no-store, must-revalidate");
398
+ headers.insert(req->pool, "Content-Type", "application/json");
399
399
  writeSimpleResponse(client, 200, &headers, "{ \"status\": \"ok\" }");
400
400
  if (!req->ended()) {
401
401
  endRequest(&client, &req);
@@ -410,7 +410,7 @@ private:
410
410
  respondWith405(client, req);
411
411
  } else if (authorize(client, req, FULL)) {
412
412
  HeaderTable headers;
413
- headers.insert(req->pool, "content-type", "application/json");
413
+ headers.insert(req->pool, "Content-Type", "application/json");
414
414
  exitEvent->notify();
415
415
  writeSimpleResponse(client, 200, &headers, "{ \"status\": \"ok\" }");
416
416
  if (!req->ended()) {
@@ -436,7 +436,7 @@ private:
436
436
  respondWith405(client, req);
437
437
  } else if (authorize(client, req, FULL)) {
438
438
  HeaderTable headers;
439
- headers.insert(req->pool, "content-type", "application/json");
439
+ headers.insert(req->pool, "Content-Type", "application/json");
440
440
  for (unsigned int i = 0; i < requestHandlers.size(); i++) {
441
441
  requestHandlers[i]->getContext()->libev->runLater(boost::bind(
442
442
  garbageCollect, requestHandlers[i]));
@@ -464,7 +464,7 @@ private:
464
464
  string logFile = getLogFile();
465
465
  string fileDescriptorLogFile = getFileDescriptorLogFile();
466
466
 
467
- headers.insert(req->pool, "content-type", "application/json");
467
+ headers.insert(req->pool, "Content-Type", "application/json");
468
468
  Json::Value doc;
469
469
  requestHandlers[0]->getContext()->libev->runSync(boost::bind(
470
470
  getRequestHandlerConfig, requestHandlers[0], &doc));
@@ -501,8 +501,8 @@ private:
501
501
  HeaderTable headers;
502
502
  Json::Value &json = req->jsonBody;
503
503
 
504
- headers.insert(req->pool, "content-type", "application/json");
505
- headers.insert(req->pool, "cache-control", "no-cache, no-store, must-revalidate");
504
+ headers.insert(req->pool, "Content-Type", "application/json");
505
+ headers.insert(req->pool, "Cache-Control", "no-cache, no-store, must-revalidate");
506
506
 
507
507
  if (json.isMember("log_level")) {
508
508
  setLogLevel(json["log_level"].asInt());
@@ -556,7 +556,7 @@ private:
556
556
  } else if (authorize(client, req, FULL)) {
557
557
  int e;
558
558
  HeaderTable headers;
559
- headers.insert(req->pool, "content-type", "application/json");
559
+ headers.insert(req->pool, "Content-Type", "application/json");
560
560
 
561
561
  string logFile = getLogFile();
562
562
  if (logFile.empty()) {
@@ -620,8 +620,8 @@ private:
620
620
 
621
621
  void respondWith401(Client *client, Request *req) {
622
622
  HeaderTable headers;
623
- headers.insert(req->pool, "cache-control", "no-cache, no-store, must-revalidate");
624
- headers.insert(req->pool, "www-authenticate", "Basic realm=\"admin\"");
623
+ headers.insert(req->pool, "Cache-Control", "no-cache, no-store, must-revalidate");
624
+ headers.insert(req->pool, "WWW-Authenticate", "Basic realm=\"admin\"");
625
625
  writeSimpleResponse(client, 401, &headers, "Unauthorized");
626
626
  if (!req->ended()) {
627
627
  endRequest(&client, &req);
@@ -630,7 +630,7 @@ private:
630
630
 
631
631
  void respondWith404(Client *client, Request *req) {
632
632
  HeaderTable headers;
633
- headers.insert(req->pool, "cache-control", "no-cache, no-store, must-revalidate");
633
+ headers.insert(req->pool, "Cache-Control", "no-cache, no-store, must-revalidate");
634
634
  writeSimpleResponse(client, 404, &headers, "Not found");
635
635
  if (!req->ended()) {
636
636
  endRequest(&client, &req);
@@ -639,7 +639,7 @@ private:
639
639
 
640
640
  void respondWith405(Client *client, Request *req) {
641
641
  HeaderTable headers;
642
- headers.insert(req->pool, "cache-control", "no-cache, no-store, must-revalidate");
642
+ headers.insert(req->pool, "Cache-Control", "no-cache, no-store, must-revalidate");
643
643
  writeSimpleResponse(client, 405, &headers, "Method not allowed");
644
644
  if (!req->ended()) {
645
645
  endRequest(&client, &req);
@@ -648,7 +648,7 @@ private:
648
648
 
649
649
  void respondWith413(Client *client, Request *req) {
650
650
  HeaderTable headers;
651
- headers.insert(req->pool, "cache-control", "no-cache, no-store, must-revalidate");
651
+ headers.insert(req->pool, "Cache-Control", "no-cache, no-store, must-revalidate");
652
652
  writeSimpleResponse(client, 413, &headers, "Request body too large");
653
653
  if (!req->ended()) {
654
654
  endRequest(&client, &req);
@@ -657,8 +657,8 @@ private:
657
657
 
658
658
  void respondWith422(Client *client, Request *req, const StaticString &body) {
659
659
  HeaderTable headers;
660
- headers.insert(req->pool, "cache-control", "no-cache, no-store, must-revalidate");
661
- headers.insert(req->pool, "content-type", "text/plain; charset=utf-8");
660
+ headers.insert(req->pool, "Cache-Control", "no-cache, no-store, must-revalidate");
661
+ headers.insert(req->pool, "Content-Type", "text/plain; charset=utf-8");
662
662
  writeSimpleResponse(client, 422, &headers, body);
663
663
  if (!req->ended()) {
664
664
  endRequest(&client, &req);
@@ -159,6 +159,21 @@ namespace ServerAgent {
159
159
  adminServerFds[i] = -1;
160
160
  }
161
161
  }
162
+
163
+ ~WorkingObjects() {
164
+ delete prestarterThread;
165
+
166
+ vector<ThreadWorkingObjects>::iterator it, end = threadWorkingObjects.end();
167
+ for (it = threadWorkingObjects.begin(); it != end; it++) {
168
+ delete it->requestHandler;
169
+ delete it->serverKitContext;
170
+ delete it->bgloop;
171
+ }
172
+
173
+ delete adminWorkingObjects.adminServer;
174
+ delete adminWorkingObjects.serverKitContext;
175
+ delete adminWorkingObjects.bgloop;
176
+ }
162
177
  };
163
178
  } // namespace ServerAgent
164
179
  } // namespace Passenger
@@ -580,11 +595,12 @@ initializeNonPrivilegedWorkingObjects() {
580
595
  if (i == 0) {
581
596
  two.bgloop = firstLoop = new BackgroundEventLoop(true, true);
582
597
  } else {
583
- two.bgloop = new BackgroundEventLoop(true, false);
598
+ two.bgloop = new BackgroundEventLoop(true, true);
584
599
  }
585
600
 
586
601
  UPDATE_TRACE_POINT();
587
- two.serverKitContext = new ServerKit::Context(two.bgloop->safe);
602
+ two.serverKitContext = new ServerKit::Context(two.bgloop->safe,
603
+ two.bgloop->libuv_loop);
588
604
  two.serverKitContext->secureModePassword = wo->password;
589
605
  two.serverKitContext->defaultFileBufferedChannelConfig.bufferDir =
590
606
  options.get("data_buffer_dir");
@@ -607,26 +623,25 @@ initializeNonPrivilegedWorkingObjects() {
607
623
 
608
624
  UPDATE_TRACE_POINT();
609
625
  ev_signal_init(&wo->sigquitWatcher, printInfo, SIGQUIT);
610
- ev_signal_start(firstLoop->loop, &wo->sigquitWatcher);
626
+ ev_signal_start(firstLoop->libev_loop, &wo->sigquitWatcher);
611
627
  ev_signal_init(&wo->sigintWatcher, onTerminationSignal, SIGINT);
612
- ev_signal_start(firstLoop->loop, &wo->sigintWatcher);
628
+ ev_signal_start(firstLoop->libev_loop, &wo->sigintWatcher);
613
629
  ev_signal_init(&wo->sigtermWatcher, onTerminationSignal, SIGTERM);
614
- ev_signal_start(firstLoop->loop, &wo->sigtermWatcher);
630
+ ev_signal_start(firstLoop->libev_loop, &wo->sigtermWatcher);
615
631
 
616
632
  UPDATE_TRACE_POINT();
617
633
  if (!adminAddresses.empty()) {
618
634
  UPDATE_TRACE_POINT();
619
635
  AdminWorkingObjects *awo = &wo->adminWorkingObjects;
620
636
 
621
- awo->bgloop = new BackgroundEventLoop(true, false);
622
- awo->serverKitContext = new ServerKit::Context(awo->bgloop->safe);
637
+ awo->bgloop = new BackgroundEventLoop(true, true);
638
+ awo->serverKitContext = new ServerKit::Context(awo->bgloop->safe,
639
+ awo->bgloop->libuv_loop);
623
640
  awo->serverKitContext->secureModePassword = wo->password;
624
- // Configure a large threshold so that it uses libeio as little as possible.
625
- // libeio runs on the RequestHandler's first thread, and if there's a
626
- // problem there we don't want it to affect the admin server.
627
- awo->serverKitContext->defaultFileBufferedChannelConfig.threshold = 1024 * 1024;
628
641
  awo->serverKitContext->defaultFileBufferedChannelConfig.bufferDir =
629
642
  options.get("data_buffer_dir");
643
+ awo->serverKitContext->defaultFileBufferedChannelConfig.threshold =
644
+ options.getUint("file_buffer_threshold");
630
645
 
631
646
  UPDATE_TRACE_POINT();
632
647
  awo->adminServer = new ServerAgent::AdminServer(awo->serverKitContext);
@@ -912,10 +927,12 @@ cleanup() {
912
927
  for (unsigned i = 0; i < wo->threadWorkingObjects.size(); i++) {
913
928
  ThreadWorkingObjects *two = &wo->threadWorkingObjects[i];
914
929
  delete two->requestHandler;
930
+ two->requestHandler = NULL;
915
931
  }
916
932
  if (wo->prestarterThread != NULL) {
917
933
  wo->prestarterThread->interrupt_and_join();
918
934
  delete wo->prestarterThread;
935
+ wo->prestarterThread = NULL;
919
936
  }
920
937
  for (unsigned int i = 0; i < SERVER_KIT_MAX_SERVER_ENDPOINTS; i++) {
921
938
  if (wo->serverFds[i] != -1) {
@@ -926,6 +943,8 @@ cleanup() {
926
943
  }
927
944
  }
928
945
  deletePidFile();
946
+ delete workingObjects;
947
+ workingObjects = NULL;
929
948
  P_NOTICE(AGENT_EXE " server shutdown finished");
930
949
  }
931
950
 
@@ -960,6 +979,8 @@ runServer() {
960
979
  UPDATE_TRACE_POINT();
961
980
  cleanup();
962
981
  } catch (const tracable_exception &e) {
982
+ // We intentionally don't call cleanup() in
983
+ // order to avoid various destructor assertions.
963
984
  P_CRITICAL("ERROR: " << e.what() << "\n" << e.backtrace());
964
985
  deletePidFile();
965
986
  return 1;
@@ -1170,10 +1191,14 @@ sanityCheckOptions() {
1170
1191
 
1171
1192
  int
1172
1193
  serverMain(int argc, char *argv[]) {
1194
+ int ret;
1195
+
1173
1196
  agentsOptions = new VariantMap();
1174
1197
  *agentsOptions = initializeAgent(argc, &argv, AGENT_EXE " server", parseOptions,
1175
1198
  preinitialize, 2);
1176
1199
  setAgentsOptionsDefaults();
1177
1200
  sanityCheckOptions();
1178
- return runServer();
1201
+ ret = runServer();
1202
+ shutdownAgent(agentsOptions);
1203
+ return ret;
1179
1204
  }
@@ -150,8 +150,6 @@ private:
150
150
  HashedStaticString HTTP_CONNECTION;
151
151
  HashedStaticString HTTP_STATUS;
152
152
  HashedStaticString HTTP_TRANSFER_ENCODING;
153
- HashedStaticString HTTP_X_SENDFILE;
154
- HashedStaticString HTTP_X_ACCEL_REDIRECT;
155
153
 
156
154
  unsigned int threadNumber;
157
155
  StaticString serverLogName;
@@ -217,8 +215,6 @@ public:
217
215
  HTTP_CONNECTION("connection"),
218
216
  HTTP_STATUS("status"),
219
217
  HTTP_TRANSFER_ENCODING("transfer-encoding"),
220
- HTTP_X_SENDFILE("x-sendfile"),
221
- HTTP_X_ACCEL_REDIRECT("x-accel-redirect"),
222
218
 
223
219
  threadNumber(_threadNumber),
224
220
  turboCaching(getTurboCachingInitialState(_agentsOptions))
@@ -336,7 +332,7 @@ public:
336
332
  StaticString hostStr;
337
333
 
338
334
  size = getClientName(client, clientName, sizeof(clientName));
339
- if (req->host != NULL) {
335
+ if (req->host != NULL && req->host->size > 0) {
340
336
  host = psg_lstr_make_contiguous(req->host, req->pool);
341
337
  hostStr = StaticString(host->start->data, host->size);
342
338
  }
@@ -439,22 +435,24 @@ public:
439
435
 
440
436
  if (req->appResponseInitialized) {
441
437
  doc["app_response_http_state"] = resp->getHttpStateString();
442
- doc["app_response_http_major"] = resp->httpMajor;
443
- doc["app_response_http_minor"] = resp->httpMinor;
444
- doc["app_response_want_keep_alive"] = resp->wantKeepAlive;
445
- doc["app_response_body_type"] = resp->getBodyTypeString();
446
- doc["app_response_body_fully_read"] = resp->bodyFullyRead();
447
- doc["app_response_body_already_read"] = byteSizeToJson(
448
- resp->bodyAlreadyRead);
449
- if (resp->httpState != AppResponse::ERROR) {
450
- if (resp->bodyType == AppResponse::RBT_CONTENT_LENGTH) {
451
- doc["app_response_content_length"] = byteSizeToJson(
452
- resp->aux.bodyInfo.contentLength);
453
- } else if (resp->bodyType == AppResponse::RBT_CHUNKED) {
454
- doc["app_response_end_chunk_reached"] = resp->aux.bodyInfo.endChunkReached;
438
+ if (resp->begun()) {
439
+ doc["app_response_http_major"] = resp->httpMajor;
440
+ doc["app_response_http_minor"] = resp->httpMinor;
441
+ doc["app_response_want_keep_alive"] = resp->wantKeepAlive;
442
+ doc["app_response_body_type"] = resp->getBodyTypeString();
443
+ doc["app_response_body_fully_read"] = resp->bodyFullyRead();
444
+ doc["app_response_body_already_read"] = byteSizeToJson(
445
+ resp->bodyAlreadyRead);
446
+ if (resp->httpState != AppResponse::ERROR) {
447
+ if (resp->bodyType == AppResponse::RBT_CONTENT_LENGTH) {
448
+ doc["app_response_content_length"] = byteSizeToJson(
449
+ resp->aux.bodyInfo.contentLength);
450
+ } else if (resp->bodyType == AppResponse::RBT_CHUNKED) {
451
+ doc["app_response_end_chunk_reached"] = resp->aux.bodyInfo.endChunkReached;
452
+ }
453
+ } else {
454
+ doc["app_response_parse_error"] = ServerKit::getErrorDesc(resp->aux.parseError);
455
455
  }
456
- } else {
457
- doc["app_response_parse_error"] = ServerKit::getErrorDesc(resp->aux.parseError);
458
456
  }
459
457
  }
460
458
 
@@ -215,6 +215,10 @@ public:
215
215
  return bodyType == RBT_UPGRADE;
216
216
  }
217
217
 
218
+ bool begun() const {
219
+ return (int) httpState >= COMPLETE;
220
+ }
221
+
218
222
  bool canKeepAlive() const {
219
223
  return wantKeepAlive && bodyFullyRead();
220
224
  }
@@ -335,11 +335,15 @@ onAppResponseBegin(Client *client, Request *req) {
335
335
  req->wantKeepAlive = false;
336
336
  }
337
337
  }
338
- if (resp->headers.lookup(HTTP_X_SENDFILE) != NULL
339
- || resp->headers.lookup(HTTP_X_ACCEL_REDIRECT) != NULL)
338
+ if (resp->headers.lookup(ServerKit::HTTP_X_SENDFILE) != NULL
339
+ || resp->headers.lookup(ServerKit::HTTP_X_ACCEL_REDIRECT) != NULL)
340
340
  {
341
- // https://github.com/phusion/passenger/issues/1498
342
- resp->wantKeepAlive = false;
341
+ // If X-Sendfile or X-Accel-Redirect is set, then HttpHeaderParser
342
+ // treats the app response as having no body, and removes the
343
+ // Content-Length and Transfer-Encoding headers. Because of this,
344
+ // the response that we output also doesn't Content-Length
345
+ // or Transfer-Encoding. So we should disable keep-alive.
346
+ req->wantKeepAlive = false;
343
347
  }
344
348
 
345
349
  prepareAppResponseCaching(client, req);
@@ -553,10 +557,10 @@ constructHeaderBuffersForResponse(Request *req, struct iovec *buffers,
553
557
  }
554
558
 
555
559
  while (*it != NULL) {
556
- dataSize += it->header->key.size + sizeof(": ") - 1;
560
+ dataSize += it->header->origKey.size + sizeof(": ") - 1;
557
561
  dataSize += it->header->val.size + sizeof("\r\n") - 1;
558
562
 
559
- part = it->header->key.start;
563
+ part = it->header->origKey.start;
560
564
  while (part != NULL) {
561
565
  if (buffers != NULL) {
562
566
  buffers[i].iov_base = (void *) part->data;
@@ -173,6 +173,7 @@ void deinitializeAppResponse(Client *client, Request *req) {
173
173
  ServerKit::HeaderTable::Iterator it(resp->headers);
174
174
  while (*it != NULL) {
175
175
  psg_lstr_deinit(&it->header->key);
176
+ psg_lstr_deinit(&it->header->origKey);
176
177
  psg_lstr_deinit(&it->header->val);
177
178
  it.next();
178
179
  }
@@ -180,6 +181,7 @@ void deinitializeAppResponse(Client *client, Request *req) {
180
181
  it = ServerKit::HeaderTable::Iterator(resp->secureHeaders);
181
182
  while (*it != NULL) {
182
183
  psg_lstr_deinit(&it->header->key);
184
+ psg_lstr_deinit(&it->header->origKey);
183
185
  psg_lstr_deinit(&it->header->val);
184
186
  it.next();
185
187
  }
@@ -426,7 +426,7 @@ setStickySessionId(Client *client, Request *req) {
426
426
  // headers, although this is in practice extremely rare.
427
427
  // http://stackoverflow.com/questions/16305814/are-multiple-cookie-headers-allowed-in-an-http-request
428
428
  const LString *cookieHeader = req->headers.lookup(HTTP_COOKIE);
429
- if (cookieHeader != NULL) {
429
+ if (cookieHeader != NULL && cookieHeader->size > 0) {
430
430
  const LString *cookieName = getStickySessionCookieName(req);
431
431
  vector< pair<StaticString, StaticString> > cookies;
432
432
  pair<StaticString, StaticString> cookie;