passenger 4.0.14 → 4.0.16

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 (121) hide show
  1. data.tar.gz.asc +7 -7
  2. data/NEWS +69 -0
  3. data/bin/passenger-install-apache2-module +7 -1
  4. data/bin/passenger-install-nginx-module +18 -1
  5. data/build/apache2.rb +25 -1
  6. data/build/basics.rb +7 -4
  7. data/build/debian.rb +72 -25
  8. data/build/nginx.rb +24 -0
  9. data/build/packaging.rb +45 -3
  10. data/debian.template/{control → control.template} +17 -8
  11. data/debian.template/ruby-passenger.install.template +1 -0
  12. data/debian.template/rules.template +9 -3
  13. data/dev/run_travis.sh +14 -0
  14. data/doc/Users guide Apache.idmap.txt +64 -48
  15. data/doc/Users guide Apache.txt +127 -93
  16. data/doc/Users guide Nginx.idmap.txt +46 -28
  17. data/doc/Users guide Nginx.txt +100 -12
  18. data/doc/images/{conservative_spawning.png → direct_spawning.png} +0 -0
  19. data/doc/images/{conservative_spawning.svg → direct_spawning.svg} +0 -0
  20. data/doc/users_guide_snippets/installation.txt +107 -66
  21. data/doc/users_guide_snippets/passenger_spawn_method.txt +1 -1
  22. data/doc/users_guide_snippets/rvm_helper_tool.txt +0 -12
  23. data/doc/users_guide_snippets/tips.txt +70 -3
  24. data/doc/users_guide_snippets/under_the_hood/page_caching_support.txt +2 -0
  25. data/doc/users_guide_snippets/under_the_hood/relationship_with_ruby.txt +114 -0
  26. data/ext/apache2/Configuration.cpp +53 -101
  27. data/ext/apache2/Configuration.hpp +19 -41
  28. data/ext/apache2/ConfigurationCommands.cpp +95 -0
  29. data/ext/apache2/ConfigurationCommands.cpp.erb +91 -0
  30. data/ext/apache2/ConfigurationFields.hpp +59 -0
  31. data/ext/apache2/ConfigurationFields.hpp.erb +89 -0
  32. data/ext/apache2/ConfigurationSetters.cpp +223 -0
  33. data/ext/apache2/ConfigurationSetters.cpp.erb +126 -0
  34. data/ext/apache2/CreateDirConfig.cpp +50 -0
  35. data/ext/apache2/CreateDirConfig.cpp.erb +71 -0
  36. data/ext/apache2/Hooks.cpp +6 -0
  37. data/ext/apache2/MergeDirConfig.cpp +103 -0
  38. data/ext/apache2/MergeDirConfig.cpp.erb +81 -0
  39. data/ext/common/ApplicationPool2/AppTypes.cpp +2 -0
  40. data/ext/common/ApplicationPool2/AppTypes.h +2 -0
  41. data/ext/common/ApplicationPool2/Common.h +1 -1
  42. data/ext/common/ApplicationPool2/Group.h +56 -7
  43. data/ext/common/ApplicationPool2/Implementation.cpp +133 -31
  44. data/ext/common/ApplicationPool2/Options.h +23 -2
  45. data/ext/common/ApplicationPool2/Pool.h +8 -1
  46. data/ext/common/ApplicationPool2/Process.h +9 -0
  47. data/ext/common/ApplicationPool2/Session.h +1 -0
  48. data/ext/common/ApplicationPool2/Spawner.h +21 -19
  49. data/ext/common/ApplicationPool2/SuperGroup.h +1 -1
  50. data/ext/common/Constants.h +21 -17
  51. data/ext/common/Constants.h.erb +1 -1
  52. data/ext/common/Exceptions.h +19 -0
  53. data/ext/common/ServerInstanceDir.h +8 -4
  54. data/ext/common/Utils.cpp +33 -1
  55. data/ext/common/Utils.h +14 -0
  56. data/ext/common/Utils/StrIntUtils.cpp +16 -0
  57. data/ext/common/Utils/StrIntUtils.h +5 -0
  58. data/ext/common/agents/HelperAgent/Main.cpp +5 -5
  59. data/ext/common/agents/HelperAgent/RequestHandler.h +94 -45
  60. data/ext/common/agents/LoggingAgent/Main.cpp +10 -26
  61. data/ext/common/agents/Watchdog/Main.cpp +4 -15
  62. data/ext/nginx/CacheLocationConfig.c +501 -0
  63. data/ext/nginx/CacheLocationConfig.c.erb +140 -0
  64. data/ext/nginx/Configuration.c +29 -453
  65. data/ext/nginx/Configuration.h +3 -21
  66. data/ext/nginx/ConfigurationCommands.c +501 -0
  67. data/ext/nginx/ConfigurationCommands.c.erb +136 -0
  68. data/ext/nginx/ConfigurationFields.h +89 -0
  69. data/ext/nginx/ConfigurationFields.h.erb +85 -0
  70. data/ext/nginx/ContentHandler.c +3 -166
  71. data/ext/nginx/CreateLocationConfig.c +146 -0
  72. data/ext/nginx/CreateLocationConfig.c.erb +70 -0
  73. data/ext/nginx/MergeLocationConfig.c +166 -0
  74. data/ext/nginx/MergeLocationConfig.c.erb +72 -0
  75. data/ext/nginx/config +4 -0
  76. data/ext/oxt/detail/tracable_exception_disabled.hpp +21 -1
  77. data/ext/oxt/detail/tracable_exception_enabled.hpp +4 -1
  78. data/ext/oxt/implementation.cpp +7 -1
  79. data/ext/oxt/macros.hpp +9 -7
  80. data/helper-scripts/backtrace-sanitizer.rb +23 -0
  81. data/helper-scripts/classic-rails-loader.rb +23 -0
  82. data/helper-scripts/classic-rails-preloader.rb +23 -0
  83. data/helper-scripts/download_binaries/extconf.rb +10 -5
  84. data/helper-scripts/meteor-loader.rb +127 -0
  85. data/helper-scripts/node-loader.js +1 -1
  86. data/helper-scripts/rack-preloader.rb +23 -0
  87. data/helper-scripts/system-memory-stats.py +22 -0
  88. data/helper-scripts/touch-dir.sh +48 -0
  89. data/lib/phusion_passenger.rb +1 -1
  90. data/lib/phusion_passenger/apache2/config_options.rb +104 -0
  91. data/lib/phusion_passenger/constants.rb +8 -0
  92. data/lib/phusion_passenger/native_support.rb +9 -1
  93. data/lib/phusion_passenger/nginx/config_options.rb +328 -0
  94. data/lib/phusion_passenger/packaging.rb +2 -2
  95. data/lib/phusion_passenger/platform_info/apache.rb +8 -0
  96. data/lib/phusion_passenger/platform_info/compiler.rb +2 -2
  97. data/lib/phusion_passenger/rails3_extensions/init.rb +19 -4
  98. data/lib/phusion_passenger/ruby_core_enhancements.rb +4 -1
  99. data/lib/phusion_passenger/standalone/app_finder.rb +3 -2
  100. data/lib/phusion_passenger/standalone/command.rb +1 -0
  101. data/lib/phusion_passenger/standalone/runtime_installer.rb +1 -6
  102. data/lib/phusion_passenger/standalone/runtime_locator.rb +9 -2
  103. data/lib/phusion_passenger/standalone/start_command.rb +45 -9
  104. data/lib/phusion_passenger/utils.rb +4 -1
  105. data/resources/templates/{nginx → installer_common}/run_installer_as_root.txt.erb +3 -1
  106. data/resources/templates/nginx/nginx_module_sources_not_available.txt.erb +6 -0
  107. data/resources/templates/standalone/config.erb +8 -8
  108. data/test/cxx/ApplicationPool2/PoolTest.cpp +120 -3
  109. data/test/cxx/RequestHandlerTest.cpp +66 -3
  110. data/test/integration_tests/native_packaging_spec.rb +41 -0
  111. data/test/integration_tests/nginx_tests.rb +1 -0
  112. data/test/integration_tests/standalone_tests.rb +4 -0
  113. data/test/ruby/shared/rails/analytics_logging_extensions_sharedspec.rb +22 -0
  114. data/test/stub/rails3.0/config/initializers/passenger.rb +2 -1
  115. data/test/stub/rails3.1/config/initializers/passenger.rb +2 -1
  116. data/test/stub/rails3.2/config/initializers/passenger.rb +2 -1
  117. data/test/stub/rails4.0/config/initializers/passenger.rb +5 -1
  118. data/test/stub/wsgi/passenger_wsgi.py +5 -0
  119. metadata +32 -7
  120. metadata.gz.asc +7 -7
  121. data/resources/templates/apache2/run_installer_as_root.txt.erb +0 -8
@@ -237,6 +237,11 @@ integerToHexatri(IntegerType value, char *output) {
237
237
  */
238
238
  string integerToHexatri(long long value);
239
239
 
240
+ /**
241
+ * Checks whether the given string looks like a number >= 0.
242
+ */
243
+ bool looksLikePositiveNumber(const StaticString &str);
244
+
240
245
  /**
241
246
  * Converts the given string to an integer.
242
247
  */
@@ -329,8 +329,8 @@ private:
329
329
  */
330
330
  void lowerPrivilege(const string &username, const string &groupname) {
331
331
  struct passwd *userEntry;
332
- struct group *groupEntry;
333
- int e;
332
+ gid_t gid;
333
+ int e;
334
334
 
335
335
  userEntry = getpwnam(username.c_str());
336
336
  if (userEntry == NULL) {
@@ -338,8 +338,8 @@ private:
338
338
  "HelperAgent's privilege to that of user '") + username +
339
339
  "': user does not exist.");
340
340
  }
341
- groupEntry = getgrnam(groupname.c_str());
342
- if (groupEntry == NULL) {
341
+ gid = lookupGid(groupname);
342
+ if (gid == (gid_t) -1) {
343
343
  throw NonExistentGroupException(string("Unable to lower Passenger "
344
344
  "HelperAgent's privilege to that of user '") + username +
345
345
  "': user does not exist.");
@@ -351,7 +351,7 @@ private:
351
351
  "privilege to that of user '") + username +
352
352
  "': cannot set supplementary groups for this user", e);
353
353
  }
354
- if (setgid(groupEntry->gr_gid) != 0) {
354
+ if (setgid(gid) != 0) {
355
355
  e = errno;
356
356
  throw SystemException(string("Unable to lower Passenger HelperAgent's "
357
357
  "privilege to that of user '") + username +
@@ -120,6 +120,7 @@ using namespace ApplicationPool2;
120
120
 
121
121
  class RequestHandler;
122
122
 
123
+ #define RH_ERROR(client, x) P_ERROR("[Client " << client->name() << "] " << x)
123
124
  #define RH_WARN(client, x) P_WARN("[Client " << client->name() << "] " << x)
124
125
  #define RH_DEBUG(client, x) P_DEBUG("[Client " << client->name() << "] " << x)
125
126
  #define RH_TRACE(client, level, x) P_TRACE(level, "[Client " << client->name() << "] " << x)
@@ -651,28 +652,38 @@ private:
651
652
  }
652
653
  }
653
654
 
654
- void writeSimpleResponse(const ClientPtr &client, const StaticString &data) {
655
- char header[256];
655
+ void writeSimpleResponse(const ClientPtr &client, const StaticString &data, int code = 200) {
656
+ char header[256], statusBuffer[50];
656
657
  char *pos = header;
657
658
  const char *end = header + sizeof(header) - 1;
659
+ const char *status;
660
+
661
+ status = getStatusCodeAndReasonPhrase(code);
662
+ if (status == NULL) {
663
+ snprintf(statusBuffer, sizeof(statusBuffer), "%d Unknown Reason-Phrase", code);
664
+ status = statusBuffer;
665
+ }
658
666
 
659
667
  if (getBoolOption(client, "PASSENGER_STATUS_LINE", true)) {
660
- pos = appendData(pos, end, "HTTP/1.1 200 OK\r\n");
668
+ pos += snprintf(pos, end - pos, "HTTP/1.1 %s\r\n",
669
+ status);
661
670
  }
662
671
  pos += snprintf(pos, end - pos,
663
- "Status: 200 OK\r\n"
672
+ "Status: %s\r\n"
664
673
  "Content-Length: %lu\r\n"
665
674
  "Content-Type: text/html; charset=UTF-8\r\n"
666
675
  "Cache-Control: no-cache, no-store, must-revalidate\r\n"
667
676
  "\r\n",
668
- (unsigned long) data.size());
677
+ status, (unsigned long) data.size());
669
678
 
670
679
  client->clientOutputPipe->write(header, pos - header);
671
680
  client->clientOutputPipe->write(data.data(), data.size());
672
681
  client->clientOutputPipe->end();
673
682
 
674
683
  if (client->useUnionStation()) {
675
- client->logMessage("Status: 200 OK");
684
+ snprintf(header, end - header, "Status: %d %s",
685
+ code, status);
686
+ client->logMessage(header);
676
687
  }
677
688
  }
678
689
 
@@ -1621,6 +1632,13 @@ private:
1621
1632
  }
1622
1633
  }
1623
1634
 
1635
+ static void fillPoolOptionSecToMsec(const ClientPtr &client, unsigned int &field, const StaticString &name) {
1636
+ ScgiRequestParser::const_iterator it = client->scgiParser.getHeaderIterator(name);
1637
+ if (it != client->scgiParser.end()) {
1638
+ field = stringToUint(it->second) * 1000;
1639
+ }
1640
+ }
1641
+
1624
1642
  void fillPoolOptions(const ClientPtr &client) {
1625
1643
  Options &options = client->options;
1626
1644
  ScgiRequestParser &parser = client->scgiParser;
@@ -1670,8 +1688,9 @@ private:
1670
1688
  fillPoolOption(client, options.maxRequests, "PASSENGER_MAX_REQUESTS");
1671
1689
  fillPoolOption(client, options.spawnMethod, "PASSENGER_SPAWN_METHOD");
1672
1690
  fillPoolOption(client, options.startCommand, "PASSENGER_START_COMMAND");
1673
- fillPoolOption(client, options.startTimeout, "PASSENGER_START_TIMEOUT");
1691
+ fillPoolOptionSecToMsec(client, options.startTimeout, "PASSENGER_START_TIMEOUT");
1674
1692
  fillPoolOption(client, options.maxPreloaderIdleTime, "PASSENGER_MAX_PRELOADER_IDLE_TIME");
1693
+ fillPoolOption(client, options.maxRequestQueueSize, "PASSENGER_MAX_REQUEST_QUEUE_SIZE");
1675
1694
  fillPoolOption(client, options.statThrottleRate, "PASSENGER_STAT_THROTTLE_RATE");
1676
1695
  fillPoolOption(client, options.restartDir, "PASSENGER_RESTART_DIR");
1677
1696
  fillPoolOption(client, options.loadShellEnvvars, "PASSENGER_LOAD_SHELL_ENVVARS");
@@ -1890,47 +1909,21 @@ private:
1890
1909
 
1891
1910
  if (e != NULL) {
1892
1911
  client->endScopeLog(&client->scopeLogs.getFromPool, false);
1893
- shared_ptr<SpawnException> e2 = dynamic_pointer_cast<SpawnException>(e);
1894
- if (e2 != NULL) {
1895
- if (strip(e2->getErrorPage()).empty()) {
1896
- RH_WARN(client, "Cannot checkout session. " << e2->what());
1897
- writeErrorResponse(client, e2->what());
1898
- } else {
1899
- RH_WARN(client, "Cannot checkout session. " << e2->what() <<
1900
- "\nError page:\n" << e2->getErrorPage());
1901
- writeErrorResponse(client, e2->getErrorPage(), e2.get());
1912
+ {
1913
+ shared_ptr<RequestQueueFullException> e2 = dynamic_pointer_cast<RequestQueueFullException>(e);
1914
+ if (e2 != NULL) {
1915
+ writeRequestQueueFullExceptionErrorResponse(client);
1916
+ return;
1902
1917
  }
1903
- } else {
1904
- string typeName;
1905
- #ifdef CXX_ABI_API_AVAILABLE
1906
- int status;
1907
- char *tmp = abi::__cxa_demangle(typeid(*e).name(), 0, 0, &status);
1908
- if (tmp != NULL) {
1909
- typeName = tmp;
1910
- free(tmp);
1911
- } else {
1912
- typeName = typeid(*e).name();
1913
- }
1914
- #else
1915
- typeName = typeid(*e).name();
1916
- #endif
1917
-
1918
- RH_WARN(client, "Cannot checkout session (exception type " <<
1919
- typeName << "): " << e->what());
1920
-
1921
- string response = "An internal error occurred while trying to spawn the application.\n";
1922
- response.append("Exception type: ");
1923
- response.append(typeName);
1924
- response.append("\nError message: ");
1925
- response.append(e->what());
1926
- shared_ptr<tracable_exception> e3 = dynamic_pointer_cast<tracable_exception>(e);
1927
- if (e3 != NULL) {
1928
- response.append("\nBacktrace:\n");
1929
- response.append(e3->backtrace());
1918
+ }
1919
+ {
1920
+ shared_ptr<SpawnException> e2 = dynamic_pointer_cast<SpawnException>(e);
1921
+ if (e2 != NULL) {
1922
+ writeSpawnExceptionErrorResponse(client, e2);
1923
+ return;
1930
1924
  }
1931
-
1932
- writeErrorResponse(client, response);
1933
1925
  }
1926
+ writeOtherExceptionErrorResponse(client, e);
1934
1927
  } else {
1935
1928
  RH_DEBUG(client, "Session checked out: pid=" << session->getPid() <<
1936
1929
  ", gupid=" << session->getGupid());
@@ -1939,6 +1932,62 @@ private:
1939
1932
  }
1940
1933
  }
1941
1934
 
1935
+ void writeRequestQueueFullExceptionErrorResponse(const ClientPtr &client) {
1936
+ StaticString value = client->scgiParser.getHeader("PASSENGER_REQUEST_QUEUE_OVERFLOW_STATUS_CODE");
1937
+ int requestQueueOverflowStatusCode = 503;
1938
+ if (!value.empty()) {
1939
+ requestQueueOverflowStatusCode = atoi(value.data());
1940
+ }
1941
+ writeSimpleResponse(client,
1942
+ "<h1>This website is under heavy load</h1>"
1943
+ "<p>We're sorry, too many people are accessing this website at the same "
1944
+ "time. We're working on this problem. Please try again later.</p>",
1945
+ requestQueueOverflowStatusCode);
1946
+ }
1947
+
1948
+ void writeSpawnExceptionErrorResponse(const ClientPtr &client, const shared_ptr<SpawnException> &e) {
1949
+ if (strip(e->getErrorPage()).empty()) {
1950
+ RH_WARN(client, "Cannot checkout session. " << e->what());
1951
+ writeErrorResponse(client, e->what());
1952
+ } else {
1953
+ RH_WARN(client, "Cannot checkout session. " << e->what() <<
1954
+ "\nError page:\n" << e->getErrorPage());
1955
+ writeErrorResponse(client, e->getErrorPage(), e.get());
1956
+ }
1957
+ }
1958
+
1959
+ void writeOtherExceptionErrorResponse(const ClientPtr &client, const ExceptionPtr &e) {
1960
+ string typeName;
1961
+ #ifdef CXX_ABI_API_AVAILABLE
1962
+ int status;
1963
+ char *tmp = abi::__cxa_demangle(typeid(*e).name(), 0, 0, &status);
1964
+ if (tmp != NULL) {
1965
+ typeName = tmp;
1966
+ free(tmp);
1967
+ } else {
1968
+ typeName = typeid(*e).name();
1969
+ }
1970
+ #else
1971
+ typeName = typeid(*e).name();
1972
+ #endif
1973
+
1974
+ RH_WARN(client, "Cannot checkout session (exception type " <<
1975
+ typeName << "): " << e->what());
1976
+
1977
+ string response = "An internal error occurred while trying to spawn the application.\n";
1978
+ response.append("Exception type: ");
1979
+ response.append(typeName);
1980
+ response.append("\nError message: ");
1981
+ response.append(e->what());
1982
+ shared_ptr<tracable_exception> e3 = dynamic_pointer_cast<tracable_exception>(e);
1983
+ if (e3 != NULL) {
1984
+ response.append("\nBacktrace:\n");
1985
+ response.append(e3->backtrace());
1986
+ }
1987
+
1988
+ writeErrorResponse(client, response);
1989
+ }
1990
+
1942
1991
  void initiateSession(const ClientPtr &client) {
1943
1992
  assert(client->state == Client::CHECKING_OUT_SESSION);
1944
1993
  client->sessionCheckoutTry++;
@@ -182,19 +182,19 @@ initializePrivilegedWorkingObjects(WorkingObjects &wo) {
182
182
  }
183
183
 
184
184
  static void
185
- lowerPrivilege(const string &username, const struct passwd *user, const struct group *group) {
185
+ lowerPrivilege(const string &username, const struct passwd *user, gid_t gid) {
186
186
  int e;
187
187
 
188
- if (initgroups(username.c_str(), group->gr_gid) != 0) {
188
+ if (initgroups(username.c_str(), gid) != 0) {
189
189
  e = errno;
190
190
  P_WARN("WARNING: Unable to set supplementary groups for " <<
191
191
  "PassengerLoggingAgent: " << strerror(e) << " (" << e << ")");
192
192
  }
193
- if (setgid(group->gr_gid) != 0) {
193
+ if (setgid(gid) != 0) {
194
194
  e = errno;
195
195
  P_WARN("WARNING: Unable to lower PassengerLoggingAgent's "
196
196
  "privilege to that of user '" << username <<
197
- "': cannot set group ID to " << group->gr_gid <<
197
+ "': cannot set group ID to " << gid <<
198
198
  ": " << strerror(e) <<
199
199
  " (" << e << ")");
200
200
  }
@@ -210,7 +210,7 @@ lowerPrivilege(const string &username, const struct passwd *user, const struct g
210
210
  static void
211
211
  maybeLowerPrivilege() {
212
212
  struct passwd *user;
213
- struct group *group;
213
+ gid_t gid;
214
214
 
215
215
  /* Sanity check user accounts. */
216
216
 
@@ -224,27 +224,11 @@ maybeLowerPrivilege() {
224
224
  }
225
225
 
226
226
  if (groupname.empty()) {
227
- group = getgrgid(user->pw_gid);
228
- if (group == NULL) {
229
- throw NonExistentGroupException(string("The configuration option ") +
230
- "'PassengerAnalyticsLogGroup' (Apache) or " +
231
- "'passenger_analytics_log_group' (Nginx) wasn't set, " +
232
- "so PassengerLoggingAgent tried to use the default group " +
233
- "for user '" + username + "' - which is GID #" +
234
- toString(user->pw_gid) + " - as the group for the analytics " +
235
- "log dir, but this GID doesn't exist. " +
236
- "You can solve this problem by explicitly " +
237
- "setting PassengerAnalyticsLogGroup (Apache) or " +
238
- "passenger_analytics_log_group (Nginx) to a group that " +
239
- "does exist. In any case, it looks like your system's user " +
240
- "database is broken; Phusion Passenger can work fine even " +
241
- "with this broken user database, but you should still fix it.");
242
- } else {
243
- groupname = group->gr_name;
244
- }
227
+ gid = user->pw_gid;
228
+ groupname = getGroupName(user->pw_gid);
245
229
  } else {
246
- group = getgrnam(groupname.c_str());
247
- if (group == NULL) {
230
+ gid = lookupGid(groupname);
231
+ if (gid == (gid_t) -1) {
248
232
  throw NonExistentGroupException(string("The configuration option ") +
249
233
  "'PassengerAnalyticsLogGroup' (Apache) or " +
250
234
  "'passenger_analytics_log_group' (Nginx) was set to '" +
@@ -255,7 +239,7 @@ maybeLowerPrivilege() {
255
239
 
256
240
  /* Now's a good time to lower the privilege. */
257
241
  if (geteuid() == 0) {
258
- lowerPrivilege(username, user, group);
242
+ lowerPrivilege(username, user, gid);
259
243
  }
260
244
  }
261
245
 
@@ -54,6 +54,7 @@
54
54
  #include <Utils/Base64.h>
55
55
  #include <Utils/Timer.h>
56
56
  #include <Utils/ScopeGuard.h>
57
+ #include <Utils/StrIntUtils.h>
57
58
  #include <Utils/IOUtils.h>
58
59
  #include <Utils/MessageIO.h>
59
60
  #include <Utils/VariantMap.h>
@@ -378,17 +379,7 @@ inferDefaultGroup(const string &defaultUser) {
378
379
  string("The user that PassengerDefaultUser refers to, '") +
379
380
  defaultUser + "', does not exist.");
380
381
  }
381
-
382
- struct group *groupEntry = getgrgid(userEntry->pw_gid);
383
- if (groupEntry == NULL) {
384
- throw ConfigurationException(
385
- string("The option PassengerDefaultUser is set to '" +
386
- defaultUser + "', but its primary group doesn't exist. "
387
- "In other words, your system's user account database "
388
- "is broken. Please fix it."));
389
- }
390
-
391
- return groupEntry->gr_name;
382
+ return getGroupName(userEntry->pw_gid);
392
383
  }
393
384
 
394
385
  static void
@@ -477,7 +468,6 @@ maybeSetsid() {
477
468
  static void
478
469
  lookupDefaultUidGid(uid_t &uid, gid_t &gid) {
479
470
  struct passwd *userEntry;
480
- struct group *groupEntry;
481
471
 
482
472
  userEntry = getpwnam(defaultUser.c_str());
483
473
  if (userEntry == NULL) {
@@ -486,12 +476,11 @@ lookupDefaultUidGid(uid_t &uid, gid_t &gid) {
486
476
  }
487
477
  uid = userEntry->pw_uid;
488
478
 
489
- groupEntry = getgrnam(defaultGroup.c_str());
490
- if (groupEntry == NULL) {
479
+ gid = lookupGid(defaultGroup);
480
+ if (gid == (gid_t) -1) {
491
481
  throw NonExistentGroupException("Default group '" + defaultGroup +
492
482
  "' does not exist.");
493
483
  }
494
- gid = groupEntry->gr_gid;
495
484
  }
496
485
 
497
486
  static void
@@ -0,0 +1,501 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2010-2013 Phusion
4
+ *
5
+ * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ */
25
+
26
+ /*
27
+ * CacheLocationConfig.c is automatically generated from CacheLocationConfig.c.erb,
28
+ * using definitions from lib/phusion_passenger/nginx/config_options.rb.
29
+ * Edits to MergeLocationConfig.c will be lost.
30
+ *
31
+ * To update CacheLocationConfig.c:
32
+ * rake nginx
33
+ *
34
+ * To force regeneration of CacheLocationConfig.c:
35
+ * rm -f ext/nginx/CacheLocationConfig.c
36
+ * rake ext/nginx/CacheLocationConfig.c
37
+ */
38
+
39
+
40
+
41
+ size_t len = 0;
42
+ u_char int_buf[32], *end, *buf, *pos;
43
+
44
+ /* Calculate lengths */
45
+
46
+
47
+ if (conf->ruby.data != NULL) {
48
+ len += 15;
49
+ len += conf->ruby.len + 1;
50
+ }
51
+
52
+
53
+
54
+ if (conf->python.data != NULL) {
55
+ len += 17;
56
+ len += conf->python.len + 1;
57
+ }
58
+
59
+
60
+
61
+ if (conf->environment.data != NULL) {
62
+ len += 14;
63
+ len += conf->environment.len + 1;
64
+ }
65
+
66
+
67
+
68
+ if (conf->friendly_error_pages != NGX_CONF_UNSET) {
69
+ len += 31;
70
+ len += conf->friendly_error_pages ? sizeof("true") : sizeof("false");
71
+ }
72
+
73
+
74
+
75
+ if (conf->min_instances != NGX_CONF_UNSET) {
76
+ end = ngx_snprintf(int_buf,
77
+ sizeof(int_buf) - 1,
78
+ "%d",
79
+ conf->min_instances);
80
+ len += 24;
81
+ len += end - int_buf + 1;
82
+ }
83
+
84
+
85
+
86
+ if (conf->max_requests != NGX_CONF_UNSET) {
87
+ end = ngx_snprintf(int_buf,
88
+ sizeof(int_buf) - 1,
89
+ "%d",
90
+ conf->max_requests);
91
+ len += 23;
92
+ len += end - int_buf + 1;
93
+ }
94
+
95
+
96
+
97
+ if (conf->start_timeout != NGX_CONF_UNSET) {
98
+ end = ngx_snprintf(int_buf,
99
+ sizeof(int_buf) - 1,
100
+ "%d",
101
+ conf->start_timeout);
102
+ len += 24;
103
+ len += end - int_buf + 1;
104
+ }
105
+
106
+
107
+
108
+ if (conf->user.data != NULL) {
109
+ len += 15;
110
+ len += conf->user.len + 1;
111
+ }
112
+
113
+
114
+
115
+ if (conf->group.data != NULL) {
116
+ len += 16;
117
+ len += conf->group.len + 1;
118
+ }
119
+
120
+
121
+
122
+ if (conf->app_group_name.data != NULL) {
123
+ len += 25;
124
+ len += conf->app_group_name.len + 1;
125
+ }
126
+
127
+
128
+
129
+ if (conf->app_root.data != NULL) {
130
+ len += 19;
131
+ len += conf->app_root.len + 1;
132
+ }
133
+
134
+
135
+
136
+ if (conf->app_rights.data != NULL) {
137
+ len += 21;
138
+ len += conf->app_rights.len + 1;
139
+ }
140
+
141
+
142
+
143
+ if (conf->union_station_support != NGX_CONF_UNSET) {
144
+ len += 22;
145
+ len += conf->union_station_support ? sizeof("true") : sizeof("false");
146
+ }
147
+
148
+
149
+
150
+ if (conf->debugger != NGX_CONF_UNSET) {
151
+ len += 19;
152
+ len += conf->debugger ? sizeof("true") : sizeof("false");
153
+ }
154
+
155
+
156
+
157
+ if (conf->show_version_in_header != NGX_CONF_UNSET) {
158
+ len += 33;
159
+ len += conf->show_version_in_header ? sizeof("true") : sizeof("false");
160
+ }
161
+
162
+
163
+
164
+ if (conf->max_preloader_idle_time != NGX_CONF_UNSET) {
165
+ end = ngx_snprintf(int_buf,
166
+ sizeof(int_buf) - 1,
167
+ "%d",
168
+ conf->max_preloader_idle_time);
169
+ len += 34;
170
+ len += end - int_buf + 1;
171
+ }
172
+
173
+
174
+
175
+ if (conf->spawn_method.data != NULL) {
176
+ len += 23;
177
+ len += conf->spawn_method.len + 1;
178
+ }
179
+
180
+
181
+
182
+ if (conf->union_station_key.data != NULL) {
183
+ len += 18;
184
+ len += conf->union_station_key.len + 1;
185
+ }
186
+
187
+
188
+
189
+ if (conf->max_request_queue_size != NGX_CONF_UNSET) {
190
+ end = ngx_snprintf(int_buf,
191
+ sizeof(int_buf) - 1,
192
+ "%d",
193
+ conf->max_request_queue_size);
194
+ len += 33;
195
+ len += end - int_buf + 1;
196
+ }
197
+
198
+
199
+
200
+ if (conf->request_queue_overflow_status_code != NGX_CONF_UNSET) {
201
+ end = ngx_snprintf(int_buf,
202
+ sizeof(int_buf) - 1,
203
+ "%d",
204
+ conf->request_queue_overflow_status_code);
205
+ len += 45;
206
+ len += end - int_buf + 1;
207
+ }
208
+
209
+
210
+
211
+ /* Create string */
212
+ buf = pos = ngx_pnalloc(cf->pool, len);
213
+
214
+
215
+
216
+ if (conf->ruby.data != NULL) {
217
+ pos = ngx_copy(pos,
218
+ "PASSENGER_RUBY",
219
+ 15);
220
+ pos = ngx_copy(pos,
221
+ conf->ruby.data,
222
+ conf->ruby.len);
223
+ *pos = '\0';
224
+ pos++;
225
+ }
226
+
227
+
228
+
229
+ if (conf->python.data != NULL) {
230
+ pos = ngx_copy(pos,
231
+ "PASSENGER_PYTHON",
232
+ 17);
233
+ pos = ngx_copy(pos,
234
+ conf->python.data,
235
+ conf->python.len);
236
+ *pos = '\0';
237
+ pos++;
238
+ }
239
+
240
+
241
+
242
+ if (conf->environment.data != NULL) {
243
+ pos = ngx_copy(pos,
244
+ "PASSENGER_ENV",
245
+ 14);
246
+ pos = ngx_copy(pos,
247
+ conf->environment.data,
248
+ conf->environment.len);
249
+ *pos = '\0';
250
+ pos++;
251
+ }
252
+
253
+
254
+
255
+ if (conf->friendly_error_pages != NGX_CONF_UNSET) {
256
+ pos = ngx_copy(pos,
257
+ "PASSENGER_FRIENDLY_ERROR_PAGES",
258
+ 31);
259
+ if (conf->friendly_error_pages) {
260
+ pos = ngx_copy(pos, "true", sizeof("true"));
261
+ } else {
262
+ pos = ngx_copy(pos, "false", sizeof("false"));
263
+ }
264
+ }
265
+
266
+
267
+
268
+ if (conf->min_instances != NGX_CONF_UNSET) {
269
+ pos = ngx_copy(pos,
270
+ "PASSENGER_MIN_INSTANCES",
271
+ 24);
272
+ end = ngx_snprintf(int_buf,
273
+ sizeof(int_buf) - 1,
274
+ "%d",
275
+ conf->min_instances);
276
+ pos = ngx_copy(pos,
277
+ int_buf,
278
+ end - int_buf);
279
+ *pos = '\0';
280
+ pos++;
281
+ }
282
+
283
+
284
+
285
+ if (conf->max_requests != NGX_CONF_UNSET) {
286
+ pos = ngx_copy(pos,
287
+ "PASSENGER_MAX_REQUESTS",
288
+ 23);
289
+ end = ngx_snprintf(int_buf,
290
+ sizeof(int_buf) - 1,
291
+ "%d",
292
+ conf->max_requests);
293
+ pos = ngx_copy(pos,
294
+ int_buf,
295
+ end - int_buf);
296
+ *pos = '\0';
297
+ pos++;
298
+ }
299
+
300
+
301
+
302
+ if (conf->start_timeout != NGX_CONF_UNSET) {
303
+ pos = ngx_copy(pos,
304
+ "PASSENGER_START_TIMEOUT",
305
+ 24);
306
+ end = ngx_snprintf(int_buf,
307
+ sizeof(int_buf) - 1,
308
+ "%d",
309
+ conf->start_timeout);
310
+ pos = ngx_copy(pos,
311
+ int_buf,
312
+ end - int_buf);
313
+ *pos = '\0';
314
+ pos++;
315
+ }
316
+
317
+
318
+
319
+ if (conf->user.data != NULL) {
320
+ pos = ngx_copy(pos,
321
+ "PASSENGER_USER",
322
+ 15);
323
+ pos = ngx_copy(pos,
324
+ conf->user.data,
325
+ conf->user.len);
326
+ *pos = '\0';
327
+ pos++;
328
+ }
329
+
330
+
331
+
332
+ if (conf->group.data != NULL) {
333
+ pos = ngx_copy(pos,
334
+ "PASSENGER_GROUP",
335
+ 16);
336
+ pos = ngx_copy(pos,
337
+ conf->group.data,
338
+ conf->group.len);
339
+ *pos = '\0';
340
+ pos++;
341
+ }
342
+
343
+
344
+
345
+ if (conf->app_group_name.data != NULL) {
346
+ pos = ngx_copy(pos,
347
+ "PASSENGER_APP_GROUP_NAME",
348
+ 25);
349
+ pos = ngx_copy(pos,
350
+ conf->app_group_name.data,
351
+ conf->app_group_name.len);
352
+ *pos = '\0';
353
+ pos++;
354
+ }
355
+
356
+
357
+
358
+ if (conf->app_root.data != NULL) {
359
+ pos = ngx_copy(pos,
360
+ "PASSENGER_APP_ROOT",
361
+ 19);
362
+ pos = ngx_copy(pos,
363
+ conf->app_root.data,
364
+ conf->app_root.len);
365
+ *pos = '\0';
366
+ pos++;
367
+ }
368
+
369
+
370
+
371
+ if (conf->app_rights.data != NULL) {
372
+ pos = ngx_copy(pos,
373
+ "PASSENGER_APP_RIGHTS",
374
+ 21);
375
+ pos = ngx_copy(pos,
376
+ conf->app_rights.data,
377
+ conf->app_rights.len);
378
+ *pos = '\0';
379
+ pos++;
380
+ }
381
+
382
+
383
+
384
+ if (conf->union_station_support != NGX_CONF_UNSET) {
385
+ pos = ngx_copy(pos,
386
+ "UNION_STATION_SUPPORT",
387
+ 22);
388
+ if (conf->union_station_support) {
389
+ pos = ngx_copy(pos, "true", sizeof("true"));
390
+ } else {
391
+ pos = ngx_copy(pos, "false", sizeof("false"));
392
+ }
393
+ }
394
+
395
+
396
+
397
+ if (conf->debugger != NGX_CONF_UNSET) {
398
+ pos = ngx_copy(pos,
399
+ "PASSENGER_DEBUGGER",
400
+ 19);
401
+ if (conf->debugger) {
402
+ pos = ngx_copy(pos, "true", sizeof("true"));
403
+ } else {
404
+ pos = ngx_copy(pos, "false", sizeof("false"));
405
+ }
406
+ }
407
+
408
+
409
+
410
+ if (conf->show_version_in_header != NGX_CONF_UNSET) {
411
+ pos = ngx_copy(pos,
412
+ "PASSENGER_SHOW_VERSION_IN_HEADER",
413
+ 33);
414
+ if (conf->show_version_in_header) {
415
+ pos = ngx_copy(pos, "true", sizeof("true"));
416
+ } else {
417
+ pos = ngx_copy(pos, "false", sizeof("false"));
418
+ }
419
+ }
420
+
421
+
422
+
423
+ if (conf->max_preloader_idle_time != NGX_CONF_UNSET) {
424
+ pos = ngx_copy(pos,
425
+ "PASSENGER_MAX_PRELOADER_IDLE_TIME",
426
+ 34);
427
+ end = ngx_snprintf(int_buf,
428
+ sizeof(int_buf) - 1,
429
+ "%d",
430
+ conf->max_preloader_idle_time);
431
+ pos = ngx_copy(pos,
432
+ int_buf,
433
+ end - int_buf);
434
+ *pos = '\0';
435
+ pos++;
436
+ }
437
+
438
+
439
+
440
+ if (conf->spawn_method.data != NULL) {
441
+ pos = ngx_copy(pos,
442
+ "PASSENGER_SPAWN_METHOD",
443
+ 23);
444
+ pos = ngx_copy(pos,
445
+ conf->spawn_method.data,
446
+ conf->spawn_method.len);
447
+ *pos = '\0';
448
+ pos++;
449
+ }
450
+
451
+
452
+
453
+ if (conf->union_station_key.data != NULL) {
454
+ pos = ngx_copy(pos,
455
+ "UNION_STATION_KEY",
456
+ 18);
457
+ pos = ngx_copy(pos,
458
+ conf->union_station_key.data,
459
+ conf->union_station_key.len);
460
+ *pos = '\0';
461
+ pos++;
462
+ }
463
+
464
+
465
+
466
+ if (conf->max_request_queue_size != NGX_CONF_UNSET) {
467
+ pos = ngx_copy(pos,
468
+ "PASSENGER_MAX_REQUEST_QUEUE_SIZE",
469
+ 33);
470
+ end = ngx_snprintf(int_buf,
471
+ sizeof(int_buf) - 1,
472
+ "%d",
473
+ conf->max_request_queue_size);
474
+ pos = ngx_copy(pos,
475
+ int_buf,
476
+ end - int_buf);
477
+ *pos = '\0';
478
+ pos++;
479
+ }
480
+
481
+
482
+
483
+ if (conf->request_queue_overflow_status_code != NGX_CONF_UNSET) {
484
+ pos = ngx_copy(pos,
485
+ "PASSENGER_REQUEST_QUEUE_OVERFLOW_STATUS_CODE",
486
+ 45);
487
+ end = ngx_snprintf(int_buf,
488
+ sizeof(int_buf) - 1,
489
+ "%d",
490
+ conf->request_queue_overflow_status_code);
491
+ pos = ngx_copy(pos,
492
+ int_buf,
493
+ end - int_buf);
494
+ *pos = '\0';
495
+ pos++;
496
+ }
497
+
498
+
499
+
500
+ conf->options_cache.data = buf;
501
+ conf->options_cache.len = pos - buf;