passenger 4.0.2 → 4.0.3
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 +27 -0
- data/bin/passenger-config +6 -3
- data/bin/passenger-install-apache2-module +2 -2
- data/bin/passenger-install-nginx-module +16 -2
- data/build/agents.rb +4 -0
- data/build/apache2.rb +1 -1
- data/build/cplusplus_support.rb +1 -1
- data/build/cxx_tests.rb +3 -0
- data/build/packaging.rb +51 -8
- data/build/ruby_extension.rb +1 -1
- data/doc/Packaging.txt.md +20 -7
- data/doc/Users guide Apache.html +1 -1
- data/doc/Users guide Apache.txt +1 -1
- data/doc/Users guide Nginx.html +5 -4
- data/doc/Users guide Nginx.txt +1 -1
- data/doc/users_guide_snippets/installation.txt +5 -3
- data/ext/apache2/Configuration.cpp +12 -0
- data/ext/apache2/Configuration.hpp +7 -4
- data/ext/apache2/Hooks.cpp +29 -19
- data/ext/common/AgentsStarter.cpp +85 -57
- data/ext/common/AgentsStarter.h +570 -42
- data/ext/common/ApplicationPool2/DirectSpawner.h +5 -2
- data/ext/common/ApplicationPool2/Implementation.cpp +7 -1
- data/ext/common/ApplicationPool2/Pool.h +6 -3
- data/ext/common/ApplicationPool2/Process.h +12 -3
- data/ext/common/ApplicationPool2/SmartSpawner.h +2 -1
- data/ext/common/Constants.h +4 -1
- data/ext/common/EventedBufferedInput.h +139 -16
- data/ext/common/MultiLibeio.cpp +4 -2
- data/ext/common/SafeLibev.h +15 -62
- data/ext/common/ServerInstanceDir.h +10 -26
- data/ext/common/Utils.cpp +1 -3
- data/ext/common/Utils.h +1 -1
- data/ext/common/Utils/StrIntUtils.cpp +9 -0
- data/ext/common/Utils/StrIntUtils.h +5 -0
- data/ext/common/Utils/VariantMap.h +63 -14
- data/ext/common/agents/Base.cpp +50 -15
- data/ext/common/agents/HelperAgent/AgentOptions.h +20 -12
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +1 -1
- data/ext/common/agents/HelperAgent/Main.cpp +5 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +1 -1
- data/ext/common/agents/LoggingAgent/Main.cpp +0 -1
- data/ext/common/agents/LoggingAgent/RemoteSender.h +2 -2
- data/ext/common/agents/SpawnPreparer.cpp +23 -5
- data/ext/common/agents/Watchdog/AgentWatcher.cpp +508 -0
- data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +93 -0
- data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +68 -0
- data/ext/common/agents/Watchdog/Main.cpp +180 -802
- data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +111 -0
- data/ext/nginx/Configuration.c +107 -92
- data/ext/nginx/Configuration.h +1 -0
- data/ext/nginx/ContentHandler.c +6 -6
- data/ext/nginx/ContentHandler.h +1 -1
- data/ext/nginx/config +8 -2
- data/ext/nginx/ngx_http_passenger_module.c +54 -60
- data/ext/nginx/ngx_http_passenger_module.h +6 -6
- data/lib/phusion_passenger.rb +17 -10
- data/lib/phusion_passenger/admin_tools/server_instance.rb +2 -2
- data/lib/phusion_passenger/common_library.rb +0 -1
- data/lib/phusion_passenger/platform_info.rb +10 -1
- data/lib/phusion_passenger/platform_info/depcheck.rb +4 -4
- data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +2 -2
- data/lib/phusion_passenger/platform_info/ruby.rb +7 -0
- data/lib/phusion_passenger/request_handler.rb +119 -42
- data/lib/phusion_passenger/request_handler/thread_handler.rb +25 -22
- data/lib/phusion_passenger/standalone/command.rb +2 -0
- data/lib/phusion_passenger/standalone/runtime_installer.rb +4 -3
- data/lib/phusion_passenger/standalone/start_command.rb +49 -37
- data/resources/templates/nginx/pcre_checksum_could_not_be_verified.txt.erb +11 -0
- data/test/cxx/CxxTestMain.cpp +2 -0
- data/test/cxx/EventedBufferedInputTest.cpp +758 -0
- data/test/cxx/ServerInstanceDirTest.cpp +16 -31
- data/test/cxx/TestSupport.cpp +2 -1
- data/test/cxx/VariantMapTest.cpp +23 -11
- metadata +8 -4
- metadata.gz.asc +7 -7
- data/ext/common/AgentsStarter.hpp +0 -655
- data/lib/phusion_passenger/utils/robust_interruption.rb +0 -173
@@ -25,10 +25,11 @@
|
|
25
25
|
#ifndef _PASSENGER_CONFIGURATION_HPP_
|
26
26
|
#define _PASSENGER_CONFIGURATION_HPP_
|
27
27
|
|
28
|
-
#include
|
29
|
-
#include
|
30
|
-
#include
|
31
|
-
#include
|
28
|
+
#include <Logging.h>
|
29
|
+
#include <ServerInstanceDir.h>
|
30
|
+
#include <Constants.h>
|
31
|
+
#include <Utils.h>
|
32
|
+
#include <Utils/VariantMap.h>
|
32
33
|
|
33
34
|
/* The APR headers must come after the Passenger headers. See Hooks.cpp
|
34
35
|
* to learn why.
|
@@ -334,6 +335,8 @@ struct ServerConfig {
|
|
334
335
|
/** The Passenger root folder. */
|
335
336
|
const char *root;
|
336
337
|
|
338
|
+
VariantMap ctl;
|
339
|
+
|
337
340
|
/** The default Ruby interpreter to use. */
|
338
341
|
const char *defaultRuby;
|
339
342
|
|
data/ext/apache2/Hooks.cpp
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010
|
3
|
+
* Copyright (c) 2010-2013 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -53,7 +53,7 @@
|
|
53
53
|
#include "Utils/IOUtils.h"
|
54
54
|
#include "Utils/Timer.h"
|
55
55
|
#include "Logging.h"
|
56
|
-
#include "AgentsStarter.
|
56
|
+
#include "AgentsStarter.h"
|
57
57
|
#include "DirectoryMapper.h"
|
58
58
|
#include "Constants.h"
|
59
59
|
|
@@ -1237,7 +1237,7 @@ private:
|
|
1237
1237
|
public:
|
1238
1238
|
Hooks(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
|
1239
1239
|
: cstat(1024),
|
1240
|
-
agentsStarter(
|
1240
|
+
agentsStarter(AS_APACHE)
|
1241
1241
|
{
|
1242
1242
|
serverConfig.finalize();
|
1243
1243
|
Passenger::setLogLevel(serverConfig.logLevel);
|
@@ -1258,23 +1258,33 @@ public:
|
|
1258
1258
|
"TIP: The correct value for this option was given to you by "
|
1259
1259
|
"'passenger-install-apache2-module'.");
|
1260
1260
|
}
|
1261
|
+
|
1262
|
+
VariantMap params;
|
1263
|
+
params
|
1264
|
+
.setPid ("web_server_pid", getpid())
|
1265
|
+
.setUid ("web_server_worker_uid", unixd_config.user_id)
|
1266
|
+
.setGid ("web_server_worker_gid", unixd_config.group_id)
|
1267
|
+
.setInt ("log_level", serverConfig.logLevel)
|
1268
|
+
.set ("debug_log_file", (serverConfig.debugLogFile == NULL) ? "" : serverConfig.debugLogFile)
|
1269
|
+
.set ("temp_dir", serverConfig.tempDir)
|
1270
|
+
.setBool("user_switching", serverConfig.userSwitching)
|
1271
|
+
.set ("default_user", serverConfig.defaultUser)
|
1272
|
+
.set ("default_group", serverConfig.defaultGroup)
|
1273
|
+
.set ("default_ruby", serverConfig.defaultRuby)
|
1274
|
+
.setInt ("max_pool_size", serverConfig.maxPoolSize)
|
1275
|
+
.setInt ("pool_idle_time", serverConfig.poolIdleTime)
|
1276
|
+
.setInt ("max_instances_per_app", serverConfig.maxInstancesPerApp)
|
1277
|
+
.set ("analytics_log_user", serverConfig.analyticsLogUser)
|
1278
|
+
.set ("analytics_log_group", serverConfig.analyticsLogGroup)
|
1279
|
+
.set ("union_station_gateway_address", serverConfig.unionStationGatewayAddress)
|
1280
|
+
.setInt ("union_station_gateway_port", serverConfig.unionStationGatewayPort)
|
1281
|
+
.set ("union_station_gateway_cert", serverConfig.unionStationGatewayCert)
|
1282
|
+
.set ("union_station_proxy_address", serverConfig.unionStationProxyAddress)
|
1283
|
+
.setStrSet("prestart_urls", serverConfig.prestartURLs);
|
1261
1284
|
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
serverConfig.userSwitching,
|
1266
|
-
serverConfig.defaultUser, serverConfig.defaultGroup,
|
1267
|
-
unixd_config.user_id, unixd_config.group_id,
|
1268
|
-
serverConfig.root, serverConfig.defaultRuby, serverConfig.maxPoolSize,
|
1269
|
-
serverConfig.maxInstancesPerApp, serverConfig.poolIdleTime,
|
1270
|
-
"",
|
1271
|
-
serverConfig.analyticsLogUser,
|
1272
|
-
serverConfig.analyticsLogGroup,
|
1273
|
-
serverConfig.unionStationGatewayAddress,
|
1274
|
-
serverConfig.unionStationGatewayPort,
|
1275
|
-
serverConfig.unionStationGatewayCert,
|
1276
|
-
serverConfig.unionStationProxyAddress,
|
1277
|
-
serverConfig.prestartURLs);
|
1285
|
+
serverConfig.ctl.addTo(params);
|
1286
|
+
|
1287
|
+
agentsStarter.start(serverConfig.root, params);
|
1278
1288
|
|
1279
1289
|
// Store some relevant information in the generation directory.
|
1280
1290
|
string generationPath = agentsStarter.getGeneration()->getPath();
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2013 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -23,76 +23,104 @@
|
|
23
23
|
* THE SOFTWARE.
|
24
24
|
*/
|
25
25
|
#include <oxt/thread.hpp>
|
26
|
-
#include
|
27
|
-
#include "AgentsStarter.hpp"
|
26
|
+
#include <set>
|
28
27
|
#include <cerrno>
|
29
28
|
#include <cstring>
|
29
|
+
#include <AgentsStarter.h>
|
30
30
|
|
31
31
|
using namespace std;
|
32
32
|
using namespace boost;
|
33
33
|
using namespace oxt;
|
34
34
|
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
Passenger::
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
PSG_VariantMap *
|
37
|
+
psg_variant_map_new() {
|
38
|
+
return (PSG_VariantMap *) new Passenger::VariantMap();
|
39
|
+
}
|
40
|
+
|
41
|
+
void
|
42
|
+
psg_variant_map_set(PSG_VariantMap *m,
|
43
|
+
const char *name,
|
44
|
+
const char *value,
|
45
|
+
unsigned int value_len)
|
46
|
+
{
|
47
|
+
Passenger::VariantMap *vm = (Passenger::VariantMap *) m;
|
48
|
+
vm->set(name, string(value, value_len));
|
49
|
+
}
|
50
|
+
|
51
|
+
void
|
52
|
+
psg_variant_map_set2(PSG_VariantMap *m,
|
53
|
+
const char *name,
|
54
|
+
unsigned int name_len,
|
55
|
+
const char *value,
|
56
|
+
unsigned int value_len)
|
57
|
+
{
|
58
|
+
Passenger::VariantMap *vm = (Passenger::VariantMap *) m;
|
59
|
+
vm->set(string(name, name_len), string(value, value_len));
|
60
|
+
}
|
61
|
+
|
62
|
+
void
|
63
|
+
psg_variant_map_set_int(PSG_VariantMap *m,
|
64
|
+
const char *name,
|
65
|
+
int value)
|
66
|
+
{
|
67
|
+
Passenger::VariantMap *vm = (Passenger::VariantMap *) m;
|
68
|
+
vm->setInt(name, value);
|
69
|
+
}
|
70
|
+
|
71
|
+
void
|
72
|
+
psg_variant_map_set_bool(PSG_VariantMap *m,
|
73
|
+
const char *name,
|
74
|
+
int value)
|
75
|
+
{
|
76
|
+
Passenger::VariantMap *vm = (Passenger::VariantMap *) m;
|
77
|
+
vm->setBool(name, value);
|
78
|
+
}
|
79
|
+
|
80
|
+
void
|
81
|
+
psg_variant_map_set_strset(PSG_VariantMap *m,
|
82
|
+
const char *name,
|
83
|
+
const char **strs,
|
84
|
+
unsigned int count)
|
85
|
+
{
|
86
|
+
Passenger::VariantMap *vm = (Passenger::VariantMap *) m;
|
87
|
+
std::set<string> the_set;
|
88
|
+
|
89
|
+
for (unsigned int i = 0; i < count; i++) {
|
90
|
+
the_set.insert(strs[i]);
|
43
91
|
}
|
44
|
-
|
92
|
+
vm->setStrSet(name, the_set);
|
93
|
+
}
|
94
|
+
|
95
|
+
void
|
96
|
+
psg_variant_map_free(PSG_VariantMap *m) {
|
97
|
+
delete (Passenger::VariantMap *) m;
|
98
|
+
}
|
99
|
+
|
100
|
+
|
101
|
+
PSG_AgentsStarter *
|
102
|
+
psg_agents_starter_new(PSG_AgentsStarterType type, char **error_message) {
|
103
|
+
return (PSG_AgentsStarter *) new Passenger::AgentsStarter(type);
|
45
104
|
}
|
46
105
|
|
47
106
|
int
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
const char *passengerRoot,
|
55
|
-
const char *defaultRubyCommand, unsigned int maxPoolSize,
|
56
|
-
unsigned int maxInstancesPerApp,
|
57
|
-
unsigned int poolIdleTime,
|
58
|
-
const char *analyticsServer,
|
59
|
-
const char *analyticsLogUser,
|
60
|
-
const char *analyticsLogGroup,
|
61
|
-
const char *unionStationGatewayAddress,
|
62
|
-
unsigned short unionStationGatewayPort,
|
63
|
-
const char *unionStationGatewayCert,
|
64
|
-
const char *unionStationProxyAddress,
|
65
|
-
const char **prestartURLs, unsigned int prestartURLsCount,
|
66
|
-
const AfterForkCallback afterFork,
|
67
|
-
void *callbackArgument,
|
68
|
-
char **errorMessage)
|
107
|
+
psg_agents_starter_start(PSG_AgentsStarter *as,
|
108
|
+
const char *passengerRoot,
|
109
|
+
PSG_VariantMap *extraParams,
|
110
|
+
const PSG_AfterForkCallback afterFork,
|
111
|
+
void *callbackArgument,
|
112
|
+
char **errorMessage)
|
69
113
|
{
|
70
114
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
71
115
|
this_thread::disable_syscall_interruption dsi;
|
72
116
|
try {
|
73
117
|
function<void ()> afterForkFunctionObject;
|
74
|
-
set<string> setOfprestartURLs;
|
75
|
-
unsigned int i;
|
76
118
|
|
77
119
|
if (afterFork != NULL) {
|
78
120
|
afterForkFunctionObject = boost::bind(afterFork, callbackArgument);
|
79
121
|
}
|
80
|
-
|
81
|
-
|
82
|
-
}
|
83
|
-
agentsStarter->start(logLevel, debugLogFile,
|
84
|
-
webServerPid, tempDir, userSwitching,
|
85
|
-
defaultUser, defaultGroup,
|
86
|
-
webServerWorkerUid, webServerWorkerGid,
|
87
|
-
passengerRoot, defaultRubyCommand,
|
88
|
-
maxPoolSize, maxInstancesPerApp, poolIdleTime,
|
89
|
-
analyticsServer,
|
90
|
-
analyticsLogUser, analyticsLogGroup,
|
91
|
-
unionStationGatewayAddress,
|
92
|
-
unionStationGatewayPort,
|
93
|
-
unionStationGatewayCert,
|
94
|
-
unionStationProxyAddress,
|
95
|
-
setOfprestartURLs,
|
122
|
+
agentsStarter->start(passengerRoot,
|
123
|
+
*((Passenger::VariantMap *) extraParams),
|
96
124
|
afterForkFunctionObject);
|
97
125
|
return 1;
|
98
126
|
} catch (const Passenger::SystemException &e) {
|
@@ -107,7 +135,7 @@ agents_starter_start(AgentsStarter *as,
|
|
107
135
|
}
|
108
136
|
|
109
137
|
const char *
|
110
|
-
|
138
|
+
psg_agents_starter_get_request_socket_filename(PSG_AgentsStarter *as, unsigned int *size) {
|
111
139
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
112
140
|
if (size != NULL) {
|
113
141
|
*size = agentsStarter->getRequestSocketFilename().size();
|
@@ -116,7 +144,7 @@ agents_starter_get_request_socket_filename(AgentsStarter *as, unsigned int *size
|
|
116
144
|
}
|
117
145
|
|
118
146
|
const char *
|
119
|
-
|
147
|
+
psg_agents_starter_get_request_socket_password(PSG_AgentsStarter *as, unsigned int *size) {
|
120
148
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
121
149
|
if (size != NULL) {
|
122
150
|
*size = agentsStarter->getRequestSocketPassword().size();
|
@@ -125,31 +153,31 @@ agents_starter_get_request_socket_password(AgentsStarter *as, unsigned int *size
|
|
125
153
|
}
|
126
154
|
|
127
155
|
const char *
|
128
|
-
|
156
|
+
psg_agents_starter_get_server_instance_dir(PSG_AgentsStarter *as) {
|
129
157
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
130
158
|
return agentsStarter->getServerInstanceDir()->getPath().c_str();
|
131
159
|
}
|
132
160
|
|
133
161
|
const char *
|
134
|
-
|
162
|
+
psg_agents_starter_get_generation_dir(PSG_AgentsStarter *as) {
|
135
163
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
136
164
|
return agentsStarter->getGeneration()->getPath().c_str();
|
137
165
|
}
|
138
166
|
|
139
167
|
pid_t
|
140
|
-
|
168
|
+
psg_agents_starter_get_pid(PSG_AgentsStarter *as) {
|
141
169
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
142
170
|
return agentsStarter->getPid();
|
143
171
|
}
|
144
172
|
|
145
173
|
void
|
146
|
-
|
174
|
+
psg_agents_starter_detach(PSG_AgentsStarter *as) {
|
147
175
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
148
176
|
agentsStarter->detach();
|
149
177
|
}
|
150
178
|
|
151
179
|
void
|
152
|
-
|
180
|
+
psg_agents_starter_free(PSG_AgentsStarter *as) {
|
153
181
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
154
182
|
delete agentsStarter;
|
155
183
|
}
|
data/ext/common/AgentsStarter.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2013 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -22,10 +22,9 @@
|
|
22
22
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
23
|
* THE SOFTWARE.
|
24
24
|
*/
|
25
|
+
#ifndef _PASSENGER_AGENTS_STARTER_HPP_
|
26
|
+
#define _PASSENGER_AGENTS_STARTER_HPP_
|
25
27
|
|
26
|
-
/* C wrappers for Passenger::AgentsStarter. */
|
27
|
-
#ifndef _PASSENGER_AGENTS_STARTER_H_
|
28
|
-
#define _PASSENGER_AGENTS_STARTER_H_
|
29
28
|
|
30
29
|
#include <sys/types.h>
|
31
30
|
#include <unistd.h>
|
@@ -34,49 +33,578 @@
|
|
34
33
|
extern "C" {
|
35
34
|
#endif
|
36
35
|
|
37
|
-
|
38
|
-
typedef void AgentsStarter;
|
39
|
-
|
40
36
|
typedef enum {
|
41
37
|
AS_APACHE,
|
42
38
|
AS_NGINX
|
43
|
-
}
|
44
|
-
|
45
|
-
typedef void
|
46
|
-
|
47
|
-
|
48
|
-
int agents_starter_start(AgentsStarter *as,
|
49
|
-
int logLevel, const char *debugLogFile,
|
50
|
-
pid_t webServerPid,
|
51
|
-
const char *tempDir, int userSwitching,
|
52
|
-
const char *defaultUser, const char *defaultGroup,
|
53
|
-
uid_t webServerWorkerUid, gid_t webServerWorkerGid,
|
54
|
-
const char *passengerRoot,
|
55
|
-
const char *defaultRubyCommand, unsigned int maxPoolSize,
|
56
|
-
unsigned int maxInstancesPerApp,
|
57
|
-
unsigned int poolIdleTime,
|
58
|
-
const char *analyticsServer,
|
59
|
-
const char *analyticsLogUser,
|
60
|
-
const char *analyticsLogGroup,
|
61
|
-
const char *unionStationGatewayAddress,
|
62
|
-
unsigned short unionStationGatewayPort,
|
63
|
-
const char *unionStationGatewayCert,
|
64
|
-
const char *unionStationProxyAddress,
|
65
|
-
const char **prestartURLs, unsigned int prestartURLsCount,
|
66
|
-
const AfterForkCallback afterFork,
|
67
|
-
void *callbackArgument,
|
68
|
-
char **errorMessage);
|
69
|
-
const char *agents_starter_get_request_socket_filename(AgentsStarter *as, unsigned int *size);
|
70
|
-
const char *agents_starter_get_request_socket_password(AgentsStarter *as, unsigned int *size);
|
71
|
-
const char *agents_starter_get_server_instance_dir(AgentsStarter *as);
|
72
|
-
const char *agents_starter_get_generation_dir(AgentsStarter *as);
|
73
|
-
pid_t agents_starter_get_pid(AgentsStarter *as);
|
74
|
-
void agents_starter_detach(AgentsStarter *as);
|
75
|
-
void agents_starter_free(AgentsStarter *as);
|
39
|
+
} PSG_AgentsStarterType;
|
40
|
+
|
41
|
+
typedef void PSG_AgentsStarter;
|
42
|
+
typedef void PSG_VariantMap;
|
43
|
+
typedef void (*PSG_AfterForkCallback)(void *);
|
76
44
|
|
45
|
+
PSG_VariantMap *psg_variant_map_new();
|
46
|
+
void psg_variant_map_set(PSG_VariantMap *m,
|
47
|
+
const char *name,
|
48
|
+
const char *value,
|
49
|
+
unsigned int value_len);
|
50
|
+
void psg_variant_map_set2(PSG_VariantMap *m,
|
51
|
+
const char *name,
|
52
|
+
unsigned int name_len,
|
53
|
+
const char *value,
|
54
|
+
unsigned int value_len);
|
55
|
+
void psg_variant_map_set_int(PSG_VariantMap *m,
|
56
|
+
const char *name,
|
57
|
+
int value);
|
58
|
+
void psg_variant_map_set_bool(PSG_VariantMap *m,
|
59
|
+
const char *name,
|
60
|
+
int value);
|
61
|
+
void psg_variant_map_set_strset(PSG_VariantMap *m,
|
62
|
+
const char *name,
|
63
|
+
const char **strs,
|
64
|
+
unsigned int count);
|
65
|
+
void psg_variant_map_free(PSG_VariantMap *m);
|
66
|
+
|
67
|
+
PSG_AgentsStarter *psg_agents_starter_new(PSG_AgentsStarterType type,
|
68
|
+
char **error_message);
|
69
|
+
int psg_agents_starter_start(PSG_AgentsStarter *as,
|
70
|
+
const char *passengerRoot,
|
71
|
+
PSG_VariantMap *params,
|
72
|
+
const PSG_AfterForkCallback afterFork,
|
73
|
+
void *callbackArgument,
|
74
|
+
char **errorMessage);
|
75
|
+
const char *psg_agents_starter_get_request_socket_filename(PSG_AgentsStarter *as, unsigned int *size);
|
76
|
+
const char *psg_agents_starter_get_request_socket_password(PSG_AgentsStarter *as, unsigned int *size);
|
77
|
+
const char *psg_agents_starter_get_server_instance_dir(PSG_AgentsStarter *as);
|
78
|
+
const char *psg_agents_starter_get_generation_dir(PSG_AgentsStarter *as);
|
79
|
+
pid_t psg_agents_starter_get_pid(PSG_AgentsStarter *as);
|
80
|
+
void psg_agents_starter_detach(PSG_AgentsStarter *as);
|
81
|
+
void psg_agents_starter_free(PSG_AgentsStarter *as);
|
77
82
|
|
78
83
|
#ifdef __cplusplus
|
79
|
-
}
|
84
|
+
} /* extern "C" */
|
80
85
|
#endif
|
81
86
|
|
82
|
-
|
87
|
+
|
88
|
+
#ifdef __cplusplus
|
89
|
+
|
90
|
+
#include <boost/function.hpp>
|
91
|
+
#include <oxt/system_calls.hpp>
|
92
|
+
#include <oxt/backtrace.hpp>
|
93
|
+
#include <string>
|
94
|
+
#include <vector>
|
95
|
+
#include <set>
|
96
|
+
|
97
|
+
#include <signal.h>
|
98
|
+
|
99
|
+
#include <Constants.h>
|
100
|
+
#include <FileDescriptor.h>
|
101
|
+
#include <MessageClient.h>
|
102
|
+
#include <ServerInstanceDir.h>
|
103
|
+
#include <Exceptions.h>
|
104
|
+
#include <ResourceLocator.h>
|
105
|
+
#include <Logging.h>
|
106
|
+
#include <Utils.h>
|
107
|
+
#include <Utils/IOUtils.h>
|
108
|
+
#include <Utils/MessageIO.h>
|
109
|
+
#include <Utils/Timer.h>
|
110
|
+
#include <Utils/ScopeGuard.h>
|
111
|
+
#include <Utils/VariantMap.h>
|
112
|
+
|
113
|
+
namespace Passenger {
|
114
|
+
|
115
|
+
using namespace std;
|
116
|
+
using namespace boost;
|
117
|
+
using namespace oxt;
|
118
|
+
|
119
|
+
/**
|
120
|
+
* Utility class for starting various Phusion Passenger agents through the watchdog.
|
121
|
+
*/
|
122
|
+
class AgentsStarter {
|
123
|
+
private:
|
124
|
+
PSG_AgentsStarterType type;
|
125
|
+
|
126
|
+
/** The watchdog's PID. Equals 0 if the watchdog hasn't been started yet
|
127
|
+
* or if detach() is called. */
|
128
|
+
pid_t pid;
|
129
|
+
|
130
|
+
/******* Information about the started services. Only valid when pid != 0. *******/
|
131
|
+
|
132
|
+
/** The watchdog's feedback file descriptor. */
|
133
|
+
FileDescriptor feedbackFd;
|
134
|
+
|
135
|
+
/** The helper agent's request socket filename and its password. This socket
|
136
|
+
* is for serving SCGI requests. */
|
137
|
+
string requestSocketFilename;
|
138
|
+
string requestSocketPassword;
|
139
|
+
|
140
|
+
/** The socket on which the helper agent listens for administration commands,
|
141
|
+
* and the corresponding password for the "web_server" account, which has the
|
142
|
+
* authorization to shutdown the helper agent.
|
143
|
+
*/
|
144
|
+
string helperAgentAdminSocketAddress;
|
145
|
+
string helperAgentExitPassword;
|
146
|
+
|
147
|
+
/** The logging agent's socket address and its password. */
|
148
|
+
string loggingSocketAddress;
|
149
|
+
string loggingSocketPassword;
|
150
|
+
|
151
|
+
/** The server instance dir and generation dir of the agents. */
|
152
|
+
ServerInstanceDirPtr serverInstanceDir;
|
153
|
+
/** The generation dir of the agents. */
|
154
|
+
ServerInstanceDir::GenerationPtr generation;
|
155
|
+
|
156
|
+
/**
|
157
|
+
* Safely dup2() the given file descriptor to 3 (FEEDBACK_FD).
|
158
|
+
*/
|
159
|
+
void installFeedbackFd(const FileDescriptor &fd) {
|
160
|
+
if (fd != FEEDBACK_FD && syscalls::dup2(fd, FEEDBACK_FD) == -1) {
|
161
|
+
int e = errno;
|
162
|
+
try {
|
163
|
+
writeArrayMessage(fd,
|
164
|
+
"system error",
|
165
|
+
"dup2() failed",
|
166
|
+
toString(e).c_str(),
|
167
|
+
NULL);
|
168
|
+
_exit(1);
|
169
|
+
} catch (...) {
|
170
|
+
fprintf(stderr, "Passenger AgentsStarter: dup2() failed: %s (%d)\n",
|
171
|
+
strerror(e), e);
|
172
|
+
fflush(stderr);
|
173
|
+
_exit(1);
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
/**
|
179
|
+
* Call this if the watchdog seems to have crashed. This function will try
|
180
|
+
* to determine whether the watchdog is still running, whether it crashed
|
181
|
+
* with a signal, etc. If it has detected that the watchdog is no longer running
|
182
|
+
* then it will set `pid` to -1.
|
183
|
+
*/
|
184
|
+
void inspectWatchdogCrashReason(pid_t &pid) {
|
185
|
+
this_thread::disable_interruption di;
|
186
|
+
this_thread::disable_syscall_interruption dsi;
|
187
|
+
int ret, status;
|
188
|
+
|
189
|
+
/* Upon noticing that something went wrong, the watchdog
|
190
|
+
* or its subprocesses might still be writing out an error
|
191
|
+
* report, so we wait a while before killing the watchdog.
|
192
|
+
*/
|
193
|
+
ret = timedWaitPid(pid, &status, 5000);
|
194
|
+
if (ret == 0) {
|
195
|
+
/* Looks like the watchdog didn't crash and is still running. */
|
196
|
+
throw RuntimeException(
|
197
|
+
"Unable to start the Phusion Passenger watchdog: "
|
198
|
+
"it froze during startup and reported an unknown error");
|
199
|
+
} else if (ret != -1 && WIFSIGNALED(status)) {
|
200
|
+
/* Looks like a crash which caused a signal. */
|
201
|
+
pid = -1;
|
202
|
+
throw RuntimeException(
|
203
|
+
"Unable to start the Phusion Passenger watchdog: "
|
204
|
+
"it seems to have been killed with signal " +
|
205
|
+
getSignalName(WTERMSIG(status)) + " during startup");
|
206
|
+
} else if (ret == -1) {
|
207
|
+
/* Looks like it exited for a different reason and has no exit code. */
|
208
|
+
pid = -1;
|
209
|
+
throw RuntimeException(
|
210
|
+
"Unable to start the Phusion Passenger watchdog: "
|
211
|
+
"it seems to have crashed during startup for an unknown reason");
|
212
|
+
} else {
|
213
|
+
/* Looks like it exited for a different reason, but has an exit code. */
|
214
|
+
pid = -1;
|
215
|
+
throw RuntimeException(
|
216
|
+
"Unable to start the Phusion Passenger watchdog: "
|
217
|
+
"it seems to have crashed during startup for an unknown reason, "
|
218
|
+
"with exit code " + toString(WEXITSTATUS(status)));
|
219
|
+
}
|
220
|
+
}
|
221
|
+
|
222
|
+
static void killProcessGroupAndWait(pid_t *pid, unsigned long long timeout = 0) {
|
223
|
+
if (*pid != -1 && (timeout == 0 || timedWaitPid(*pid, NULL, timeout) <= 0)) {
|
224
|
+
this_thread::disable_syscall_interruption dsi;
|
225
|
+
syscalls::killpg(*pid, SIGKILL);
|
226
|
+
syscalls::waitpid(*pid, NULL, 0);
|
227
|
+
*pid = -1;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
/**
|
232
|
+
* Behaves like `waitpid(pid, status, WNOHANG)`, but waits at most
|
233
|
+
* `timeout` miliseconds for the process to exit.
|
234
|
+
*/
|
235
|
+
static int timedWaitPid(pid_t pid, int *status, unsigned long long timeout) {
|
236
|
+
Timer timer;
|
237
|
+
int ret;
|
238
|
+
|
239
|
+
do {
|
240
|
+
ret = syscalls::waitpid(pid, status, WNOHANG);
|
241
|
+
if (ret > 0 || ret == -1) {
|
242
|
+
return ret;
|
243
|
+
} else {
|
244
|
+
syscalls::usleep(10000);
|
245
|
+
}
|
246
|
+
} while (timer.elapsed() < timeout);
|
247
|
+
return 0; // timed out
|
248
|
+
}
|
249
|
+
|
250
|
+
/**
|
251
|
+
* Gracefully shutdown an agent process by sending an exit command to its socket.
|
252
|
+
* Returns whether the agent has successfully processed the exit command.
|
253
|
+
* Any exceptions are caught and will cause false to be returned.
|
254
|
+
*/
|
255
|
+
bool gracefullyShutdownAgent(const string &address, const string &username,
|
256
|
+
const string &password)
|
257
|
+
{
|
258
|
+
try {
|
259
|
+
MessageClient client;
|
260
|
+
vector<string> args;
|
261
|
+
|
262
|
+
client.connect(address, username, password);
|
263
|
+
client.write("exit", NULL);
|
264
|
+
return client.read(args) && args[0] == "Passed security" &&
|
265
|
+
client.read(args) && args[0] == "exit command received";
|
266
|
+
} catch (const SystemException &) {
|
267
|
+
} catch (const IOException &) {
|
268
|
+
} catch (const SecurityException &) {
|
269
|
+
}
|
270
|
+
return false;
|
271
|
+
}
|
272
|
+
|
273
|
+
string findUnionStationGatewayCert(const ResourceLocator &locator,
|
274
|
+
const VariantMap ¶ms) const
|
275
|
+
{
|
276
|
+
string value = params.get("union_station_gateway_cert", false);
|
277
|
+
if (value.empty()) {
|
278
|
+
return locator.getResourcesDir() + "/union_station_gateway.crt";
|
279
|
+
} else {
|
280
|
+
return value;
|
281
|
+
}
|
282
|
+
}
|
283
|
+
|
284
|
+
public:
|
285
|
+
/**
|
286
|
+
* Construct a AgentsStarter object. The watchdog and the agents
|
287
|
+
* aren't started yet until you call start().
|
288
|
+
*
|
289
|
+
* @param type Whether one wants to start the Apache or the Nginx helper agent.
|
290
|
+
*/
|
291
|
+
AgentsStarter(PSG_AgentsStarterType type) {
|
292
|
+
this->type = type;
|
293
|
+
pid = 0;
|
294
|
+
}
|
295
|
+
|
296
|
+
~AgentsStarter() {
|
297
|
+
if (pid != 0) {
|
298
|
+
this_thread::disable_syscall_interruption dsi;
|
299
|
+
bool cleanShutdown = gracefullyShutdownAgent(helperAgentAdminSocketAddress,
|
300
|
+
"_web_server", helperAgentExitPassword);
|
301
|
+
cleanShutdown = cleanShutdown &&
|
302
|
+
gracefullyShutdownAgent(loggingSocketAddress,
|
303
|
+
"logging", loggingSocketPassword);
|
304
|
+
|
305
|
+
/* Send a message down the feedback fd to tell the watchdog
|
306
|
+
* Whether this is a clean shutdown. Closing the fd without
|
307
|
+
* sending anything also indicates an unclean shutdown,
|
308
|
+
* but we send a byte anyway in case there are other processes
|
309
|
+
* who have the fd open.
|
310
|
+
*/
|
311
|
+
if (cleanShutdown) {
|
312
|
+
syscalls::write(feedbackFd, "c", 1);
|
313
|
+
} else {
|
314
|
+
syscalls::write(feedbackFd, "u", 1);
|
315
|
+
}
|
316
|
+
|
317
|
+
/* If we failed to send an exit command to one of the agents then we have
|
318
|
+
* to forcefully kill all agents now because otherwise one of them might
|
319
|
+
* never exit. We do this by closing the feedback fd without sending a
|
320
|
+
* random byte, to indicate that this is an abnormal shutdown. The watchdog
|
321
|
+
* will then kill all agents.
|
322
|
+
*/
|
323
|
+
|
324
|
+
feedbackFd.close();
|
325
|
+
syscalls::waitpid(pid, NULL, 0);
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
/**
|
330
|
+
* Returns the type as was passed to the constructor.
|
331
|
+
*/
|
332
|
+
PSG_AgentsStarterType getType() const {
|
333
|
+
return type;
|
334
|
+
}
|
335
|
+
|
336
|
+
/**
|
337
|
+
* Returns the watchdog's PID. Equals 0 if the watchdog hasn't been started yet
|
338
|
+
* or if detach() is called.
|
339
|
+
*/
|
340
|
+
pid_t getPid() const {
|
341
|
+
return pid;
|
342
|
+
}
|
343
|
+
|
344
|
+
// The 'const string &' here is on purpose. The C getter functions
|
345
|
+
// return the string pointer directly.
|
346
|
+
const string &getRequestSocketFilename() const {
|
347
|
+
return requestSocketFilename;
|
348
|
+
}
|
349
|
+
|
350
|
+
const string &getRequestSocketPassword() const {
|
351
|
+
return requestSocketPassword;
|
352
|
+
}
|
353
|
+
|
354
|
+
string getHelperAgentAdminSocketFilename() const {
|
355
|
+
return parseUnixSocketAddress(helperAgentAdminSocketAddress);
|
356
|
+
}
|
357
|
+
|
358
|
+
string getHelperAgentExitPassword() const {
|
359
|
+
return helperAgentExitPassword;
|
360
|
+
}
|
361
|
+
|
362
|
+
string getLoggingSocketAddress() const {
|
363
|
+
return loggingSocketAddress;
|
364
|
+
}
|
365
|
+
|
366
|
+
string getLoggingSocketPassword() const {
|
367
|
+
return loggingSocketPassword;
|
368
|
+
}
|
369
|
+
|
370
|
+
ServerInstanceDirPtr getServerInstanceDir() const {
|
371
|
+
return serverInstanceDir;
|
372
|
+
}
|
373
|
+
|
374
|
+
ServerInstanceDir::GenerationPtr getGeneration() const {
|
375
|
+
return generation;
|
376
|
+
}
|
377
|
+
|
378
|
+
/**
|
379
|
+
* Start the agents through the watchdog.
|
380
|
+
*
|
381
|
+
* @throws SystemException Something went wrong.
|
382
|
+
* @throws IOException Something went wrong while communicating with one
|
383
|
+
* of the agents during its initialization phase.
|
384
|
+
* @throws RuntimeException Something went wrong.
|
385
|
+
*/
|
386
|
+
void start(const string &passengerRoot,
|
387
|
+
const VariantMap &extraParams = VariantMap(),
|
388
|
+
const function<void ()> &afterFork = function<void ()>())
|
389
|
+
{
|
390
|
+
TRACE_POINT();
|
391
|
+
this_thread::disable_interruption di;
|
392
|
+
this_thread::disable_syscall_interruption dsi;
|
393
|
+
ResourceLocator locator(passengerRoot);
|
394
|
+
string realUnionStationGatewayCert = findUnionStationGatewayCert(locator, extraParams);
|
395
|
+
string watchdogFilename = locator.getAgentsDir() + "/PassengerWatchdog";
|
396
|
+
SocketPair fds;
|
397
|
+
int e;
|
398
|
+
pid_t pid;
|
399
|
+
|
400
|
+
VariantMap params;
|
401
|
+
params
|
402
|
+
.set ("web_server_type", type == AS_APACHE ? "apache" : "nginx")
|
403
|
+
.setPid ("web_server_pid", getpid())
|
404
|
+
.set ("passenger_root", passengerRoot)
|
405
|
+
.setInt ("log_level", getLogLevel())
|
406
|
+
.set ("temp_dir", getSystemTempDir());
|
407
|
+
extraParams.addTo(params);
|
408
|
+
|
409
|
+
// .setUid ("web_server_worker_uid", webServerWorkerUid)
|
410
|
+
// .setGid ("web_server_worker_gid", webServerWorkerGid)
|
411
|
+
// .set ("debug_log_file", debugLogFile)
|
412
|
+
// .set ("temp_dir", tempDir.empty() ? getSystemTempDir() : tempDir)
|
413
|
+
// .setBool("user_switching", userSwitching)
|
414
|
+
// .set ("default_user", defaultUser)
|
415
|
+
// .set ("default_group", defaultGroup)
|
416
|
+
// .set ("default_ruby", defaultRubyCommand)
|
417
|
+
// .setInt ("max_pool_size", maxPoolSize)
|
418
|
+
// .setInt ("max_instances_per_app", maxInstancesPerApp)
|
419
|
+
/*
|
420
|
+
.setInt ("pool_idle_time", poolIdleTime)
|
421
|
+
.set ("analytics_server", analyticsServer)
|
422
|
+
.set ("analytics_log_user", analyticsLogUser)
|
423
|
+
.set ("analytics_log_group", analyticsLogGroup)
|
424
|
+
.set ("union_station_gateway_address", unionStationGatewayAddress)
|
425
|
+
.setInt ("union_station_gateway_port", unionStationGatewayPort)
|
426
|
+
.set ("union_station_gateway_cert", realUnionStationGatewayCert)
|
427
|
+
.set ("union_station_proxy_address", unionStationProxyAddress)
|
428
|
+
.set ("prestart_urls", serializePrestartURLs(prestartURLs));
|
429
|
+
*/
|
430
|
+
|
431
|
+
fds = createUnixSocketPair();
|
432
|
+
pid = syscalls::fork();
|
433
|
+
if (pid == 0) {
|
434
|
+
// Child
|
435
|
+
|
436
|
+
/* Become the session leader so that Apache can't kill the
|
437
|
+
* watchdog with killpg() during shutdown, so that a
|
438
|
+
* Ctrl-C only affects the web server, and so that
|
439
|
+
* we can kill all of our subprocesses in a single killpg().
|
440
|
+
*/
|
441
|
+
setsid();
|
442
|
+
|
443
|
+
// Make sure the feedback fd is 3 and close all file descriptors
|
444
|
+
// except stdin, stdout, stderr and 3.
|
445
|
+
syscalls::close(fds[0]);
|
446
|
+
installFeedbackFd(fds[1]);
|
447
|
+
closeAllFileDescriptors(FEEDBACK_FD);
|
448
|
+
|
449
|
+
/* We don't know how the web server or the environment affect
|
450
|
+
* signal handlers and the signal mask, so reset this stuff
|
451
|
+
* just in case.
|
452
|
+
*/
|
453
|
+
resetSignalHandlersAndMask();
|
454
|
+
|
455
|
+
if (afterFork) {
|
456
|
+
afterFork();
|
457
|
+
}
|
458
|
+
|
459
|
+
execl(watchdogFilename.c_str(), "PassengerWatchdog", (char *) 0);
|
460
|
+
e = errno;
|
461
|
+
try {
|
462
|
+
writeArrayMessage(FEEDBACK_FD,
|
463
|
+
"exec error",
|
464
|
+
toString(e).c_str(),
|
465
|
+
NULL);
|
466
|
+
_exit(1);
|
467
|
+
} catch (...) {
|
468
|
+
fprintf(stderr, "Passenger AgentsStarter: could not execute %s: %s (%d)\n",
|
469
|
+
watchdogFilename.c_str(), strerror(e), e);
|
470
|
+
fflush(stderr);
|
471
|
+
_exit(1);
|
472
|
+
}
|
473
|
+
} else if (pid == -1) {
|
474
|
+
// Error
|
475
|
+
e = errno;
|
476
|
+
throw SystemException("Cannot fork a new process", e);
|
477
|
+
} else {
|
478
|
+
// Parent
|
479
|
+
UPDATE_TRACE_POINT();
|
480
|
+
FileDescriptor feedbackFd = fds[0];
|
481
|
+
vector<string> args;
|
482
|
+
bool result;
|
483
|
+
|
484
|
+
ScopeGuard guard(boost::bind(&AgentsStarter::killProcessGroupAndWait, &pid, 0));
|
485
|
+
fds[1].close();
|
486
|
+
|
487
|
+
|
488
|
+
/****** Send arguments to watchdog through the feedback channel ******/
|
489
|
+
|
490
|
+
UPDATE_TRACE_POINT();
|
491
|
+
/* Here we don't care about EPIPE and ECONNRESET errors. The watchdog
|
492
|
+
* could have sent an error message over the feedback fd without
|
493
|
+
* reading the arguments. We'll notice that later.
|
494
|
+
*/
|
495
|
+
try {
|
496
|
+
params.writeToFd(feedbackFd);
|
497
|
+
} catch (const SystemException &e) {
|
498
|
+
if (e.code() != EPIPE && e.code() != ECONNRESET) {
|
499
|
+
inspectWatchdogCrashReason(pid);
|
500
|
+
}
|
501
|
+
}
|
502
|
+
|
503
|
+
|
504
|
+
/****** Read agents information report ******/
|
505
|
+
|
506
|
+
this_thread::restore_interruption ri(di);
|
507
|
+
this_thread::restore_syscall_interruption rsi(dsi);
|
508
|
+
UPDATE_TRACE_POINT();
|
509
|
+
|
510
|
+
try {
|
511
|
+
result = readArrayMessage(feedbackFd, args);
|
512
|
+
} catch (const SystemException &ex) {
|
513
|
+
if (ex.code() == ECONNRESET) {
|
514
|
+
inspectWatchdogCrashReason(pid);
|
515
|
+
} else {
|
516
|
+
killProcessGroupAndWait(&pid, 5000);
|
517
|
+
guard.clear();
|
518
|
+
throw SystemException("Unable to start the Phusion Passenger watchdog: "
|
519
|
+
"unable to read its startup information report",
|
520
|
+
ex.code());
|
521
|
+
}
|
522
|
+
}
|
523
|
+
if (!result) {
|
524
|
+
UPDATE_TRACE_POINT();
|
525
|
+
inspectWatchdogCrashReason(pid);
|
526
|
+
}
|
527
|
+
|
528
|
+
if (args[0] == "Agents information") {
|
529
|
+
if ((args.size() - 1) % 2 != 0) {
|
530
|
+
throw RuntimeException("Unable to start the Phusion Passenger watchdog "
|
531
|
+
"because it sent an invalid startup information report (the number "
|
532
|
+
"of items is not an even number)");
|
533
|
+
}
|
534
|
+
|
535
|
+
VariantMap info;
|
536
|
+
for (unsigned i = 1; i < args.size(); i += 2) {
|
537
|
+
const string &key = args[i];
|
538
|
+
const string &value = args[i + 1];
|
539
|
+
info.set(key, value);
|
540
|
+
}
|
541
|
+
|
542
|
+
this->pid = pid;
|
543
|
+
this->feedbackFd = feedbackFd;
|
544
|
+
requestSocketFilename = info.get("request_socket_filename");
|
545
|
+
requestSocketPassword = info.get("request_socket_password");
|
546
|
+
helperAgentAdminSocketAddress = info.get("helper_agent_admin_socket_address");
|
547
|
+
helperAgentExitPassword = info.get("helper_agent_exit_password");
|
548
|
+
serverInstanceDir = make_shared<ServerInstanceDir>(info.get("server_instance_dir"), false);
|
549
|
+
generation = serverInstanceDir->getGeneration(info.getInt("generation"));
|
550
|
+
loggingSocketAddress = info.get("logging_socket_address");
|
551
|
+
loggingSocketPassword = info.get("logging_socket_password");
|
552
|
+
guard.clear();
|
553
|
+
} else if (args[0] == "Watchdog startup error") {
|
554
|
+
killProcessGroupAndWait(&pid, 5000);
|
555
|
+
guard.clear();
|
556
|
+
throw RuntimeException("Unable to start the Phusion Passenger watchdog "
|
557
|
+
"because it encountered the following error during startup: " +
|
558
|
+
args[1]);
|
559
|
+
} else if (args[0] == "system error") {
|
560
|
+
killProcessGroupAndWait(&pid, 5000);
|
561
|
+
guard.clear();
|
562
|
+
throw SystemException(args[1], atoi(args[2]));
|
563
|
+
} else if (args[0] == "exec error") {
|
564
|
+
e = atoi(args[1]);
|
565
|
+
killProcessGroupAndWait(&pid, 5000);
|
566
|
+
guard.clear();
|
567
|
+
if (e == ENOENT) {
|
568
|
+
string passengerRootConfig;
|
569
|
+
if (type == AS_APACHE) {
|
570
|
+
passengerRootConfig = "PassengerRoot";
|
571
|
+
} else {
|
572
|
+
passengerRootConfig = "passenger_root";
|
573
|
+
}
|
574
|
+
throw RuntimeException("Unable to start the Phusion Passenger watchdog "
|
575
|
+
"because its executable (" + watchdogFilename + ") does "
|
576
|
+
"not exist. This probably means that your Phusion Passenger "
|
577
|
+
"installation is broken or incomplete, or that your '" +
|
578
|
+
passengerRootConfig + "' directive is set to the wrong value. "
|
579
|
+
"Please reinstall Phusion Passenger or fix your '" +
|
580
|
+
passengerRootConfig + "' directive, whichever is applicable.");
|
581
|
+
} else {
|
582
|
+
throw SystemException("Unable to start the Phusion Passenger watchdog (" +
|
583
|
+
watchdogFilename + ")", e);
|
584
|
+
}
|
585
|
+
} else {
|
586
|
+
UPDATE_TRACE_POINT();
|
587
|
+
killProcessGroupAndWait(&pid, 5000);
|
588
|
+
guard.clear();
|
589
|
+
throw RuntimeException("One of the Passenger agents sent an unknown feedback message '" + args[0] + "'");
|
590
|
+
}
|
591
|
+
}
|
592
|
+
}
|
593
|
+
|
594
|
+
/**
|
595
|
+
* Close any file descriptors that this object has, and make it so that the destructor
|
596
|
+
* doesn't try to shut down the agents.
|
597
|
+
*
|
598
|
+
* @post getPid() == 0
|
599
|
+
*/
|
600
|
+
void detach() {
|
601
|
+
feedbackFd.close();
|
602
|
+
pid = 0;
|
603
|
+
}
|
604
|
+
};
|
605
|
+
|
606
|
+
} // namespace Passenger
|
607
|
+
|
608
|
+
#endif /* __cplusplus */
|
609
|
+
|
610
|
+
#endif /* _PASSENGER_AGENTS_STARTER_HPP_ */
|