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.

Files changed (106) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/CHANGELOG +15 -0
  5. data/CONTRIBUTORS +6 -0
  6. data/README.md +1 -1
  7. data/bin/passenger-install-apache2-module +24 -11
  8. data/bin/passenger-status +29 -14
  9. data/build/agents.rb +12 -10
  10. data/build/cxx_tests.rb +30 -30
  11. data/doc/Design and Architecture.html +1 -10
  12. data/doc/Design and Architecture.txt +1 -6
  13. data/doc/Users guide Apache.html +1 -19
  14. data/doc/Users guide Apache.txt +1 -1
  15. data/doc/Users guide Nginx.html +2 -20
  16. data/doc/Users guide Nginx.txt +2 -2
  17. data/doc/users_guide_snippets/tips.txt +0 -9
  18. data/ext/common/ApplicationPool2/ApiKey.h +158 -0
  19. data/ext/common/ApplicationPool2/BasicGroupInfo.h +81 -0
  20. data/ext/common/ApplicationPool2/BasicProcessInfo.h +106 -0
  21. data/ext/common/ApplicationPool2/Common.h +5 -44
  22. data/ext/common/ApplicationPool2/Context.h +94 -0
  23. data/ext/common/ApplicationPool2/Group.h +130 -1205
  24. data/ext/common/ApplicationPool2/Group/InitializationAndShutdown.cpp +190 -0
  25. data/ext/common/ApplicationPool2/Group/InternalUtils.cpp +329 -0
  26. data/ext/common/ApplicationPool2/Group/LifetimeAndBasics.cpp +103 -0
  27. data/ext/common/ApplicationPool2/{Pool/Debug.h → Group/Miscellaneous.cpp} +40 -38
  28. data/ext/common/ApplicationPool2/Group/OutOfBandWork.cpp +323 -0
  29. data/ext/common/ApplicationPool2/Group/ProcessListManagement.cpp +606 -0
  30. data/ext/common/ApplicationPool2/Group/SessionManagement.cpp +337 -0
  31. data/ext/common/ApplicationPool2/Group/SpawningAndRestarting.cpp +478 -0
  32. data/ext/common/ApplicationPool2/Group/StateInspection.cpp +197 -0
  33. data/ext/common/ApplicationPool2/Group/Verification.cpp +159 -0
  34. data/ext/common/ApplicationPool2/Implementation.cpp +19 -1401
  35. data/ext/common/ApplicationPool2/Options.h +5 -5
  36. data/ext/common/ApplicationPool2/Pool.h +260 -815
  37. data/ext/common/ApplicationPool2/Pool/{AnalyticsCollection.h → AnalyticsCollection.cpp} +55 -56
  38. data/ext/common/ApplicationPool2/Pool/{GarbageCollection.h → GarbageCollection.cpp} +49 -49
  39. data/ext/common/ApplicationPool2/Pool/GeneralUtils.cpp +241 -0
  40. data/ext/common/ApplicationPool2/Pool/GroupUtils.cpp +276 -0
  41. data/ext/common/ApplicationPool2/Pool/InitializationAndShutdown.cpp +145 -0
  42. data/ext/common/ApplicationPool2/Pool/Miscellaneous.cpp +244 -0
  43. data/ext/common/ApplicationPool2/Pool/ProcessUtils.cpp +330 -0
  44. data/ext/common/ApplicationPool2/Pool/StateInspection.cpp +299 -0
  45. data/ext/common/ApplicationPool2/Process.h +399 -205
  46. data/ext/common/ApplicationPool2/Session.h +70 -28
  47. data/ext/common/ApplicationPool2/Socket.h +1 -0
  48. data/ext/common/Constants.h +11 -3
  49. data/ext/common/Exceptions.h +1 -1
  50. data/ext/common/Logging.cpp +9 -4
  51. data/ext/common/Logging.h +6 -0
  52. data/ext/common/ServerKit/HttpServer.h +225 -215
  53. data/ext/common/ServerKit/Server.h +57 -57
  54. data/ext/common/SpawningKit/BackgroundIOCapturer.h +160 -0
  55. data/ext/common/SpawningKit/Config.h +107 -0
  56. data/ext/common/{ApplicationPool2 → SpawningKit}/DirectSpawner.h +17 -16
  57. data/ext/common/{ApplicationPool2 → SpawningKit}/DummySpawner.h +33 -33
  58. data/ext/common/{ApplicationPool2/SpawnerFactory.h → SpawningKit/Factory.h} +17 -17
  59. data/ext/common/{ApplicationPool2/ComponentInfo.h → SpawningKit/Options.h} +8 -21
  60. data/ext/common/SpawningKit/PipeWatcher.h +148 -0
  61. data/ext/common/{ApplicationPool2/PipeWatcher.h → SpawningKit/Result.h} +15 -33
  62. data/ext/common/{ApplicationPool2 → SpawningKit}/SmartSpawner.h +52 -57
  63. data/ext/common/{ApplicationPool2 → SpawningKit}/Spawner.h +83 -371
  64. data/ext/common/SpawningKit/UserSwitchingRules.h +265 -0
  65. data/ext/common/Utils/BufferedIO.h +24 -0
  66. data/ext/common/{ApplicationPool2/SpawnObject.h → Utils/ClassUtils.h} +24 -51
  67. data/ext/common/Utils/IOUtils.cpp +70 -0
  68. data/ext/common/Utils/IOUtils.h +19 -0
  69. data/ext/common/Utils/JsonUtils.h +113 -0
  70. data/ext/common/Utils/StrIntUtils.h +29 -0
  71. data/ext/common/Utils/json.h +1 -1
  72. data/ext/common/agents/ApiServerUtils.h +941 -0
  73. data/ext/common/agents/HelperAgent/{AdminServer.h → ApiServer.h} +163 -365
  74. data/ext/common/agents/HelperAgent/Main.cpp +86 -88
  75. data/ext/common/agents/HelperAgent/OptionParser.h +9 -10
  76. data/ext/common/agents/HelperAgent/RequestHandler/BufferBody.cpp +3 -0
  77. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +2 -0
  78. data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +1 -1
  79. data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +2 -2
  80. data/ext/common/agents/LoggingAgent/ApiServer.h +279 -0
  81. data/ext/common/agents/LoggingAgent/Main.cpp +41 -51
  82. data/ext/common/agents/LoggingAgent/OptionParser.h +11 -11
  83. data/ext/common/agents/Watchdog/ApiServer.h +311 -0
  84. data/ext/common/agents/Watchdog/Main.cpp +91 -65
  85. data/helper-scripts/prespawn +2 -0
  86. data/lib/phusion_passenger.rb +1 -1
  87. data/lib/phusion_passenger/admin_tools/instance.rb +1 -1
  88. data/lib/phusion_passenger/common_library.rb +27 -14
  89. data/lib/phusion_passenger/config/{admin_command_command.rb → api_call_command.rb} +19 -16
  90. data/lib/phusion_passenger/config/detach_process_command.rb +6 -3
  91. data/lib/phusion_passenger/config/main.rb +3 -5
  92. data/lib/phusion_passenger/config/reopen_logs_command.rb +29 -7
  93. data/lib/phusion_passenger/config/restart_app_command.rb +13 -4
  94. data/lib/phusion_passenger/config/utils.rb +15 -8
  95. data/lib/phusion_passenger/constants.rb +6 -2
  96. data/lib/phusion_passenger/platform_info/apache.rb +4 -0
  97. data/lib/phusion_passenger/platform_info/apache_detector.rb +18 -3
  98. data/resources/templates/apache2/mpm_unknown.txt.erb +20 -0
  99. metadata +42 -21
  100. metadata.gz.asc +7 -7
  101. data/ext/common/ApplicationPool2/Pool/GeneralUtils.h +0 -127
  102. data/ext/common/ApplicationPool2/Pool/Inspection.h +0 -219
  103. data/ext/common/ApplicationPool2/Pool/ProcessUtils.h +0 -85
  104. data/ext/common/ApplicationPool2/SuperGroup.h +0 -706
  105. data/ext/common/agents/LoggingAgent/AdminServer.h +0 -435
  106. 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 _PASSENGER_APPLICATION_POOL2_DUMMY_SPAWNER_H_
26
- #define _PASSENGER_APPLICATION_POOL2_DUMMY_SPAWNER_H_
25
+ #ifndef _PASSENGER_SPAWNING_KIT_DUMMY_SPAWNER_H_
26
+ #define _PASSENGER_SPAWNING_KIT_DUMMY_SPAWNER_H_
27
27
 
28
- #include <ApplicationPool2/Spawner.h>
28
+ #include <SpawningKit/Spawner.h>
29
+ #include <boost/atomic.hpp>
29
30
 
30
31
  namespace Passenger {
31
- namespace ApplicationPool2 {
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::mutex lock;
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 SpawnerConfigPtr &_config)
47
- : Spawner(_config)
48
- {
49
- count = 0;
50
- cleanCount = 0;
51
- }
46
+ DummySpawner(const ConfigPtr &_config)
47
+ : Spawner(_config),
48
+ count(1),
49
+ cleanCount(0)
50
+ { }
52
51
 
53
- virtual SpawnObject spawn(const Options &options) {
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
- SpawnObject object;
70
- string gupid = "gupid-" + toString(pid);
71
- object.process = boost::make_shared<Process>(
72
- pid, gupid,
73
- adminSocket.second, FileDescriptor(), sockets,
74
- SystemTime::getUsec(), SystemTime::getUsec());
75
- object.process->dummy = true;
76
- return boost::move(object);
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 ApplicationPool2
91
+ } // namespace SpawningKit
92
92
  } // namespace Passenger
93
93
 
94
- #endif /* _PASSENGER_APPLICATION_POOL2_DUMMY_SPAWNER_H_ */
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-2014 Phusion
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 _PASSENGER_APPLICATION_POOL2_SPAWNER_FACTORY_H_
26
- #define _PASSENGER_APPLICATION_POOL2_SPAWNER_FACTORY_H_
25
+ #ifndef _PASSENGER_SPAWNING_KIT_FACTORY_H_
26
+ #define _PASSENGER_SPAWNING_KIT_FACTORY_H_
27
27
 
28
- #include <ApplicationPool2/Spawner.h>
29
- #include <ApplicationPool2/SmartSpawner.h>
30
- #include <ApplicationPool2/DirectSpawner.h>
31
- #include <ApplicationPool2/DummySpawner.h>
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 ApplicationPool2 {
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 SpawnerFactory {
41
+ class Factory {
42
42
  private:
43
43
  boost::mutex syncher;
44
- SpawnerConfigPtr config;
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
- SpawnerFactory(const SpawnerConfigPtr &_config)
61
+ Factory(const ConfigPtr &_config)
62
62
  : config(_config)
63
63
  { }
64
64
 
65
- virtual ~SpawnerFactory() { }
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 SpawnerConfig object.
100
+ * All created Spawner objects share the same Config object.
101
101
  */
102
- const SpawnerConfigPtr &getConfig() const {
102
+ const ConfigPtr &getConfig() const {
103
103
  return config;
104
104
  }
105
105
  };
106
106
 
107
- typedef boost::shared_ptr<SpawnerFactory> SpawnerFactoryPtr;
107
+ typedef boost::shared_ptr<Factory> FactoryPtr;
108
108
 
109
109
 
110
- } // namespace ApplicationPool2
110
+ } // namespace SpawningKit
111
111
  } // namespace Passenger
112
112
 
113
- #endif /* _PASSENGER_APPLICATION_POOL2_SPAWNER_FACTORY_H_ */
113
+ #endif /* _PASSENGER_SPAWNING_KIT_FACTORY_H_ */
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011, 2012 Phusion
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 _PASSENGER_APPLICATION_POOL2_COMPONENT_INFO_H_
26
- #define _PASSENGER_APPLICATION_POOL2_COMPONENT_INFO_H_
25
+ #ifndef _PASSENGER_SPAWNING_KIT_OPTIONS_H_
26
+ #define _PASSENGER_SPAWNING_KIT_OPTIONS_H_
27
27
 
28
- #include <string>
28
+ #include <ApplicationPool2/Options.h>
29
29
 
30
30
  namespace Passenger {
31
- namespace ApplicationPool2 {
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 /* _PASSENGER_APPLICATION_POOL2_COMPONENT_INFO_H_ */
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) 2012-2013 Phusion
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 _PASSENGER_APPLICATION_POOL_PIPE_WATCHER_H_
26
- #define _PASSENGER_APPLICATION_POOL_PIPE_WATCHER_H_
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 ApplicationPool2 {
32
+ namespace SpawningKit {
37
33
 
38
- using namespace boost;
39
34
 
40
-
41
- /** A PipeWatcher lives until the file descriptor is closed. */
42
- struct PipeWatcher: public boost::enable_shared_from_this<PipeWatcher> {
43
- // For unit tests.
44
- typedef boost::function<void (const char *data, unsigned int size)> DataCallback;
45
- static DataCallback onData;
46
-
47
- FileDescriptor fd;
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 ApplicationPool2
46
+ } // namespace SpawningKit
65
47
  } // namespace Passenger
66
48
 
67
- #endif /* _PASSENGER_APPLICATION_POOL_PIPE_WATCHER_H_ */
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 _PASSENGER_APPLICATION_POOL2_SMART_SPAWNER_H_
26
- #define _PASSENGER_APPLICATION_POOL2_SMART_SPAWNER_H_
25
+ #ifndef _PASSENGER_SPAWNING_KIT_SMART_SPAWNER_H_
26
+ #define _PASSENGER_SPAWNING_KIT_SMART_SPAWNER_H_
27
27
 
28
- #include <ApplicationPool2/Spawner.h>
28
+ #include <SpawningKit/Spawner.h>
29
+ #include <SpawningKit/PipeWatcher.h>
29
30
  #include <Constants.h>
30
31
 
31
32
  namespace Passenger {
32
- namespace ApplicationPool2 {
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, preparation.gid);
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>(adminSocket.second,
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>(errorPipe.first,
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->groupSecret.empty()) {
354
- data.append("connect_password: " + details.options->groupSecret + "\n");
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
- SpawnResult sendSpawnCommand(const Options &options) {
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
- result.pid = spawnedPid;
690
- result.adminSocket = fd;
691
- result.io = io;
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
- SpawnResult sendSpawnCommandAgain(const Exception &e, const Options &options) {
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
- SpawnResult result = sendSpawnCommand(options);
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 SpawnerConfigPtr &_config)
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 SpawnObject spawn(const Options &options) {
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
- SpawnResult result;
771
- try {
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=" << object.process->pid);
791
- return boost::move(object);
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 ApplicationPool2
815
+ } // namespace SpawningKit
821
816
  } // namespace Passenger
822
817
 
823
- #endif /* _PASSENGER_APPLICATION_POOL2_SMART_SPAWNER_H_ */
818
+ #endif /* _PASSENGER_SPAWNING_KIT_SMART_SPAWNER_H_ */