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.
- data.tar.gz.asc +7 -7
- data/NEWS +69 -0
- data/bin/passenger-install-apache2-module +7 -1
- data/bin/passenger-install-nginx-module +18 -1
- data/build/apache2.rb +25 -1
- data/build/basics.rb +7 -4
- data/build/debian.rb +72 -25
- data/build/nginx.rb +24 -0
- data/build/packaging.rb +45 -3
- data/debian.template/{control → control.template} +17 -8
- data/debian.template/ruby-passenger.install.template +1 -0
- data/debian.template/rules.template +9 -3
- data/dev/run_travis.sh +14 -0
- data/doc/Users guide Apache.idmap.txt +64 -48
- data/doc/Users guide Apache.txt +127 -93
- data/doc/Users guide Nginx.idmap.txt +46 -28
- data/doc/Users guide Nginx.txt +100 -12
- data/doc/images/{conservative_spawning.png → direct_spawning.png} +0 -0
- data/doc/images/{conservative_spawning.svg → direct_spawning.svg} +0 -0
- data/doc/users_guide_snippets/installation.txt +107 -66
- data/doc/users_guide_snippets/passenger_spawn_method.txt +1 -1
- data/doc/users_guide_snippets/rvm_helper_tool.txt +0 -12
- data/doc/users_guide_snippets/tips.txt +70 -3
- data/doc/users_guide_snippets/under_the_hood/page_caching_support.txt +2 -0
- data/doc/users_guide_snippets/under_the_hood/relationship_with_ruby.txt +114 -0
- data/ext/apache2/Configuration.cpp +53 -101
- data/ext/apache2/Configuration.hpp +19 -41
- data/ext/apache2/ConfigurationCommands.cpp +95 -0
- data/ext/apache2/ConfigurationCommands.cpp.erb +91 -0
- data/ext/apache2/ConfigurationFields.hpp +59 -0
- data/ext/apache2/ConfigurationFields.hpp.erb +89 -0
- data/ext/apache2/ConfigurationSetters.cpp +223 -0
- data/ext/apache2/ConfigurationSetters.cpp.erb +126 -0
- data/ext/apache2/CreateDirConfig.cpp +50 -0
- data/ext/apache2/CreateDirConfig.cpp.erb +71 -0
- data/ext/apache2/Hooks.cpp +6 -0
- data/ext/apache2/MergeDirConfig.cpp +103 -0
- data/ext/apache2/MergeDirConfig.cpp.erb +81 -0
- data/ext/common/ApplicationPool2/AppTypes.cpp +2 -0
- data/ext/common/ApplicationPool2/AppTypes.h +2 -0
- data/ext/common/ApplicationPool2/Common.h +1 -1
- data/ext/common/ApplicationPool2/Group.h +56 -7
- data/ext/common/ApplicationPool2/Implementation.cpp +133 -31
- data/ext/common/ApplicationPool2/Options.h +23 -2
- data/ext/common/ApplicationPool2/Pool.h +8 -1
- data/ext/common/ApplicationPool2/Process.h +9 -0
- data/ext/common/ApplicationPool2/Session.h +1 -0
- data/ext/common/ApplicationPool2/Spawner.h +21 -19
- data/ext/common/ApplicationPool2/SuperGroup.h +1 -1
- data/ext/common/Constants.h +21 -17
- data/ext/common/Constants.h.erb +1 -1
- data/ext/common/Exceptions.h +19 -0
- data/ext/common/ServerInstanceDir.h +8 -4
- data/ext/common/Utils.cpp +33 -1
- data/ext/common/Utils.h +14 -0
- data/ext/common/Utils/StrIntUtils.cpp +16 -0
- data/ext/common/Utils/StrIntUtils.h +5 -0
- data/ext/common/agents/HelperAgent/Main.cpp +5 -5
- data/ext/common/agents/HelperAgent/RequestHandler.h +94 -45
- data/ext/common/agents/LoggingAgent/Main.cpp +10 -26
- data/ext/common/agents/Watchdog/Main.cpp +4 -15
- data/ext/nginx/CacheLocationConfig.c +501 -0
- data/ext/nginx/CacheLocationConfig.c.erb +140 -0
- data/ext/nginx/Configuration.c +29 -453
- data/ext/nginx/Configuration.h +3 -21
- data/ext/nginx/ConfigurationCommands.c +501 -0
- data/ext/nginx/ConfigurationCommands.c.erb +136 -0
- data/ext/nginx/ConfigurationFields.h +89 -0
- data/ext/nginx/ConfigurationFields.h.erb +85 -0
- data/ext/nginx/ContentHandler.c +3 -166
- data/ext/nginx/CreateLocationConfig.c +146 -0
- data/ext/nginx/CreateLocationConfig.c.erb +70 -0
- data/ext/nginx/MergeLocationConfig.c +166 -0
- data/ext/nginx/MergeLocationConfig.c.erb +72 -0
- data/ext/nginx/config +4 -0
- data/ext/oxt/detail/tracable_exception_disabled.hpp +21 -1
- data/ext/oxt/detail/tracable_exception_enabled.hpp +4 -1
- data/ext/oxt/implementation.cpp +7 -1
- data/ext/oxt/macros.hpp +9 -7
- data/helper-scripts/backtrace-sanitizer.rb +23 -0
- data/helper-scripts/classic-rails-loader.rb +23 -0
- data/helper-scripts/classic-rails-preloader.rb +23 -0
- data/helper-scripts/download_binaries/extconf.rb +10 -5
- data/helper-scripts/meteor-loader.rb +127 -0
- data/helper-scripts/node-loader.js +1 -1
- data/helper-scripts/rack-preloader.rb +23 -0
- data/helper-scripts/system-memory-stats.py +22 -0
- data/helper-scripts/touch-dir.sh +48 -0
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/apache2/config_options.rb +104 -0
- data/lib/phusion_passenger/constants.rb +8 -0
- data/lib/phusion_passenger/native_support.rb +9 -1
- data/lib/phusion_passenger/nginx/config_options.rb +328 -0
- data/lib/phusion_passenger/packaging.rb +2 -2
- data/lib/phusion_passenger/platform_info/apache.rb +8 -0
- data/lib/phusion_passenger/platform_info/compiler.rb +2 -2
- data/lib/phusion_passenger/rails3_extensions/init.rb +19 -4
- data/lib/phusion_passenger/ruby_core_enhancements.rb +4 -1
- data/lib/phusion_passenger/standalone/app_finder.rb +3 -2
- data/lib/phusion_passenger/standalone/command.rb +1 -0
- data/lib/phusion_passenger/standalone/runtime_installer.rb +1 -6
- data/lib/phusion_passenger/standalone/runtime_locator.rb +9 -2
- data/lib/phusion_passenger/standalone/start_command.rb +45 -9
- data/lib/phusion_passenger/utils.rb +4 -1
- data/resources/templates/{nginx → installer_common}/run_installer_as_root.txt.erb +3 -1
- data/resources/templates/nginx/nginx_module_sources_not_available.txt.erb +6 -0
- data/resources/templates/standalone/config.erb +8 -8
- data/test/cxx/ApplicationPool2/PoolTest.cpp +120 -3
- data/test/cxx/RequestHandlerTest.cpp +66 -3
- data/test/integration_tests/native_packaging_spec.rb +41 -0
- data/test/integration_tests/nginx_tests.rb +1 -0
- data/test/integration_tests/standalone_tests.rb +4 -0
- data/test/ruby/shared/rails/analytics_logging_extensions_sharedspec.rb +22 -0
- data/test/stub/rails3.0/config/initializers/passenger.rb +2 -1
- data/test/stub/rails3.1/config/initializers/passenger.rb +2 -1
- data/test/stub/rails3.2/config/initializers/passenger.rb +2 -1
- data/test/stub/rails4.0/config/initializers/passenger.rb +5 -1
- data/test/stub/wsgi/passenger_wsgi.py +5 -0
- metadata +32 -7
- metadata.gz.asc +7 -7
- 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
|
-
|
333
|
-
int
|
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
|
-
|
342
|
-
if (
|
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(
|
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
|
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:
|
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
|
-
|
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
|
-
|
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
|
-
|
1894
|
-
|
1895
|
-
if (
|
1896
|
-
|
1897
|
-
|
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
|
-
}
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
|
1908
|
-
|
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,
|
185
|
+
lowerPrivilege(const string &username, const struct passwd *user, gid_t gid) {
|
186
186
|
int e;
|
187
187
|
|
188
|
-
if (initgroups(username.c_str(),
|
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(
|
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 " <<
|
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
|
-
|
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
|
-
|
228
|
-
|
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
|
-
|
247
|
-
if (
|
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,
|
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
|
-
|
490
|
-
if (
|
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;
|