passenger 3.9.2.beta → 4.0.0.rc4

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 (159) hide show
  1. data/.travis.yml +3 -0
  2. data/NEWS +77 -7
  3. data/README.md +3 -11
  4. data/bin/passenger-install-apache2-module +24 -20
  5. data/bin/passenger-install-nginx-module +25 -23
  6. data/build/agents.rb +11 -0
  7. data/build/apache2.rb +9 -5
  8. data/build/basics.rb +37 -30
  9. data/build/common_library.rb +4 -1
  10. data/build/cplusplus_support.rb +5 -5
  11. data/build/cxx_tests.rb +28 -8
  12. data/build/integration_tests.rb +6 -3
  13. data/build/nginx.rb +3 -3
  14. data/build/packaging.rb +95 -57
  15. data/build/ruby_extension.rb +34 -21
  16. data/build/ruby_tests.rb +4 -2
  17. data/build/test_basics.rb +1 -1
  18. data/dev/run_travis.sh +36 -1
  19. data/doc/Users guide Apache.html +425 -308
  20. data/doc/Users guide Apache.idmap.txt +78 -70
  21. data/doc/Users guide Apache.index.sqlite3 +0 -0
  22. data/doc/Users guide Apache.txt +33 -92
  23. data/doc/Users guide Nginx.html +519 -220
  24. data/doc/Users guide Nginx.idmap.txt +78 -60
  25. data/doc/Users guide Nginx.txt +115 -26
  26. data/doc/Users guide Standalone.html +8 -2
  27. data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +1 -7
  28. data/doc/users_guide_snippets/installation.txt +167 -22
  29. data/doc/users_guide_snippets/rackup_specifications.txt +4 -0
  30. data/doc/users_guide_snippets/since_version.txt +1 -0
  31. data/doc/users_guide_snippets/support_information.txt +3 -7
  32. data/doc/users_guide_snippets/tips.txt +0 -24
  33. data/ext/apache2/Configuration.cpp +11 -33
  34. data/ext/apache2/Configuration.hpp +3 -18
  35. data/ext/apache2/DirectoryMapper.h +20 -70
  36. data/ext/apache2/Hooks.cpp +2 -2
  37. data/ext/common/AgentsStarter.cpp +0 -2
  38. data/ext/common/AgentsStarter.h +0 -1
  39. data/ext/common/AgentsStarter.hpp +1 -3
  40. data/ext/common/ApplicationPool2/AppTypes.cpp +74 -0
  41. data/ext/common/ApplicationPool2/AppTypes.h +202 -0
  42. data/ext/common/ApplicationPool2/Common.h +12 -10
  43. data/ext/common/ApplicationPool2/DirectSpawner.h +256 -0
  44. data/ext/common/ApplicationPool2/DummySpawner.h +90 -0
  45. data/ext/common/ApplicationPool2/Group.h +311 -94
  46. data/ext/common/ApplicationPool2/Implementation.cpp +405 -145
  47. data/ext/common/ApplicationPool2/Options.h +24 -26
  48. data/ext/common/ApplicationPool2/PipeWatcher.h +20 -13
  49. data/ext/common/ApplicationPool2/Pool.h +326 -183
  50. data/ext/common/ApplicationPool2/Process.h +205 -55
  51. data/ext/common/ApplicationPool2/README.md +1 -1
  52. data/ext/common/ApplicationPool2/Session.h +21 -10
  53. data/ext/common/ApplicationPool2/SmartSpawner.h +801 -0
  54. data/ext/common/ApplicationPool2/Spawner.h +141 -1149
  55. data/ext/common/ApplicationPool2/SpawnerFactory.h +132 -0
  56. data/ext/common/ApplicationPool2/SuperGroup.h +146 -223
  57. data/ext/common/Constants.h +4 -2
  58. data/ext/common/Exceptions.h +23 -1
  59. data/ext/common/Logging.cpp +17 -6
  60. data/ext/common/Logging.h +37 -7
  61. data/ext/common/ResourceLocator.h +1 -1
  62. data/ext/common/Utils.cpp +49 -1
  63. data/ext/common/Utils.h +13 -4
  64. data/ext/common/{AnsiColorConstants.h → Utils/AnsiColorConstants.h} +0 -0
  65. data/ext/common/{BCrypt.cpp → Utils/BCrypt.cpp} +0 -0
  66. data/ext/common/{BCrypt.h → Utils/BCrypt.h} +0 -0
  67. data/ext/common/{Blowfish.c → Utils/Blowfish.c} +0 -0
  68. data/ext/common/{Blowfish.h → Utils/Blowfish.h} +0 -0
  69. data/ext/common/Utils/CachedFileStat.hpp +27 -25
  70. data/ext/common/Utils/Curl.h +184 -0
  71. data/ext/common/{HttpConstants.h → Utils/HttpConstants.h} +3 -0
  72. data/ext/common/Utils/IOUtils.cpp +6 -2
  73. data/ext/common/{IniFile.h → Utils/IniFile.h} +0 -0
  74. data/ext/common/Utils/LargeFiles.cpp +30 -0
  75. data/ext/common/Utils/LargeFiles.h +40 -0
  76. data/ext/common/Utils/StrIntUtils.cpp +72 -8
  77. data/ext/common/Utils/StrIntUtils.h +24 -2
  78. data/ext/common/Utils/StringMap.h +12 -2
  79. data/ext/common/Utils/VariantMap.h +51 -2
  80. data/ext/common/Utils/jsoncpp.cpp +1 -1
  81. data/ext/common/agents/Base.cpp +147 -11
  82. data/ext/common/agents/HelperAgent/AgentOptions.h +14 -6
  83. data/ext/common/agents/HelperAgent/Main.cpp +79 -19
  84. data/ext/common/agents/HelperAgent/RequestHandler.h +36 -16
  85. data/ext/common/agents/LoggingAgent/LoggingServer.h +3 -5
  86. data/ext/common/agents/LoggingAgent/Main.cpp +2 -4
  87. data/ext/common/agents/LoggingAgent/RemoteSender.h +18 -24
  88. data/ext/common/agents/SpawnPreparer.cpp +7 -0
  89. data/ext/common/agents/Watchdog/Main.cpp +96 -38
  90. data/ext/nginx/Configuration.c +26 -22
  91. data/ext/nginx/Configuration.h +4 -2
  92. data/ext/nginx/ContentHandler.c +23 -52
  93. data/ext/nginx/ContentHandler.h +5 -11
  94. data/ext/nginx/config +10 -3
  95. data/ext/nginx/ngx_http_passenger_module.c +21 -6
  96. data/ext/nginx/ngx_http_passenger_module.h +4 -1
  97. data/ext/oxt/dynamic_thread_group.hpp +9 -1
  98. data/ext/oxt/system_calls.cpp +2 -2
  99. data/ext/ruby/extconf.rb +2 -1
  100. data/helper-scripts/backtrace-sanitizer.rb +2 -0
  101. data/helper-scripts/wsgi-loader.py +54 -21
  102. data/lib/phusion_passenger.rb +5 -3
  103. data/lib/phusion_passenger/abstract_installer.rb +18 -41
  104. data/lib/phusion_passenger/admin_tools/memory_stats.rb +2 -2
  105. data/lib/phusion_passenger/admin_tools/server_instance.rb +2 -2
  106. data/lib/phusion_passenger/common_library.rb +23 -3
  107. data/lib/phusion_passenger/debug_logging.rb +10 -3
  108. data/lib/phusion_passenger/packaging.rb +1 -0
  109. data/lib/phusion_passenger/platform_info.rb +113 -115
  110. data/lib/phusion_passenger/platform_info/compiler.rb +224 -134
  111. data/lib/phusion_passenger/platform_info/cxx_portability.rb +143 -0
  112. data/lib/phusion_passenger/platform_info/depcheck.rb +371 -0
  113. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +124 -0
  114. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +97 -0
  115. data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +39 -0
  116. data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +118 -0
  117. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +137 -0
  118. data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +15 -0
  119. data/lib/phusion_passenger/platform_info/operating_system.rb +6 -5
  120. data/lib/phusion_passenger/platform_info/ruby.rb +45 -34
  121. data/lib/phusion_passenger/request_handler.rb +35 -22
  122. data/lib/phusion_passenger/request_handler/thread_handler.rb +5 -6
  123. data/lib/phusion_passenger/ruby_core_enhancements.rb +7 -1
  124. data/lib/phusion_passenger/standalone/runtime_installer.rb +43 -34
  125. data/lib/phusion_passenger/utils/robust_interruption.rb +34 -18
  126. data/passenger.gemspec +25 -0
  127. data/resources/templates/standalone/config.erb +3 -1
  128. data/test/config.json.travis +2 -2
  129. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +37 -5
  130. data/test/cxx/ApplicationPool2/PoolTest.cpp +143 -50
  131. data/test/cxx/ApplicationPool2/ProcessTest.cpp +8 -0
  132. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +28 -17
  133. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +31 -26
  134. data/test/cxx/RequestHandlerTest.cpp +17 -1
  135. data/test/cxx/UtilsTest.cpp +84 -10
  136. data/test/integration_tests/apache2_tests.rb +49 -163
  137. data/test/integration_tests/hello_world_wsgi_spec.rb +2 -2
  138. data/test/integration_tests/mycook_spec.rb +1 -1
  139. data/test/integration_tests/nginx_tests.rb +37 -19
  140. data/test/ruby/request_handler_spec.rb +1 -0
  141. data/test/ruby/spec_helper.rb +52 -1
  142. data/test/stub/nginx/nginx.conf.erb +2 -0
  143. data/test/stub/rack/start.rb +5 -0
  144. data/test/stub/rails3.0/Gemfile.lock +30 -30
  145. data/test/stub/rails3.1/Gemfile +1 -1
  146. data/test/stub/rails3.1/Gemfile.lock +3 -3
  147. data/test/stub/rails3.2/Gemfile +1 -1
  148. data/test/stub/rails3.2/Gemfile.lock +4 -4
  149. data/test/stub/rails_apps/2.3/mycook/app/controllers/welcome_controller.rb +1 -1
  150. data/test/stub/rails_apps/2.3/mycook/app/helpers/recipes_helper.rb +2 -0
  151. data/test/stub/rails_apps/2.3/mycook/app/helpers/test_helper.rb +2 -0
  152. data/test/stub/rails_apps/2.3/mycook/app/helpers/uploads_helper.rb +2 -0
  153. data/test/stub/rails_apps/2.3/mycook/app/helpers/welcome_helper.rb +2 -0
  154. data/test/support/nginx_controller.rb +2 -1
  155. metadata +160 -156
  156. data/build/gempackagetask.rb +0 -99
  157. data/build/packagetask.rb +0 -186
  158. data/ext/common/StringListCreator.h +0 -83
  159. data/lib/phusion_passenger/dependencies.rb +0 -657
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Copyright (C) Igor Sysoev
3
3
  * Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
4
- * Copyright (C) 2010, 2011, 2012 Phusion
4
+ * Copyright (C) 2010-2013 Phusion
5
5
  *
6
6
  * Redistribution and use in source and binary forms, with or without
7
7
  * modification, are permitted provided that the following conditions
@@ -86,34 +86,6 @@ file_exists(const u_char *filename, unsigned int throttle_rate) {
86
86
  return get_file_type(filename, throttle_rate) == FT_FILE;
87
87
  }
88
88
 
89
- static passenger_app_type_t
90
- detect_application_type(const ngx_str_t *public_dir) {
91
- u_char filename[NGX_MAX_PATH];
92
-
93
- ngx_memzero(filename, sizeof(filename));
94
- ngx_snprintf(filename, sizeof(filename), "%s/%s",
95
- public_dir->data, "../config.ru");
96
- if (file_exists(filename, 1)) {
97
- return AP_RACK;
98
- }
99
-
100
- ngx_memzero(filename, sizeof(filename));
101
- ngx_snprintf(filename, sizeof(filename), "%s/%s",
102
- public_dir->data, "../config/environment.rb");
103
- if (file_exists(filename, 1)) {
104
- return AP_CLASSIC_RAILS;
105
- }
106
-
107
- ngx_memzero(filename, sizeof(filename));
108
- ngx_snprintf(filename, sizeof(filename), "%s/%s",
109
- public_dir->data, "../passenger_wsgi.py");
110
- if (file_exists(filename, 1)) {
111
- return AP_WSGI;
112
- }
113
-
114
- return AP_NONE;
115
- }
116
-
117
89
  /**
118
90
  * Maps the URI for the given request to a page cache file, if possible.
119
91
  *
@@ -197,11 +169,11 @@ find_base_uri(ngx_http_request_t *r, const passenger_loc_conf_t *loc,
197
169
  return 0;
198
170
  } else {
199
171
  base_uris = (ngx_str_t *) loc->base_uris->elts;
172
+ uri = &r->uri;
200
173
  for (i = 0; i < loc->base_uris->nelts; i++) {
201
174
  base_uri = &base_uris[i];
202
- uri = &r->uri;
203
175
 
204
- if (uri->len == 1 && uri->data[0] == '/') {
176
+ if (base_uri->len == 1 && base_uri->data[0] == '/') {
205
177
  /* Ignore 'passenger_base_uri /' options. Users usually
206
178
  * specify this out of ignorance.
207
179
  */
@@ -213,7 +185,7 @@ find_base_uri(ngx_http_request_t *r, const passenger_loc_conf_t *loc,
213
185
  || ( uri->len > base_uri->len
214
186
  && ngx_strncmp(uri->data, base_uri->data, base_uri->len) == 0
215
187
  && uri->data[base_uri->len] == (u_char) '/' )) {
216
- *found_base_uri = base_uris[i];
188
+ *found_base_uri = *base_uri;
217
189
  return 1;
218
190
  }
219
191
  }
@@ -373,24 +345,8 @@ create_request(ngx_http_request_t *r)
373
345
  return NGX_HTTP_INTERNAL_SERVER_ERROR;
374
346
  }
375
347
 
376
- switch (context->app_type) {
377
- case AP_CLASSIC_RAILS:
378
- app_type_string = (const u_char *) "classic-rails";
379
- app_type_string_len = sizeof("classic-rails");
380
- break;
381
- case AP_RACK:
382
- app_type_string = (const u_char *) "rack";
383
- app_type_string_len = sizeof("rack");
384
- break;
385
- case AP_WSGI:
386
- app_type_string = (const u_char *) "wsgi";
387
- app_type_string_len = sizeof("wsgi");
388
- break;
389
- default:
390
- app_type_string = (const u_char *) "rack";
391
- app_type_string_len = sizeof("rack");
392
- break;
393
- }
348
+ app_type_string = (const u_char *) passenger_get_app_type_name(context->app_type);
349
+ app_type_string_len = strlen((const char *) app_type_string) + 1; /* include null terminator */
394
350
 
395
351
 
396
352
  /*
@@ -472,10 +428,12 @@ create_request(ngx_http_request_t *r)
472
428
  ANALYZE_BOOLEAN_CONFIG_LENGTH("PASSENGER_SHOW_VERSION_IN_HEADER",
473
429
  slcf, show_version_in_header);
474
430
  ANALYZE_STR_CONFIG_LENGTH("PASSENGER_RUBY", slcf, ruby);
431
+ ANALYZE_STR_CONFIG_LENGTH("PASSENGER_PYTHON", slcf, python);
475
432
  len += sizeof("PASSENGER_ENV") + slcf->environment.len + 1;
476
433
  len += sizeof("PASSENGER_SPAWN_METHOD") + slcf->spawn_method.len + 1;
477
434
  len += sizeof("PASSENGER_APP_TYPE") + app_type_string_len;
478
435
  ANALYZE_STR_CONFIG_LENGTH("PASSENGER_APP_GROUP_NAME", slcf, app_group_name);
436
+ ANALYZE_STR_CONFIG_LENGTH("PASSENGER_APP_ROOT", slcf, app_root);
479
437
  ANALYZE_STR_CONFIG_LENGTH("PASSENGER_APP_RIGHTS", slcf, app_rights);
480
438
  ANALYZE_STR_CONFIG_LENGTH("PASSENGER_USER", slcf, user);
481
439
  ANALYZE_STR_CONFIG_LENGTH("PASSENGER_GROUP", slcf, group);
@@ -686,6 +644,8 @@ create_request(ngx_http_request_t *r)
686
644
 
687
645
  SERIALIZE_STR_CONFIG_DATA("PASSENGER_RUBY",
688
646
  slcf, ruby);
647
+ SERIALIZE_STR_CONFIG_DATA("PASSENGER_PYTHON",
648
+ slcf, python);
689
649
 
690
650
  b->last = ngx_copy(b->last, "PASSENGER_ENV",
691
651
  sizeof("PASSENGER_ENV"));
@@ -699,6 +659,8 @@ create_request(ngx_http_request_t *r)
699
659
 
700
660
  SERIALIZE_STR_CONFIG_DATA("PASSENGER_APP_GROUP_NAME",
701
661
  slcf, app_group_name);
662
+ SERIALIZE_STR_CONFIG_DATA("PASSENGER_APP_ROOT",
663
+ slcf, app_root);
702
664
  SERIALIZE_STR_CONFIG_DATA("PASSENGER_APP_RIGHTS",
703
665
  slcf, app_rights);
704
666
  SERIALIZE_STR_CONFIG_DATA("PASSENGER_USER",
@@ -1393,8 +1355,17 @@ passenger_content_handler(ngx_http_request_t *r)
1393
1355
  return passenger_static_content_handler(r, &page_cache_file);
1394
1356
  }
1395
1357
 
1396
- context->app_type = detect_application_type(&context->public_dir);
1397
- if (context->app_type == AP_NONE) {
1358
+ if (slcf->app_root.data == NULL) {
1359
+ context->app_type = passenger_app_type_detector_check_document_root(
1360
+ passenger_app_type_detector,
1361
+ (const char *) context->public_dir.data, context->public_dir.len,
1362
+ context->base_uri.len != 0);
1363
+ } else {
1364
+ context->app_type = passenger_app_type_detector_check_app_root(
1365
+ passenger_app_type_detector,
1366
+ (const char *) slcf->app_root.data, slcf->app_root.len);
1367
+ }
1368
+ if (context->app_type == PAT_NONE) {
1398
1369
  return NGX_DECLINED;
1399
1370
  }
1400
1371
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Copyright (C) Igor Sysoev
3
3
  * Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
4
- * Copyright (C) 2010 Phusion
4
+ * Copyright (C) 2010-2013 Phusion
5
5
  *
6
6
  * Redistribution and use in source and binary forms, with or without
7
7
  * modification, are permitted provided that the following conditions
@@ -30,15 +30,9 @@
30
30
 
31
31
  #include <ngx_core.h>
32
32
  #include <ngx_http.h>
33
+ #include "../common/ApplicationPool2/AppTypes.h"
33
34
 
34
35
 
35
- typedef enum {
36
- AP_CLASSIC_RAILS,
37
- AP_RACK,
38
- AP_WSGI,
39
- AP_NONE
40
- } passenger_app_type_t;
41
-
42
36
  typedef struct {
43
37
  /** Proxy state. */
44
38
  ngx_uint_t status;
@@ -46,14 +40,14 @@ typedef struct {
46
40
  u_char *status_start;
47
41
  u_char *status_end;
48
42
 
49
- /** The backend application's 'public' directory. */
43
+ /** The application's 'public' directory. */
50
44
  ngx_str_t public_dir;
51
45
 
52
46
  /** The application's base URI. Points to an empty string if none. */
53
47
  ngx_str_t base_uri;
54
48
 
55
- /** The backend application's type. */
56
- passenger_app_type_t app_type;
49
+ /** The application's type. */
50
+ PassengerAppType app_type;
57
51
  } passenger_context_t;
58
52
 
59
53
 
@@ -8,8 +8,14 @@ if test "x$PASSENGER_LIBS" = "x" && ! passenger-config --compiled; then
8
8
  if ! cd $ngx_addon_dir; then
9
9
  exit 1
10
10
  fi
11
- if ! rake nginx CACHING=false; then
12
- exit 1
11
+ if test "x$TRACE" = 1; then
12
+ if ! rake --trace nginx CACHING=false; then
13
+ exit 1
14
+ fi
15
+ else
16
+ if ! rake nginx CACHING=false; then
17
+ exit 1
18
+ fi
13
19
  fi
14
20
  cd "$old_dir"
15
21
  echo "*** Phusion Passenger support files have been successfully compiled. ***"
@@ -27,7 +33,8 @@ NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
27
33
  ${ngx_addon_dir}/ContentHandler.h \
28
34
  ${ngx_addon_dir}/StaticContentHandler.h \
29
35
  ${ngx_addon_dir}/ngx_http_passenger_module.h \
30
- `passenger-config --root`/ext/common/Constants.h"
36
+ `passenger-config --root`/ext/common/Constants.h \
37
+ `passenger-config --root`/ext/common/ApplicationPool2/AppTypes.h"
31
38
  if test "x$PASSENGER_LIBS" = "x"; then
32
39
  CORE_LIBS="$CORE_LIBS `passenger-config --nginx-libs`"
33
40
  else
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Copyright (C) Igor Sysoev
3
3
  * Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
4
- * Copyright (C) 2010-2012 Phusion
4
+ * Copyright (C) 2010-2013 Phusion
5
5
  *
6
6
  * Redistribution and use in source and binary forms, with or without
7
7
  * modification, are permitted provided that the following conditions
@@ -53,6 +53,7 @@ static int first_start = 1;
53
53
  ngx_str_t passenger_schema_string;
54
54
  ngx_str_t passenger_placeholder_upstream_address;
55
55
  PassengerCachedFileStat *passenger_stat_cache;
56
+ PassengerAppTypeDetector *passenger_app_type_detector;
56
57
  AgentsStarter *passenger_agents_starter = NULL;
57
58
  ngx_cycle_t *passenger_current_cycle;
58
59
 
@@ -143,6 +144,10 @@ starting_helper_server_after_fork(void *arg) {
143
144
  ngx_cycle_t *cycle = (void *) arg;
144
145
  char *log_filename;
145
146
  FILE *log_file;
147
+ ngx_core_conf_t *ccf;
148
+ ngx_uint_t i;
149
+ ngx_str_t *envs;
150
+ const char *env;
146
151
 
147
152
  /* At this point, stdout and stderr may still point to the console.
148
153
  * Make sure that they're both redirected to the log file.
@@ -178,6 +183,16 @@ starting_helper_server_after_fork(void *arg) {
178
183
  dup2(fileno(log_file), 2);
179
184
  fclose(log_file);
180
185
  }
186
+
187
+ /* Set environment variables in Nginx config file. */
188
+ ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
189
+ envs = ccf->env.elts;
190
+ for (i = 0; i < ccf->env.nelts; i++) {
191
+ env = (const char *) envs[i].data;
192
+ if (strchr(env, '=') != NULL) {
193
+ putenv(strdup(env));
194
+ }
195
+ }
181
196
 
182
197
  /* Set SERVER_SOFTWARE so that application processes know what web
183
198
  * server they're running on during startup. */
@@ -231,12 +246,12 @@ start_helper_server(ngx_cycle_t *cycle) {
231
246
  char *default_user = NULL;
232
247
  char *default_group = NULL;
233
248
  char *passenger_root = NULL;
249
+ char *temp_dir = NULL;
234
250
  char *analytics_log_user;
235
251
  char *analytics_log_group;
236
252
  char *union_station_gateway_address;
237
253
  char *union_station_gateway_cert;
238
254
  char *union_station_proxy_address;
239
- char *union_station_proxy_type;
240
255
  char *error_message = NULL;
241
256
 
242
257
  core_conf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
@@ -247,12 +262,12 @@ start_helper_server(ngx_cycle_t *cycle) {
247
262
  default_user = ngx_str_null_terminate(&passenger_main_conf.default_user);
248
263
  default_group = ngx_str_null_terminate(&passenger_main_conf.default_group);
249
264
  passenger_root = ngx_str_null_terminate(&passenger_main_conf.root_dir);
265
+ temp_dir = ngx_str_null_terminate(&passenger_main_conf.temp_dir);
250
266
  analytics_log_user = ngx_str_null_terminate(&passenger_main_conf.analytics_log_user);
251
267
  analytics_log_group = ngx_str_null_terminate(&passenger_main_conf.analytics_log_group);
252
268
  union_station_gateway_address = ngx_str_null_terminate(&passenger_main_conf.union_station_gateway_address);
253
269
  union_station_gateway_cert = ngx_str_null_terminate(&passenger_main_conf.union_station_gateway_cert);
254
270
  union_station_proxy_address = ngx_str_null_terminate(&passenger_main_conf.union_station_proxy_address);
255
- union_station_proxy_type = ngx_str_null_terminate(&passenger_main_conf.union_station_proxy_type);
256
271
 
257
272
  prestart_uris = (ngx_str_t *) passenger_main_conf.prestart_uris->elts;
258
273
  prestart_uris_ary = calloc(sizeof(char *), passenger_main_conf.prestart_uris->nelts);
@@ -269,7 +284,7 @@ start_helper_server(ngx_cycle_t *cycle) {
269
284
 
270
285
  ret = agents_starter_start(passenger_agents_starter,
271
286
  passenger_main_conf.log_level, debug_log_file, getpid(),
272
- "", passenger_main_conf.user_switching,
287
+ temp_dir, passenger_main_conf.user_switching,
273
288
  default_user, default_group,
274
289
  core_conf->user, core_conf->group,
275
290
  passenger_root, "ruby", passenger_main_conf.max_pool_size,
@@ -281,7 +296,6 @@ start_helper_server(ngx_cycle_t *cycle) {
281
296
  passenger_main_conf.union_station_gateway_port,
282
297
  union_station_gateway_cert,
283
298
  union_station_proxy_address,
284
- union_station_proxy_type,
285
299
  (const char **) prestart_uris_ary, passenger_main_conf.prestart_uris->nelts,
286
300
  starting_helper_server_after_fork,
287
301
  cycle,
@@ -336,12 +350,12 @@ cleanup:
336
350
  free(default_user);
337
351
  free(default_group);
338
352
  free(passenger_root);
353
+ free(temp_dir);
339
354
  free(analytics_log_user);
340
355
  free(analytics_log_group);
341
356
  free(union_station_gateway_address);
342
357
  free(union_station_gateway_cert);
343
358
  free(union_station_proxy_address);
344
- free(union_station_proxy_type);
345
359
  free(error_message);
346
360
  if (prestart_uris_ary != NULL) {
347
361
  for (i = 0; i < passenger_main_conf.prestart_uris->nelts; i++) {
@@ -387,6 +401,7 @@ pre_config_init(ngx_conf_t *cf)
387
401
  passenger_placeholder_upstream_address.data = (u_char *) "unix:/passenger_helper_server";
388
402
  passenger_placeholder_upstream_address.len = sizeof("unix:/passenger_helper_server") - 1;
389
403
  passenger_stat_cache = cached_file_stat_new(1024);
404
+ passenger_app_type_detector = passenger_app_type_detector_new();
390
405
  passenger_agents_starter = agents_starter_new(AS_NGINX, &error_message);
391
406
 
392
407
  if (passenger_agents_starter == NULL) {
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Copyright (C) Igor Sysoev
3
3
  * Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
4
- * Copyright (C) 2010 Phusion
4
+ * Copyright (C) 2010-2013 Phusion
5
5
  *
6
6
  * Redistribution and use in source and binary forms, with or without
7
7
  * modification, are permitted provided that the following conditions
@@ -31,6 +31,7 @@
31
31
  #include <ngx_config.h>
32
32
  #include <ngx_core.h>
33
33
  #include "../common/AgentsStarter.h"
34
+ #include "../common/ApplicationPool2/AppTypes.h"
34
35
  #include "../common/Utils/CachedFileStat.h"
35
36
 
36
37
  /**
@@ -56,6 +57,8 @@ extern ngx_str_t passenger_placeholder_upstream_address;
56
57
  */
57
58
  extern PassengerCachedFileStat *passenger_stat_cache;
58
59
 
60
+ extern PassengerAppTypeDetector *passenger_app_type_detector;
61
+
59
62
  extern AgentsStarter *passenger_agents_starter;
60
63
 
61
64
  extern ngx_cycle_t *passenger_current_cycle;
@@ -2,7 +2,7 @@
2
2
  * OXT - OS eXtensions for boosT
3
3
  * Provides important functionality necessary for writing robust server software.
4
4
  *
5
- * Copyright (c) 2010 Phusion
5
+ * Copyright (c) 2010-2013 Phusion
6
6
  *
7
7
  * Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  * of this software and associated documentation files (the "Software"), to deal
@@ -146,6 +146,14 @@ public:
146
146
  throw;
147
147
  }
148
148
  }
149
+
150
+ void interrupt_all() {
151
+ boost::unique_lock<boost::mutex> l(lock);
152
+ list<thread_handle_ptr>::iterator it;
153
+ for (it = thread_handles.begin(); it != thread_handles.end(); it++) {
154
+ (*it)->thr->interrupt();
155
+ }
156
+ }
149
157
 
150
158
  /**
151
159
  * Interrupt and join all threads in this group.
@@ -2,7 +2,7 @@
2
2
  * OXT - OS eXtensions for boosT
3
3
  * Provides important functionality necessary for writing robust server software.
4
4
  *
5
- * Copyright (c) 2010 Phusion
5
+ * Copyright (c) 2010-2013 Phusion
6
6
  *
7
7
  * Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  * of this software and associated documentation files (the "Software"), to deal
@@ -122,7 +122,7 @@ shouldSimulateFailure() {
122
122
  ctx->syscall_interruption_lock.unlock(); \
123
123
  } \
124
124
  int _my_errno; \
125
- bool _intr_requested; \
125
+ bool _intr_requested = false; \
126
126
  do { \
127
127
  code; \
128
128
  _my_errno = errno; \
@@ -1,5 +1,5 @@
1
1
  # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2010 Phusion
2
+ # Copyright (c) 2010-2013 Phusion
3
3
  #
4
4
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
5
5
  #
@@ -23,6 +23,7 @@
23
23
  require 'mkmf'
24
24
  $LIBS = ""
25
25
  $CFLAGS << " -g"
26
+ $LIBS << " -lpthread"
26
27
 
27
28
  if RUBY_PLATFORM =~ /solaris/
28
29
  have_library('xnet')
@@ -50,6 +50,8 @@ end
50
50
 
51
51
  input = STDIN
52
52
  output = STDERR
53
+ output.sync = true
54
+ output.puts "Using backtrace sanitizer."
53
55
  argv0, pid_or_filename = ARGV
54
56
  if pid_or_filename =~ /\A\d+\Z/
55
57
  begin
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
2
  # Phusion Passenger - https://www.phusionpassenger.com/
3
- # Copyright (c) 2010, 2011, 2012 Phusion
3
+ # Copyright (c) 2010-2013 Phusion
4
4
  #
5
5
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  #
@@ -23,7 +23,6 @@
23
23
  # THE SOFTWARE.
24
24
 
25
25
  import sys, os, re, imp, traceback, socket, select, struct, logging, errno
26
- from socket import _fileobject
27
26
 
28
27
  options = {}
29
28
 
@@ -73,6 +72,25 @@ def advertise_sockets(socket_filename):
73
72
  print("!> socket: main;unix:%s;session;1" % socket_filename)
74
73
  print("!> ")
75
74
 
75
+ if sys.version_info[0] >= 3:
76
+ def reraise_exception(exc_info):
77
+ raise exc_info[0].with_traceback(exc_info[1], exc_info[2])
78
+
79
+ def bytes_to_str(b):
80
+ return b.decode()
81
+
82
+ def str_to_bytes(s):
83
+ return s.encode('latin-1')
84
+ else:
85
+ def reraise_exception(exc_info):
86
+ exec("raise exc_info[0], exc_info[1], exc_info[2]")
87
+
88
+ def bytes_to_str(b):
89
+ return b
90
+
91
+ def str_to_bytes(s):
92
+ return s
93
+
76
94
 
77
95
  class RequestHandler:
78
96
  def __init__(self, server_socket, owner_pipe, app):
@@ -98,12 +116,19 @@ class RequestHandler:
98
116
  self.process_request(env, input_stream, client)
99
117
  except KeyboardInterrupt:
100
118
  done = True
101
- except IOError, e:
119
+ except IOError:
120
+ e = sys.exc_info()[1]
102
121
  if not getattr(e, 'passenger', False) or e.errno != errno.EPIPE:
103
122
  logging.exception("WSGI application raised an I/O exception!")
104
- except Exception, e:
123
+ except Exception:
105
124
  logging.exception("WSGI application raised an exception!")
106
125
  finally:
126
+ try:
127
+ # Shutdown the socket like this just in case the app
128
+ # spawned a child process that keeps it open.
129
+ client.shutdown(socket.SHUT_WR)
130
+ except:
131
+ pass
107
132
  try:
108
133
  client.close()
109
134
  except:
@@ -119,7 +144,7 @@ class RequestHandler:
119
144
  return (None, None)
120
145
 
121
146
  def parse_request(self, client):
122
- buf = ''
147
+ buf = b''
123
148
  while len(buf) < 4:
124
149
  tmp = client.recv(4 - len(buf))
125
150
  if len(tmp) == 0:
@@ -127,35 +152,42 @@ class RequestHandler:
127
152
  buf += tmp
128
153
  header_size = struct.unpack('>I', buf)[0]
129
154
 
130
- buf = ''
155
+ buf = b''
131
156
  while len(buf) < header_size:
132
157
  tmp = client.recv(header_size - len(buf))
133
158
  if len(tmp) == 0:
134
159
  return (None, None)
135
160
  buf += tmp
136
161
 
137
- headers = buf.split("\0")
162
+ headers = buf.split(b"\0")
138
163
  headers.pop() # Remove trailing "\0"
139
164
  env = {}
140
165
  i = 0
141
166
  while i < len(headers):
142
- env[headers[i]] = headers[i + 1]
167
+ env[bytes_to_str(headers[i])] = bytes_to_str(headers[i + 1])
143
168
  i += 2
144
-
169
+
145
170
  return (env, client)
146
171
 
172
+ if hasattr(socket, '_fileobject'):
173
+ def wrap_input_socket(self, sock):
174
+ return socket._fileobject(sock, 'r', 512)
175
+ else:
176
+ def wrap_input_socket(self, sock):
177
+ return socket.socket.makefile(sock, 'r', 512)
178
+
147
179
  def process_request(self, env, input_stream, output_stream):
148
- # The WSGI speculation says that the input paramter object passed needs to
180
+ # The WSGI speculation says that the input parameter object passed needs to
149
181
  # implement a few file-like methods. This is the reason why we "wrap" the socket._socket
150
182
  # into the _fileobject to solve this.
151
183
  #
152
184
  # Otherwise, the POST data won't be correctly retrieved by Django.
153
185
  #
154
186
  # See: http://www.python.org/dev/peps/pep-0333/#input-and-error-streams
155
- env['wsgi.input'] = _fileobject(input_stream, 'r', 512)
156
- env['wsgi.errors'] = sys.stderr
157
- env['wsgi.version'] = (1, 0)
158
- env['wsgi.multithread'] = False
187
+ env['wsgi.input'] = self.wrap_input_socket(input_stream)
188
+ env['wsgi.errors'] = sys.stderr
189
+ env['wsgi.version'] = (1, 0)
190
+ env['wsgi.multithread'] = False
159
191
  env['wsgi.multiprocess'] = True
160
192
  env['wsgi.run_once'] = True
161
193
  if env.get('HTTPS','off') in ('on', '1', 'true', 'yes'):
@@ -173,14 +205,15 @@ class RequestHandler:
173
205
  elif not headers_sent:
174
206
  # Before the first output, send the stored headers.
175
207
  status, response_headers = headers_sent[:] = headers_set
176
- output_stream.sendall('Status: %s\r\n' % status)
208
+ output_stream.sendall(str_to_bytes('Status: %s\r\n' % status))
177
209
  for header in response_headers:
178
- output_stream.sendall('%s: %s\r\n' % header)
179
- output_stream.sendall('\r\n')
210
+ output_stream.sendall(str_to_bytes('%s: %s\r\n' % header))
211
+ output_stream.sendall(b'\r\n')
180
212
  output_stream.sendall(data)
181
- except IOError, e:
213
+ except IOError:
182
214
  # Mark this exception as coming from the Phusion Passenger
183
215
  # socket and not some other socket.
216
+ e = sys.exc_info()[1]
184
217
  setattr(e, 'passenger', True)
185
218
  raise e
186
219
 
@@ -189,7 +222,7 @@ class RequestHandler:
189
222
  try:
190
223
  if headers_sent:
191
224
  # Re-raise original exception if headers sent.
192
- raise exc_info[0], exc_info[1], exc_info[2]
225
+ reraise_exception(exc_info)
193
226
  finally:
194
227
  # Avoid dangling circular ref.
195
228
  exc_info = None
@@ -207,13 +240,13 @@ class RequestHandler:
207
240
  write(data)
208
241
  if not headers_sent:
209
242
  # Send headers now if body was empty.
210
- write('')
243
+ write(b'')
211
244
  finally:
212
245
  if hasattr(result, 'close'):
213
246
  result.close()
214
247
 
215
248
  def process_ping(self, env, input_stream, output_stream):
216
- output_stream.sendall("pong")
249
+ output_stream.sendall(b"pong")
217
250
 
218
251
 
219
252
  if __name__ == "__main__":