passenger 5.0.9 → 5.0.10
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.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/CHANGELOG +15 -0
- data/CONTRIBUTORS +6 -0
- data/README.md +1 -1
- data/bin/passenger-install-apache2-module +24 -11
- data/bin/passenger-status +29 -14
- data/build/agents.rb +12 -10
- data/build/cxx_tests.rb +30 -30
- data/doc/Design and Architecture.html +1 -10
- data/doc/Design and Architecture.txt +1 -6
- data/doc/Users guide Apache.html +1 -19
- data/doc/Users guide Apache.txt +1 -1
- data/doc/Users guide Nginx.html +2 -20
- data/doc/Users guide Nginx.txt +2 -2
- data/doc/users_guide_snippets/tips.txt +0 -9
- data/ext/common/ApplicationPool2/ApiKey.h +158 -0
- data/ext/common/ApplicationPool2/BasicGroupInfo.h +81 -0
- data/ext/common/ApplicationPool2/BasicProcessInfo.h +106 -0
- data/ext/common/ApplicationPool2/Common.h +5 -44
- data/ext/common/ApplicationPool2/Context.h +94 -0
- data/ext/common/ApplicationPool2/Group.h +130 -1205
- data/ext/common/ApplicationPool2/Group/InitializationAndShutdown.cpp +190 -0
- data/ext/common/ApplicationPool2/Group/InternalUtils.cpp +329 -0
- data/ext/common/ApplicationPool2/Group/LifetimeAndBasics.cpp +103 -0
- data/ext/common/ApplicationPool2/{Pool/Debug.h → Group/Miscellaneous.cpp} +40 -38
- data/ext/common/ApplicationPool2/Group/OutOfBandWork.cpp +323 -0
- data/ext/common/ApplicationPool2/Group/ProcessListManagement.cpp +606 -0
- data/ext/common/ApplicationPool2/Group/SessionManagement.cpp +337 -0
- data/ext/common/ApplicationPool2/Group/SpawningAndRestarting.cpp +478 -0
- data/ext/common/ApplicationPool2/Group/StateInspection.cpp +197 -0
- data/ext/common/ApplicationPool2/Group/Verification.cpp +159 -0
- data/ext/common/ApplicationPool2/Implementation.cpp +19 -1401
- data/ext/common/ApplicationPool2/Options.h +5 -5
- data/ext/common/ApplicationPool2/Pool.h +260 -815
- data/ext/common/ApplicationPool2/Pool/{AnalyticsCollection.h → AnalyticsCollection.cpp} +55 -56
- data/ext/common/ApplicationPool2/Pool/{GarbageCollection.h → GarbageCollection.cpp} +49 -49
- data/ext/common/ApplicationPool2/Pool/GeneralUtils.cpp +241 -0
- data/ext/common/ApplicationPool2/Pool/GroupUtils.cpp +276 -0
- data/ext/common/ApplicationPool2/Pool/InitializationAndShutdown.cpp +145 -0
- data/ext/common/ApplicationPool2/Pool/Miscellaneous.cpp +244 -0
- data/ext/common/ApplicationPool2/Pool/ProcessUtils.cpp +330 -0
- data/ext/common/ApplicationPool2/Pool/StateInspection.cpp +299 -0
- data/ext/common/ApplicationPool2/Process.h +399 -205
- data/ext/common/ApplicationPool2/Session.h +70 -28
- data/ext/common/ApplicationPool2/Socket.h +1 -0
- data/ext/common/Constants.h +11 -3
- data/ext/common/Exceptions.h +1 -1
- data/ext/common/Logging.cpp +9 -4
- data/ext/common/Logging.h +6 -0
- data/ext/common/ServerKit/HttpServer.h +225 -215
- data/ext/common/ServerKit/Server.h +57 -57
- data/ext/common/SpawningKit/BackgroundIOCapturer.h +160 -0
- data/ext/common/SpawningKit/Config.h +107 -0
- data/ext/common/{ApplicationPool2 → SpawningKit}/DirectSpawner.h +17 -16
- data/ext/common/{ApplicationPool2 → SpawningKit}/DummySpawner.h +33 -33
- data/ext/common/{ApplicationPool2/SpawnerFactory.h → SpawningKit/Factory.h} +17 -17
- data/ext/common/{ApplicationPool2/ComponentInfo.h → SpawningKit/Options.h} +8 -21
- data/ext/common/SpawningKit/PipeWatcher.h +148 -0
- data/ext/common/{ApplicationPool2/PipeWatcher.h → SpawningKit/Result.h} +15 -33
- data/ext/common/{ApplicationPool2 → SpawningKit}/SmartSpawner.h +52 -57
- data/ext/common/{ApplicationPool2 → SpawningKit}/Spawner.h +83 -371
- data/ext/common/SpawningKit/UserSwitchingRules.h +265 -0
- data/ext/common/Utils/BufferedIO.h +24 -0
- data/ext/common/{ApplicationPool2/SpawnObject.h → Utils/ClassUtils.h} +24 -51
- data/ext/common/Utils/IOUtils.cpp +70 -0
- data/ext/common/Utils/IOUtils.h +19 -0
- data/ext/common/Utils/JsonUtils.h +113 -0
- data/ext/common/Utils/StrIntUtils.h +29 -0
- data/ext/common/Utils/json.h +1 -1
- data/ext/common/agents/ApiServerUtils.h +941 -0
- data/ext/common/agents/HelperAgent/{AdminServer.h → ApiServer.h} +163 -365
- data/ext/common/agents/HelperAgent/Main.cpp +86 -88
- data/ext/common/agents/HelperAgent/OptionParser.h +9 -10
- data/ext/common/agents/HelperAgent/RequestHandler/BufferBody.cpp +3 -0
- data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +2 -0
- data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +1 -1
- data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +2 -2
- data/ext/common/agents/LoggingAgent/ApiServer.h +279 -0
- data/ext/common/agents/LoggingAgent/Main.cpp +41 -51
- data/ext/common/agents/LoggingAgent/OptionParser.h +11 -11
- data/ext/common/agents/Watchdog/ApiServer.h +311 -0
- data/ext/common/agents/Watchdog/Main.cpp +91 -65
- data/helper-scripts/prespawn +2 -0
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/admin_tools/instance.rb +1 -1
- data/lib/phusion_passenger/common_library.rb +27 -14
- data/lib/phusion_passenger/config/{admin_command_command.rb → api_call_command.rb} +19 -16
- data/lib/phusion_passenger/config/detach_process_command.rb +6 -3
- data/lib/phusion_passenger/config/main.rb +3 -5
- data/lib/phusion_passenger/config/reopen_logs_command.rb +29 -7
- data/lib/phusion_passenger/config/restart_app_command.rb +13 -4
- data/lib/phusion_passenger/config/utils.rb +15 -8
- data/lib/phusion_passenger/constants.rb +6 -2
- data/lib/phusion_passenger/platform_info/apache.rb +4 -0
- data/lib/phusion_passenger/platform_info/apache_detector.rb +18 -3
- data/resources/templates/apache2/mpm_unknown.txt.erb +20 -0
- metadata +42 -21
- metadata.gz.asc +7 -7
- data/ext/common/ApplicationPool2/Pool/GeneralUtils.h +0 -127
- data/ext/common/ApplicationPool2/Pool/Inspection.h +0 -219
- data/ext/common/ApplicationPool2/Pool/ProcessUtils.h +0 -85
- data/ext/common/ApplicationPool2/SuperGroup.h +0 -706
- data/ext/common/agents/LoggingAgent/AdminServer.h +0 -435
- data/ext/common/agents/Watchdog/AdminServer.h +0 -432
@@ -22,13 +22,14 @@
|
|
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
|
26
|
-
#define
|
25
|
+
#ifndef _PASSENGER_SPAWNING_KIT_DUMMY_SPAWNER_H_
|
26
|
+
#define _PASSENGER_SPAWNING_KIT_DUMMY_SPAWNER_H_
|
27
27
|
|
28
|
-
#include <
|
28
|
+
#include <SpawningKit/Spawner.h>
|
29
|
+
#include <boost/atomic.hpp>
|
29
30
|
|
30
31
|
namespace Passenger {
|
31
|
-
namespace
|
32
|
+
namespace SpawningKit {
|
32
33
|
|
33
34
|
using namespace std;
|
34
35
|
using namespace boost;
|
@@ -37,43 +38,42 @@ using namespace oxt;
|
|
37
38
|
|
38
39
|
class DummySpawner: public Spawner {
|
39
40
|
private:
|
40
|
-
boost::
|
41
|
-
unsigned int count;
|
41
|
+
boost::atomic<unsigned int> count;
|
42
42
|
|
43
43
|
public:
|
44
44
|
unsigned int cleanCount;
|
45
45
|
|
46
|
-
DummySpawner(const
|
47
|
-
: Spawner(_config)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
}
|
46
|
+
DummySpawner(const ConfigPtr &_config)
|
47
|
+
: Spawner(_config),
|
48
|
+
count(1),
|
49
|
+
cleanCount(0)
|
50
|
+
{ }
|
52
51
|
|
53
|
-
virtual
|
52
|
+
virtual Result spawn(const Options &options) {
|
54
53
|
TRACE_POINT();
|
55
54
|
possiblyRaiseInternalError(options);
|
56
55
|
|
57
|
-
pid_t pid;
|
58
|
-
{
|
59
|
-
boost::lock_guard<boost::mutex> l(lock);
|
60
|
-
count++;
|
61
|
-
pid = count;
|
62
|
-
}
|
63
|
-
|
64
|
-
SocketPair adminSocket = createUnixSocketPair(__FILE__, __LINE__);
|
65
|
-
SocketList sockets;
|
66
|
-
sockets.add(pid, "main", "tcp://127.0.0.1:1234", "session", config->concurrency);
|
67
56
|
syscalls::usleep(config->spawnTime);
|
68
57
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
58
|
+
SocketPair adminSocket = createUnixSocketPair(__FILE__, __LINE__);
|
59
|
+
unsigned int number = count.fetch_add(1, boost::memory_order_relaxed);
|
60
|
+
Result result;
|
61
|
+
Json::Value socket;
|
62
|
+
|
63
|
+
socket["name"] = "main";
|
64
|
+
socket["address"] = "tcp://127.0.0.1:1234";
|
65
|
+
socket["protocol"] = "session";
|
66
|
+
socket["concurrency"] = config->concurrency;
|
67
|
+
|
68
|
+
result["type"] = "dummy";
|
69
|
+
result["pid"] = number;
|
70
|
+
result["gupid"] = "gupid-" + toString(number);
|
71
|
+
result["spawner_creation_time"] = (Json::UInt64) SystemTime::getUsec();
|
72
|
+
result["spawn_start_time"] = (Json::UInt64) SystemTime::getUsec();
|
73
|
+
result["sockets"].append(socket);
|
74
|
+
result.adminSocket = adminSocket.second;
|
75
|
+
|
76
|
+
return result;
|
77
77
|
}
|
78
78
|
|
79
79
|
virtual bool cleanable() const {
|
@@ -88,7 +88,7 @@ public:
|
|
88
88
|
typedef boost::shared_ptr<DummySpawner> DummySpawnerPtr;
|
89
89
|
|
90
90
|
|
91
|
-
} // namespace
|
91
|
+
} // namespace SpawningKit
|
92
92
|
} // namespace Passenger
|
93
93
|
|
94
|
-
#endif /*
|
94
|
+
#endif /* _PASSENGER_SPAWNING_KIT_DUMMY_SPAWNER_H_ */
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2015 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -22,26 +22,26 @@
|
|
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
|
26
|
-
#define
|
25
|
+
#ifndef _PASSENGER_SPAWNING_KIT_FACTORY_H_
|
26
|
+
#define _PASSENGER_SPAWNING_KIT_FACTORY_H_
|
27
27
|
|
28
|
-
#include <
|
29
|
-
#include <
|
30
|
-
#include <
|
31
|
-
#include <
|
28
|
+
#include <SpawningKit/Spawner.h>
|
29
|
+
#include <SpawningKit/SmartSpawner.h>
|
30
|
+
#include <SpawningKit/DirectSpawner.h>
|
31
|
+
#include <SpawningKit/DummySpawner.h>
|
32
32
|
|
33
33
|
namespace Passenger {
|
34
|
-
namespace
|
34
|
+
namespace SpawningKit {
|
35
35
|
|
36
36
|
using namespace std;
|
37
37
|
using namespace boost;
|
38
38
|
using namespace oxt;
|
39
39
|
|
40
40
|
|
41
|
-
class
|
41
|
+
class Factory {
|
42
42
|
private:
|
43
43
|
boost::mutex syncher;
|
44
|
-
|
44
|
+
ConfigPtr config;
|
45
45
|
DummySpawnerPtr dummySpawner;
|
46
46
|
|
47
47
|
SpawnerPtr tryCreateSmartSpawner(const Options &options) {
|
@@ -58,11 +58,11 @@ private:
|
|
58
58
|
}
|
59
59
|
|
60
60
|
public:
|
61
|
-
|
61
|
+
Factory(const ConfigPtr &_config)
|
62
62
|
: config(_config)
|
63
63
|
{ }
|
64
64
|
|
65
|
-
virtual ~
|
65
|
+
virtual ~Factory() { }
|
66
66
|
|
67
67
|
virtual SpawnerPtr create(const Options &options) {
|
68
68
|
if (options.spawnMethod == "smart" || options.spawnMethod == "smart-lv2") {
|
@@ -97,17 +97,17 @@ public:
|
|
97
97
|
}
|
98
98
|
|
99
99
|
/**
|
100
|
-
* All created Spawner objects share the same
|
100
|
+
* All created Spawner objects share the same Config object.
|
101
101
|
*/
|
102
|
-
const
|
102
|
+
const ConfigPtr &getConfig() const {
|
103
103
|
return config;
|
104
104
|
}
|
105
105
|
};
|
106
106
|
|
107
|
-
typedef boost::shared_ptr<
|
107
|
+
typedef boost::shared_ptr<Factory> FactoryPtr;
|
108
108
|
|
109
109
|
|
110
|
-
} // namespace
|
110
|
+
} // namespace SpawningKit
|
111
111
|
} // namespace Passenger
|
112
112
|
|
113
|
-
#endif /*
|
113
|
+
#endif /* _PASSENGER_SPAWNING_KIT_FACTORY_H_ */
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c)
|
3
|
+
* Copyright (c) 2015 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -22,32 +22,19 @@
|
|
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
|
26
|
-
#define
|
25
|
+
#ifndef _PASSENGER_SPAWNING_KIT_OPTIONS_H_
|
26
|
+
#define _PASSENGER_SPAWNING_KIT_OPTIONS_H_
|
27
27
|
|
28
|
-
#include <
|
28
|
+
#include <ApplicationPool2/Options.h>
|
29
29
|
|
30
30
|
namespace Passenger {
|
31
|
-
namespace
|
31
|
+
namespace SpawningKit {
|
32
32
|
|
33
|
-
using namespace std;
|
34
33
|
|
34
|
+
typedef ApplicationPool2::Options Options;
|
35
35
|
|
36
|
-
struct ComponentInfo {
|
37
|
-
string name;
|
38
|
-
bool isDefault;
|
39
36
|
|
40
|
-
|
41
|
-
/****************/
|
42
|
-
|
43
|
-
ComponentInfo() {
|
44
|
-
isDefault = false;
|
45
|
-
/******************/
|
46
|
-
}
|
47
|
-
};
|
48
|
-
|
49
|
-
|
50
|
-
} // namespace ApplicationPool2
|
37
|
+
} // namespace SpawningKit
|
51
38
|
} // namespace Passenger
|
52
39
|
|
53
|
-
#endif /*
|
40
|
+
#endif /* _PASSENGER_SPAWNING_KIT_OPTIONS_H_ */
|
@@ -0,0 +1,148 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2012-2015 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
|
+
#ifndef _PASSENGER_SPAwNING_KIT_PIPE_WATCHER_H_
|
26
|
+
#define _PASSENGER_SPAwNING_KIT_PIPE_WATCHER_H_
|
27
|
+
|
28
|
+
#include <boost/shared_ptr.hpp>
|
29
|
+
#include <boost/enable_shared_from_this.hpp>
|
30
|
+
#include <boost/thread.hpp>
|
31
|
+
#include <boost/function.hpp>
|
32
|
+
#include <boost/bind.hpp>
|
33
|
+
#include <boost/foreach.hpp>
|
34
|
+
#include <oxt/thread.hpp>
|
35
|
+
#include <oxt/backtrace.hpp>
|
36
|
+
#include <vector>
|
37
|
+
|
38
|
+
#include <sys/types.h>
|
39
|
+
|
40
|
+
#include <SpawningKit/Config.h>
|
41
|
+
#include <FileDescriptor.h>
|
42
|
+
#include <Constants.h>
|
43
|
+
#include <Logging.h>
|
44
|
+
#include <Utils.h>
|
45
|
+
#include <Utils/StrIntUtils.h>
|
46
|
+
|
47
|
+
namespace Passenger {
|
48
|
+
namespace SpawningKit {
|
49
|
+
|
50
|
+
using namespace boost;
|
51
|
+
|
52
|
+
|
53
|
+
/** A PipeWatcher lives until the file descriptor is closed. */
|
54
|
+
class PipeWatcher: public boost::enable_shared_from_this<PipeWatcher> {
|
55
|
+
private:
|
56
|
+
ConfigPtr config;
|
57
|
+
FileDescriptor fd;
|
58
|
+
const char *name;
|
59
|
+
pid_t pid;
|
60
|
+
bool started;
|
61
|
+
boost::mutex startSyncher;
|
62
|
+
boost::condition_variable startCond;
|
63
|
+
|
64
|
+
static void threadMain(boost::shared_ptr<PipeWatcher> self) {
|
65
|
+
TRACE_POINT();
|
66
|
+
self->threadMain();
|
67
|
+
}
|
68
|
+
|
69
|
+
void threadMain() {
|
70
|
+
TRACE_POINT();
|
71
|
+
{
|
72
|
+
boost::unique_lock<boost::mutex> lock(startSyncher);
|
73
|
+
while (!started) {
|
74
|
+
startCond.wait(lock);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
UPDATE_TRACE_POINT();
|
79
|
+
while (!this_thread::interruption_requested()) {
|
80
|
+
char buf[1024 * 8];
|
81
|
+
ssize_t ret;
|
82
|
+
|
83
|
+
UPDATE_TRACE_POINT();
|
84
|
+
ret = syscalls::read(fd, buf, sizeof(buf));
|
85
|
+
if (ret == 0) {
|
86
|
+
break;
|
87
|
+
} else if (ret == -1) {
|
88
|
+
UPDATE_TRACE_POINT();
|
89
|
+
if (errno == ECONNRESET) {
|
90
|
+
break;
|
91
|
+
} else if (errno != EAGAIN) {
|
92
|
+
int e = errno;
|
93
|
+
P_WARN("Cannot read from process " << pid << " " << name <<
|
94
|
+
": " << strerror(e) << " (errno=" << e << ")");
|
95
|
+
break;
|
96
|
+
}
|
97
|
+
} else if (ret == 1 && buf[0] == '\n') {
|
98
|
+
UPDATE_TRACE_POINT();
|
99
|
+
printAppOutput(pid, name, "", 0);
|
100
|
+
} else {
|
101
|
+
UPDATE_TRACE_POINT();
|
102
|
+
vector<StaticString> lines;
|
103
|
+
ssize_t ret2 = ret;
|
104
|
+
if (ret2 > 0 && buf[ret2 - 1] == '\n') {
|
105
|
+
ret2--;
|
106
|
+
}
|
107
|
+
split(StaticString(buf, ret2), '\n', lines);
|
108
|
+
foreach (const StaticString line, lines) {
|
109
|
+
printAppOutput(pid, name, line.data(), line.size());
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
if (config->outputHandler) {
|
114
|
+
config->outputHandler(buf, ret);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
public:
|
120
|
+
PipeWatcher(const ConfigPtr &_config, const FileDescriptor &_fd,
|
121
|
+
const char *_name, pid_t _pid)
|
122
|
+
: config(_config),
|
123
|
+
fd(_fd),
|
124
|
+
name(_name),
|
125
|
+
pid(_pid),
|
126
|
+
started(false)
|
127
|
+
{ }
|
128
|
+
|
129
|
+
void initialize() {
|
130
|
+
oxt::thread(boost::bind(threadMain, shared_from_this()),
|
131
|
+
"PipeWatcher: PID " + toString(pid) + " " + name + ", fd " + toString(fd),
|
132
|
+
POOL_HELPER_THREAD_STACK_SIZE);
|
133
|
+
}
|
134
|
+
|
135
|
+
void start() {
|
136
|
+
boost::lock_guard<boost::mutex> lock(startSyncher);
|
137
|
+
started = true;
|
138
|
+
startCond.notify_all();
|
139
|
+
}
|
140
|
+
};
|
141
|
+
|
142
|
+
typedef boost::shared_ptr<PipeWatcher> PipeWatcherPtr;
|
143
|
+
|
144
|
+
|
145
|
+
} // namespace SpawningKit
|
146
|
+
} // namespace Passenger
|
147
|
+
|
148
|
+
#endif /* _PASSENGER_SPAwNING_KIT_PIPE_WATCHER_H_ */
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c)
|
3
|
+
* Copyright (c) 2014-2015 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -22,46 +22,28 @@
|
|
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
|
26
|
-
#define
|
25
|
+
#ifndef _PASSENGER_SPAWNING_KIT_RESULT_H_
|
26
|
+
#define _PASSENGER_SPAWNING_KIT_RESULT_H_
|
27
27
|
|
28
|
-
#include <boost/shared_ptr.hpp>
|
29
|
-
#include <boost/enable_shared_from_this.hpp>
|
30
|
-
#include <boost/thread.hpp>
|
31
|
-
#include <boost/function.hpp>
|
32
|
-
#include <sys/types.h>
|
33
28
|
#include <FileDescriptor.h>
|
29
|
+
#include <Utils/json.h>
|
34
30
|
|
35
31
|
namespace Passenger {
|
36
|
-
namespace
|
32
|
+
namespace SpawningKit {
|
37
33
|
|
38
|
-
using namespace boost;
|
39
34
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
FileDescriptor
|
48
|
-
const char *name;
|
49
|
-
pid_t pid;
|
50
|
-
bool started;
|
51
|
-
boost::mutex startSyncher;
|
52
|
-
boost::condition_variable startCond;
|
53
|
-
|
54
|
-
PipeWatcher(const FileDescriptor &_fd, const char *name, pid_t pid);
|
55
|
-
void initialize();
|
56
|
-
void start();
|
57
|
-
static void threadMain(boost::shared_ptr<PipeWatcher> self);
|
58
|
-
void threadMain();
|
35
|
+
/**
|
36
|
+
* Represents the result of a spawning operation. It is a JSON document
|
37
|
+
* containing information about the spawned process, such as its PID,
|
38
|
+
* GUPID, etc. In addition, it contains two file descriptors.
|
39
|
+
*/
|
40
|
+
struct Result: public Json::Value {
|
41
|
+
FileDescriptor adminSocket;
|
42
|
+
FileDescriptor errorPipe;
|
59
43
|
};
|
60
44
|
|
61
|
-
typedef boost::shared_ptr<PipeWatcher> PipeWatcherPtr;
|
62
|
-
|
63
45
|
|
64
|
-
} // namespace
|
46
|
+
} // namespace SpawningKit
|
65
47
|
} // namespace Passenger
|
66
48
|
|
67
|
-
#endif /*
|
49
|
+
#endif /* _PASSENGER_SPAWNING_KIT_RESULT_H_ */
|
@@ -22,14 +22,15 @@
|
|
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
|
26
|
-
#define
|
25
|
+
#ifndef _PASSENGER_SPAWNING_KIT_SMART_SPAWNER_H_
|
26
|
+
#define _PASSENGER_SPAWNING_KIT_SMART_SPAWNER_H_
|
27
27
|
|
28
|
-
#include <
|
28
|
+
#include <SpawningKit/Spawner.h>
|
29
|
+
#include <SpawningKit/PipeWatcher.h>
|
29
30
|
#include <Constants.h>
|
30
31
|
|
31
32
|
namespace Passenger {
|
32
|
-
namespace
|
33
|
+
namespace SpawningKit {
|
33
34
|
|
34
35
|
using namespace std;
|
35
36
|
using namespace boost;
|
@@ -60,12 +61,6 @@ private:
|
|
60
61
|
}
|
61
62
|
};
|
62
63
|
|
63
|
-
struct SpawnResult {
|
64
|
-
pid_t pid;
|
65
|
-
FileDescriptor adminSocket;
|
66
|
-
BufferedIO io;
|
67
|
-
};
|
68
|
-
|
69
64
|
const vector<string> preloaderCommand;
|
70
65
|
map<string, string> preloaderAnnotations;
|
71
66
|
Options options;
|
@@ -104,8 +99,8 @@ private:
|
|
104
99
|
vector<string> command;
|
105
100
|
|
106
101
|
if (shouldLoadShellEnvvars(options, preparation)) {
|
107
|
-
command.push_back(preparation.shell);
|
108
|
-
command.push_back(preparation.shell);
|
102
|
+
command.push_back(preparation.userSwitching.shell);
|
103
|
+
command.push_back(preparation.userSwitching.shell);
|
109
104
|
command.push_back("-lc");
|
110
105
|
command.push_back("exec \"$@\"");
|
111
106
|
command.push_back("SpawnPreparerShell");
|
@@ -214,7 +209,8 @@ private:
|
|
214
209
|
vector<string> command = createRealPreloaderCommand(options, args);
|
215
210
|
SocketPair adminSocket = createUnixSocketPair(__FILE__, __LINE__);
|
216
211
|
Pipe errorPipe = createPipe(__FILE__, __LINE__);
|
217
|
-
DebugDirPtr debugDir = boost::make_shared<DebugDir>(preparation.uid,
|
212
|
+
DebugDirPtr debugDir = boost::make_shared<DebugDir>(preparation.userSwitching.uid,
|
213
|
+
preparation.userSwitching.gid);
|
218
214
|
pid_t pid;
|
219
215
|
|
220
216
|
pid = syscalls::fork();
|
@@ -295,13 +291,13 @@ private:
|
|
295
291
|
|
296
292
|
PipeWatcherPtr watcher;
|
297
293
|
|
298
|
-
watcher = boost::make_shared<PipeWatcher>(
|
299
|
-
"stdout", pid);
|
294
|
+
watcher = boost::make_shared<PipeWatcher>(config,
|
295
|
+
adminSocket.second, "stdout", pid);
|
300
296
|
watcher->initialize();
|
301
297
|
watcher->start();
|
302
298
|
|
303
|
-
watcher = boost::make_shared<PipeWatcher>(
|
304
|
-
"stderr", pid);
|
299
|
+
watcher = boost::make_shared<PipeWatcher>(config,
|
300
|
+
errorPipe.first, "stderr", pid);
|
305
301
|
watcher->initialize();
|
306
302
|
watcher->start();
|
307
303
|
|
@@ -350,10 +346,11 @@ private:
|
|
350
346
|
"ruby_libdir: " + config->resourceLocator->getRubyLibDir() + "\n"
|
351
347
|
"passenger_version: " PASSENGER_VERSION "\n"
|
352
348
|
"UNIX_PATH_MAX: " + toString(UNIX_PATH_MAX) + "\n";
|
353
|
-
if (!details.options->
|
354
|
-
data.append("connect_password: " + details.options->
|
349
|
+
if (!details.options->apiKey.empty()) {
|
350
|
+
data.append("connect_password: " + details.options->apiKey + "\n");
|
355
351
|
}
|
356
352
|
if (!config->instanceDir.empty()) {
|
353
|
+
data.append("instance_dir: " + config->instanceDir + "\n");
|
357
354
|
data.append("socket_dir: " + config->instanceDir + "/apps.s\n");
|
358
355
|
}
|
359
356
|
|
@@ -617,9 +614,31 @@ private:
|
|
617
614
|
return "";
|
618
615
|
}
|
619
616
|
|
620
|
-
|
617
|
+
NegotiationDetails sendSpawnCommandAndGetNegotiationDetails(const Options &options) {
|
618
|
+
TRACE_POINT();
|
619
|
+
NegotiationDetails details;
|
620
|
+
|
621
|
+
details.preparation = &preparation;
|
622
|
+
details.options = &options;
|
623
|
+
|
624
|
+
try {
|
625
|
+
sendSpawnCommand(details);
|
626
|
+
} catch (const SystemException &e) {
|
627
|
+
sendSpawnCommandAgain(e, details);
|
628
|
+
} catch (const IOException &e) {
|
629
|
+
sendSpawnCommandAgain(e, details);
|
630
|
+
} catch (const SpawnException &e) {
|
631
|
+
sendSpawnCommandAgain(e, details);
|
632
|
+
}
|
633
|
+
|
634
|
+
return details;
|
635
|
+
}
|
636
|
+
|
637
|
+
void sendSpawnCommand(NegotiationDetails &details) {
|
621
638
|
TRACE_POINT();
|
639
|
+
const Options &options = *details.options;
|
622
640
|
FileDescriptor fd;
|
641
|
+
|
623
642
|
try {
|
624
643
|
fd.assign(connectToServer(socketAddress, __FILE__, __LINE__), NULL, 0);
|
625
644
|
} catch (const SystemException &e) {
|
@@ -683,41 +702,34 @@ private:
|
|
683
702
|
DebugDirPtr());
|
684
703
|
}
|
685
704
|
|
686
|
-
SpawnResult result;
|
687
705
|
P_LOG_FILE_DESCRIPTOR_PURPOSE(fd, "App " << spawnedPid
|
688
706
|
<< " (" << options.appRoot << ") adminSocket[1]");
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
return result;
|
707
|
+
details.pid = spawnedPid;
|
708
|
+
details.adminSocket = fd;
|
709
|
+
details.io = io;
|
693
710
|
|
694
711
|
} else if (result == "Error\n") {
|
695
712
|
UPDATE_TRACE_POINT();
|
696
|
-
NegotiationDetails details;
|
697
713
|
details.io = io;
|
698
714
|
details.timeout = timeout;
|
699
715
|
handleSpawnErrorResponse(details);
|
700
716
|
|
701
717
|
} else {
|
702
718
|
UPDATE_TRACE_POINT();
|
703
|
-
NegotiationDetails details;
|
704
719
|
handleInvalidSpawnResponseType(result, details);
|
705
720
|
}
|
706
|
-
|
707
|
-
return SpawnResult(); // Never reached.
|
708
721
|
}
|
709
722
|
|
710
723
|
template<typename Exception>
|
711
|
-
|
724
|
+
void sendSpawnCommandAgain(const Exception &e, NegotiationDetails &details) {
|
712
725
|
TRACE_POINT();
|
713
726
|
P_WARN("An error occurred while spawning a process: " << e.what());
|
714
727
|
P_WARN("The application preloader seems to have crashed, restarting it and trying again...");
|
715
728
|
stopPreloader();
|
716
729
|
startPreloader();
|
717
730
|
ScopeGuard guard(boost::bind(&SmartSpawner::stopPreloader, this));
|
718
|
-
|
731
|
+
sendSpawnCommand(details);
|
719
732
|
guard.clear();
|
720
|
-
return result;
|
721
733
|
}
|
722
734
|
|
723
735
|
protected:
|
@@ -729,7 +741,7 @@ protected:
|
|
729
741
|
public:
|
730
742
|
SmartSpawner(const vector<string> &_preloaderCommand,
|
731
743
|
const Options &_options,
|
732
|
-
const
|
744
|
+
const ConfigPtr &_config)
|
733
745
|
: Spawner(_config),
|
734
746
|
preloaderCommand(_preloaderCommand)
|
735
747
|
{
|
@@ -747,7 +759,7 @@ public:
|
|
747
759
|
stopPreloader();
|
748
760
|
}
|
749
761
|
|
750
|
-
virtual
|
762
|
+
virtual Result spawn(const Options &options) {
|
751
763
|
TRACE_POINT();
|
752
764
|
assert(options.appType == this->options.appType);
|
753
765
|
assert(options.appRoot == this->options.appRoot);
|
@@ -767,28 +779,11 @@ public:
|
|
767
779
|
}
|
768
780
|
|
769
781
|
UPDATE_TRACE_POINT();
|
770
|
-
|
771
|
-
|
772
|
-
result = sendSpawnCommand(options);
|
773
|
-
} catch (const SystemException &e) {
|
774
|
-
result = sendSpawnCommandAgain(e, options);
|
775
|
-
} catch (const IOException &e) {
|
776
|
-
result = sendSpawnCommandAgain(e, options);
|
777
|
-
} catch (const SpawnException &e) {
|
778
|
-
result = sendSpawnCommandAgain(e, options);
|
779
|
-
}
|
780
|
-
|
781
|
-
UPDATE_TRACE_POINT();
|
782
|
-
NegotiationDetails details;
|
783
|
-
details.preparation = &preparation;
|
784
|
-
details.pid = result.pid;
|
785
|
-
details.adminSocket = result.adminSocket;
|
786
|
-
details.io = result.io;
|
787
|
-
details.options = &options;
|
788
|
-
SpawnObject object = negotiateSpawn(details);
|
782
|
+
NegotiationDetails details = sendSpawnCommandAndGetNegotiationDetails(options);
|
783
|
+
Result result = negotiateSpawn(details);
|
789
784
|
P_DEBUG("Process spawning done: appRoot=" << options.appRoot <<
|
790
|
-
", pid=" <<
|
791
|
-
return
|
785
|
+
", pid=" << result["pid"].asInt());
|
786
|
+
return result;
|
792
787
|
}
|
793
788
|
|
794
789
|
virtual bool cleanable() const {
|
@@ -817,7 +812,7 @@ public:
|
|
817
812
|
};
|
818
813
|
|
819
814
|
|
820
|
-
} // namespace
|
815
|
+
} // namespace SpawningKit
|
821
816
|
} // namespace Passenger
|
822
817
|
|
823
|
-
#endif /*
|
818
|
+
#endif /* _PASSENGER_SPAWNING_KIT_SMART_SPAWNER_H_ */
|