passenger 4.0.27 → 4.0.28
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/.gitignore +1 -0
- data/NEWS +22 -0
- data/build/preprocessor.rb +10 -0
- data/build/rpm.rb +74 -65
- data/debian.template/rules.template +8 -0
- data/dev/copy_boost_headers.rb +11 -2
- data/doc/Users guide Apache.idmap.txt +161 -145
- data/doc/Users guide Apache.txt +12 -1
- data/doc/Users guide Nginx.idmap.txt +142 -126
- data/doc/Users guide Nginx.txt +14 -1
- data/doc/Users guide Standalone.txt +1 -0
- data/doc/users_guide_snippets/environment_variables.txt +1 -1
- data/doc/users_guide_snippets/installation.txt +2 -0
- data/doc/users_guide_snippets/tips.txt +118 -0
- data/ext/apache2/Configuration.cpp +0 -6
- data/ext/apache2/Configuration.hpp +0 -5
- data/ext/apache2/ConfigurationCommands.cpp +7 -0
- data/ext/apache2/ConfigurationFields.hpp +2 -0
- data/ext/apache2/ConfigurationSetters.cpp +24 -0
- data/ext/apache2/CreateDirConfig.cpp +1 -0
- data/ext/apache2/Hooks.cpp +0 -1
- data/ext/apache2/MergeDirConfig.cpp +7 -0
- data/ext/apache2/SetHeaders.cpp +5 -1
- data/ext/boost/cregex.hpp +39 -0
- data/ext/boost/libs/regex/src/c_regex_traits.cpp +193 -0
- data/ext/boost/libs/regex/src/cpp_regex_traits.cpp +117 -0
- data/ext/boost/libs/regex/src/cregex.cpp +660 -0
- data/ext/boost/libs/regex/src/instances.cpp +32 -0
- data/ext/boost/libs/regex/src/internals.hpp +35 -0
- data/ext/boost/libs/regex/src/posix_api.cpp +296 -0
- data/ext/boost/libs/regex/src/regex.cpp +227 -0
- data/ext/boost/libs/regex/src/regex_debug.cpp +59 -0
- data/ext/boost/libs/regex/src/regex_raw_buffer.cpp +72 -0
- data/ext/boost/libs/regex/src/regex_traits_defaults.cpp +692 -0
- data/ext/boost/libs/regex/src/static_mutex.cpp +179 -0
- data/ext/boost/libs/regex/src/wc_regex_traits.cpp +301 -0
- data/ext/boost/libs/regex/src/wide_posix_api.cpp +315 -0
- data/ext/boost/libs/regex/src/winstances.cpp +35 -0
- data/ext/boost/regex.h +100 -0
- data/ext/boost/regex.hpp +37 -0
- data/ext/boost/regex/concepts.hpp +1128 -0
- data/ext/boost/regex/config.hpp +435 -0
- data/ext/boost/regex/config/borland.hpp +72 -0
- data/ext/boost/regex/config/cwchar.hpp +207 -0
- data/ext/boost/regex/mfc.hpp +190 -0
- data/ext/boost/regex/pattern_except.hpp +100 -0
- data/ext/boost/regex/pending/object_cache.hpp +165 -0
- data/ext/boost/regex/pending/static_mutex.hpp +179 -0
- data/ext/boost/regex/pending/unicode_iterator.hpp +776 -0
- data/ext/boost/regex/regex_traits.hpp +35 -0
- data/ext/boost/regex/user.hpp +93 -0
- data/ext/boost/regex/v4/basic_regex.hpp +782 -0
- data/ext/boost/regex/v4/basic_regex_creator.hpp +1571 -0
- data/ext/boost/regex/v4/basic_regex_parser.hpp +2874 -0
- data/ext/boost/regex/v4/c_regex_traits.hpp +211 -0
- data/ext/boost/regex/v4/char_regex_traits.hpp +81 -0
- data/ext/boost/regex/v4/cpp_regex_traits.hpp +1099 -0
- data/ext/boost/regex/v4/cregex.hpp +330 -0
- data/ext/boost/regex/v4/error_type.hpp +59 -0
- data/ext/boost/regex/v4/fileiter.hpp +455 -0
- data/ext/boost/regex/v4/instances.hpp +222 -0
- data/ext/boost/regex/v4/iterator_category.hpp +91 -0
- data/ext/boost/regex/v4/iterator_traits.hpp +135 -0
- data/ext/boost/regex/v4/match_flags.hpp +138 -0
- data/ext/boost/regex/v4/match_results.hpp +702 -0
- data/ext/boost/regex/v4/mem_block_cache.hpp +99 -0
- data/ext/boost/regex/v4/perl_matcher.hpp +587 -0
- data/ext/boost/regex/v4/perl_matcher_common.hpp +996 -0
- data/ext/boost/regex/v4/perl_matcher_non_recursive.hpp +1642 -0
- data/ext/boost/regex/v4/perl_matcher_recursive.hpp +991 -0
- data/ext/boost/regex/v4/primary_transform.hpp +146 -0
- data/ext/boost/regex/v4/protected_call.hpp +81 -0
- data/ext/boost/regex/v4/regbase.hpp +180 -0
- data/ext/boost/regex/v4/regex.hpp +202 -0
- data/ext/boost/regex/v4/regex_format.hpp +1156 -0
- data/ext/boost/regex/v4/regex_fwd.hpp +73 -0
- data/ext/boost/regex/v4/regex_grep.hpp +155 -0
- data/ext/boost/regex/v4/regex_iterator.hpp +201 -0
- data/ext/boost/regex/v4/regex_match.hpp +382 -0
- data/ext/boost/regex/v4/regex_merge.hpp +93 -0
- data/ext/boost/regex/v4/regex_raw_buffer.hpp +210 -0
- data/ext/boost/regex/v4/regex_replace.hpp +99 -0
- data/ext/boost/regex/v4/regex_search.hpp +217 -0
- data/ext/boost/regex/v4/regex_split.hpp +172 -0
- data/ext/boost/regex/v4/regex_token_iterator.hpp +342 -0
- data/ext/boost/regex/v4/regex_traits.hpp +189 -0
- data/ext/boost/regex/v4/regex_traits_defaults.hpp +371 -0
- data/ext/boost/regex/v4/regex_workaround.hpp +232 -0
- data/ext/boost/regex/v4/states.hpp +301 -0
- data/ext/boost/regex/v4/sub_match.hpp +512 -0
- data/ext/boost/regex/v4/syntax_type.hpp +105 -0
- data/ext/boost/regex/v4/u32regex_iterator.hpp +193 -0
- data/ext/boost/regex/v4/u32regex_token_iterator.hpp +377 -0
- data/ext/boost/regex/v4/w32_regex_traits.hpp +741 -0
- data/ext/boost/regex_fwd.hpp +33 -0
- data/ext/common/AgentsStarter.h +0 -11
- data/ext/common/ApplicationPool2/Common.h +1 -7
- data/ext/common/ApplicationPool2/DirectSpawner.h +3 -3
- data/ext/common/ApplicationPool2/Group.h +166 -69
- data/ext/common/ApplicationPool2/Implementation.cpp +55 -10
- data/ext/common/ApplicationPool2/Options.h +45 -10
- data/ext/common/ApplicationPool2/PipeWatcher.h +1 -2
- data/ext/common/ApplicationPool2/Pool.h +29 -7
- data/ext/common/ApplicationPool2/Process.h +22 -3
- data/ext/common/ApplicationPool2/Session.h +1 -0
- data/ext/common/ApplicationPool2/SmartSpawner.h +5 -10
- data/ext/common/ApplicationPool2/Spawner.h +10 -15
- data/ext/common/ApplicationPool2/SuperGroup.h +10 -9
- data/ext/common/Constants.h +1 -3
- data/ext/common/Hooks.h +193 -0
- data/ext/common/Logging.cpp +67 -2
- data/ext/common/Logging.h +23 -1
- data/ext/common/Utils.cpp +0 -21
- data/ext/common/Utils.h +0 -42
- data/ext/common/Utils/CachedFileStat.hpp +1 -1
- data/ext/common/Utils/StrIntUtils.h +61 -14
- data/ext/common/Utils/StringMap.h +4 -0
- data/ext/common/agents/HelperAgent/AgentOptions.h +4 -4
- data/ext/common/agents/HelperAgent/Main.cpp +2 -3
- data/ext/common/agents/HelperAgent/RequestHandler.h +65 -2
- data/ext/common/agents/LoggingAgent/FilterSupport.h +3 -1
- data/ext/common/agents/Watchdog/Main.cpp +8 -72
- data/ext/nginx/CacheLocationConfig.c +29 -1
- data/ext/nginx/Configuration.c +0 -12
- data/ext/nginx/Configuration.h +0 -1
- data/ext/nginx/ConfigurationCommands.c +10 -0
- data/ext/nginx/ConfigurationFields.h +2 -0
- data/ext/nginx/CreateLocationConfig.c +4 -0
- data/ext/nginx/MergeLocationConfig.c +6 -0
- data/ext/oxt/system_calls.cpp +7 -1
- data/ext/oxt/system_calls.hpp +7 -7
- data/helper-scripts/node-loader.js +6 -2
- data/helper-scripts/rack-loader.rb +5 -2
- data/helper-scripts/rack-preloader.rb +5 -2
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/apache2/config_options.rb +8 -0
- data/lib/phusion_passenger/constants.rb +0 -1
- data/lib/phusion_passenger/nginx/config_options.rb +9 -2
- data/lib/phusion_passenger/platform_info/apache.rb +2 -1
- data/lib/phusion_passenger/platform_info/compiler.rb +15 -1
- data/lib/phusion_passenger/platform_info/cxx_portability.rb +2 -0
- data/node_lib/phusion_passenger/httplib_emulation.js +85 -17
- data/node_lib/phusion_passenger/request_handler.js +10 -2
- data/rpm/Vagrantfile +32 -0
- data/rpm/get_distro_id.py +4 -0
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +2 -2
- data/test/cxx/ApplicationPool2/PoolTest.cpp +60 -9
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +2 -6
- data/test/cxx/CachedFileStatTest.cpp +5 -5
- data/test/cxx/RequestHandlerTest.cpp +3 -6
- data/test/cxx/UtilsTest.cpp +30 -0
- data/test/node/httplib_emulation_spec.js +491 -0
- data/test/node/spec_helper.js +25 -0
- metadata +78 -2
- metadata.gz.asc +7 -7
data/ext/common/Logging.h
CHANGED
@@ -124,7 +124,29 @@ enum PassengerLogLevel {
|
|
124
124
|
#define P_TRACE(level, expr) do { /* nothing */ } while (false)
|
125
125
|
#endif
|
126
126
|
|
127
|
+
/**
|
128
|
+
* Print a message that was received from an application's stdout/stderr.
|
129
|
+
*
|
130
|
+
* @param pid The application's PID.
|
131
|
+
* @param channelName "stdout" or "stderr".
|
132
|
+
* @param message The message that was received.
|
133
|
+
*/
|
134
|
+
void printAppOutput(pid_t pid, const char *channelName, const char *message, unsigned int size);
|
135
|
+
|
136
|
+
/**
|
137
|
+
* Controls how messages that are received from applications are printed.
|
138
|
+
*
|
139
|
+
* If `enabled` is true then messages are printed using P_DEBUG, meaning that
|
140
|
+
* the normal Passenger logging prefixes will be printed as well.
|
141
|
+
*
|
142
|
+
* If `enabled` is false (the default), then messages are printed directly
|
143
|
+
* to the log output channel using write(), with only a very short prefix
|
144
|
+
* that contains the PID and channel name.
|
145
|
+
*/
|
146
|
+
void setPrintAppOutputAsDebuggingMessages(bool enabled);
|
147
|
+
|
127
148
|
|
149
|
+
/** Print a [BUG] error message and abort with a stack trace. */
|
128
150
|
#define P_BUG(expr) \
|
129
151
|
do { \
|
130
152
|
TRACE_POINT(); \
|
@@ -165,7 +187,7 @@ public:
|
|
165
187
|
|
166
188
|
/**
|
167
189
|
* Put this in code sections where you don't expect *any* exceptions to be thrown.
|
168
|
-
* This macro will automatically
|
190
|
+
* This macro will automatically disable interruptions in the current scope,
|
169
191
|
* and will print an error message whenever the scope exits with an exception.
|
170
192
|
*
|
171
193
|
* When inside critical sections, you should put this macro right after the lock
|
data/ext/common/Utils.cpp
CHANGED
@@ -731,27 +731,6 @@ removeDirTree(const string &path) {
|
|
731
731
|
}
|
732
732
|
}
|
733
733
|
|
734
|
-
bool
|
735
|
-
verifyRailsDir(const string &dir, CachedFileStat *cstat, unsigned int throttleRate) {
|
736
|
-
string temp(dir);
|
737
|
-
temp.append("/config/environment.rb");
|
738
|
-
return fileExists(temp, cstat, throttleRate);
|
739
|
-
}
|
740
|
-
|
741
|
-
bool
|
742
|
-
verifyRackDir(const string &dir, CachedFileStat *cstat, unsigned int throttleRate) {
|
743
|
-
string temp(dir);
|
744
|
-
temp.append("/config.ru");
|
745
|
-
return fileExists(temp, cstat, throttleRate);
|
746
|
-
}
|
747
|
-
|
748
|
-
bool
|
749
|
-
verifyWSGIDir(const string &dir, CachedFileStat *cstat, unsigned int throttleRate) {
|
750
|
-
string temp(dir);
|
751
|
-
temp.append("/passenger_wsgi.py");
|
752
|
-
return fileExists(temp, cstat, throttleRate);
|
753
|
-
}
|
754
|
-
|
755
734
|
void
|
756
735
|
prestartWebApps(const ResourceLocator &locator, const string &ruby,
|
757
736
|
const vector<string> &prestartURLs)
|
data/ext/common/Utils.h
CHANGED
@@ -337,48 +337,6 @@ void makeDirTree(const string &path, const StaticString &mode = "u=rwx,g=,o=",
|
|
337
337
|
*/
|
338
338
|
void removeDirTree(const string &path);
|
339
339
|
|
340
|
-
/**
|
341
|
-
* Check whether the specified directory is a valid Ruby on Rails
|
342
|
-
* application root directory.
|
343
|
-
*
|
344
|
-
* @param cstat A CachedFileStat object, if you want to use cached statting.
|
345
|
-
* @param throttleRate A throttle rate for cstat. Only applicable if cstat is not NULL.
|
346
|
-
* @throws FileSystemException Unable to check because of a system error.
|
347
|
-
* @throws TimeRetrievalException
|
348
|
-
* @throws boost::thread_interrupted
|
349
|
-
* @ingroup Support
|
350
|
-
*/
|
351
|
-
bool verifyRailsDir(const string &dir, CachedFileStat *cstat = 0,
|
352
|
-
unsigned int throttleRate = 0);
|
353
|
-
|
354
|
-
/**
|
355
|
-
* Check whether the specified directory is a valid Rack application
|
356
|
-
* root directory.
|
357
|
-
*
|
358
|
-
* @param cstat A CachedFileStat object, if you want to use cached statting.
|
359
|
-
* @param throttleRate A throttle rate for cstat. Only applicable if cstat is not NULL.
|
360
|
-
* @throws FileSystemException Unable to check because of a filesystem error.
|
361
|
-
* @throws TimeRetrievalException
|
362
|
-
* @throws boost::thread_interrupted
|
363
|
-
* @ingroup Support
|
364
|
-
*/
|
365
|
-
bool verifyRackDir(const string &dir, CachedFileStat *cstat = 0,
|
366
|
-
unsigned int throttleRate = 0);
|
367
|
-
|
368
|
-
/**
|
369
|
-
* Check whether the specified directory is a valid WSGI application
|
370
|
-
* root directory.
|
371
|
-
*
|
372
|
-
* @param cstat A CachedFileStat object, if you want to use cached statting.
|
373
|
-
* @param throttleRate A throttle rate for cstat. Only applicable if cstat is not NULL.
|
374
|
-
* @throws FileSystemException Unable to check because of a filesystem error.
|
375
|
-
* @throws TimeRetrievalException
|
376
|
-
* @throws boost::thread_interrupted
|
377
|
-
* @ingroup Support
|
378
|
-
*/
|
379
|
-
bool verifyWSGIDir(const string &dir, CachedFileStat *cstat = 0,
|
380
|
-
unsigned int throttleRate = 0);
|
381
|
-
|
382
340
|
void prestartWebApps(const ResourceLocator &locator, const string &ruby,
|
383
341
|
const vector<string> &prestartURLs);
|
384
342
|
|
@@ -28,6 +28,8 @@
|
|
28
28
|
#include <string>
|
29
29
|
#include <vector>
|
30
30
|
#include <sstream>
|
31
|
+
#include <stdexcept>
|
32
|
+
#include <new>
|
31
33
|
#include <cstddef>
|
32
34
|
#include <ctime>
|
33
35
|
#include <oxt/macros.hpp>
|
@@ -38,6 +40,34 @@ namespace Passenger {
|
|
38
40
|
using namespace std;
|
39
41
|
|
40
42
|
|
43
|
+
/**
|
44
|
+
* A RAII construct for memory buffers that are dynamically allocated with malloc().
|
45
|
+
* Upon destruction of a DynamicBuffer, the memory buffer is freed.
|
46
|
+
*/
|
47
|
+
struct DynamicBuffer {
|
48
|
+
typedef string::size_type size_type;
|
49
|
+
|
50
|
+
char *data;
|
51
|
+
size_type size;
|
52
|
+
|
53
|
+
/**
|
54
|
+
* @throws std::bad_alloc The buffer cannot be allocated.
|
55
|
+
*/
|
56
|
+
DynamicBuffer(size_type _size)
|
57
|
+
: size(_size)
|
58
|
+
{
|
59
|
+
data = (char *) malloc(_size);
|
60
|
+
if (data == NULL) {
|
61
|
+
throw std::bad_alloc();
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
~DynamicBuffer() throw() {
|
66
|
+
free(data);
|
67
|
+
}
|
68
|
+
};
|
69
|
+
|
70
|
+
|
41
71
|
/**
|
42
72
|
* Given a prefix string, a middle string and a postfix string, try to build a string
|
43
73
|
* that looks like <tt>prefix + middle + postfix</tt>, with as many characters from
|
@@ -162,39 +192,56 @@ string toHex(const StaticString &data);
|
|
162
192
|
*/
|
163
193
|
void toHex(const StaticString & restrict_ref data, char * restrict output, bool upperCase = false);
|
164
194
|
|
195
|
+
/**
|
196
|
+
* Reverse a string in-place.
|
197
|
+
*/
|
198
|
+
inline void
|
199
|
+
reverseString(char *str, unsigned int size) {
|
200
|
+
char *end = str + size;
|
201
|
+
for (--end; str < end; str++, end--) {
|
202
|
+
*str = *str ^ *end,
|
203
|
+
*end = *str ^ *end,
|
204
|
+
*str = *str ^ *end;
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
165
208
|
/**
|
166
209
|
* Convert the given integer to some other radix, placing
|
167
|
-
* the result into the given output buffer.
|
168
|
-
* least <tt>2 * sizeof(IntegerType) + 1</tt> bytes. The output buffer
|
210
|
+
* the result into the given output buffer. The output buffer
|
169
211
|
* will be NULL terminated. Supported radices are 2-36.
|
170
|
-
*
|
212
|
+
*
|
213
|
+
* @param outputSize The size of the output buffer, including space for
|
214
|
+
* the terminating NULL.
|
171
215
|
* @return The size of the created string, excluding
|
172
216
|
* terminating NULL.
|
217
|
+
* @throws std::length_error The output buffer is not large enough.
|
173
218
|
*/
|
174
219
|
template<typename IntegerType, int radix>
|
175
220
|
unsigned int
|
176
|
-
integerToOtherBase(IntegerType value, char *output) {
|
177
|
-
static const char
|
221
|
+
integerToOtherBase(IntegerType value, char *output, unsigned int outputSize) {
|
222
|
+
static const char chars[] = {
|
178
223
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
179
224
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
|
180
225
|
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
181
226
|
'u', 'v', 'w', 'x', 'y', 'z'
|
182
227
|
};
|
183
|
-
char buf[sizeof(value) * 2];
|
184
228
|
IntegerType remainder = value;
|
185
229
|
unsigned int size = 0;
|
186
230
|
|
187
231
|
do {
|
188
|
-
|
232
|
+
output[size] = chars[remainder % radix];
|
189
233
|
remainder = remainder / radix;
|
190
234
|
size++;
|
191
|
-
} while (remainder != 0);
|
235
|
+
} while (remainder != 0 && size < outputSize - 1);
|
192
236
|
|
193
|
-
|
194
|
-
output
|
237
|
+
if (remainder == 0) {
|
238
|
+
reverseString(output, size);
|
239
|
+
output[size] = '\0';
|
240
|
+
return size;
|
241
|
+
} else {
|
242
|
+
throw std::length_error("Buffer not large enough to for integerToOtherBase()");
|
243
|
+
return -1; // Shut up compiler warning.
|
195
244
|
}
|
196
|
-
output[size] = '\0';
|
197
|
-
return size;
|
198
245
|
}
|
199
246
|
|
200
247
|
/**
|
@@ -209,7 +256,7 @@ integerToOtherBase(IntegerType value, char *output) {
|
|
209
256
|
template<typename IntegerType>
|
210
257
|
unsigned int
|
211
258
|
integerToHex(IntegerType value, char *output) {
|
212
|
-
return integerToOtherBase<IntegerType, 16>(value, output);
|
259
|
+
return integerToOtherBase<IntegerType, 16>(value, output, 2 * sizeof(IntegerType) + 1);
|
213
260
|
}
|
214
261
|
|
215
262
|
/**
|
@@ -229,7 +276,7 @@ string integerToHex(long long value);
|
|
229
276
|
template<typename IntegerType>
|
230
277
|
unsigned int
|
231
278
|
integerToHexatri(IntegerType value, char *output) {
|
232
|
-
return integerToOtherBase<IntegerType, 36>(value, output);
|
279
|
+
return integerToOtherBase<IntegerType, 36>(value, output, 2 * sizeof(IntegerType) + 1);
|
233
280
|
}
|
234
281
|
|
235
282
|
/**
|
@@ -170,6 +170,10 @@ public:
|
|
170
170
|
return it->second.thePair.second;
|
171
171
|
}
|
172
172
|
}
|
173
|
+
|
174
|
+
bool has(const StaticString &key) const {
|
175
|
+
return store.find(key) != store.end();
|
176
|
+
}
|
173
177
|
|
174
178
|
bool set(const StaticString &key, const T &value) {
|
175
179
|
pair<InternalIterator, bool> result = store.insert(make_pair(key, Entry()));
|
@@ -36,7 +36,7 @@ using namespace std;
|
|
36
36
|
using namespace boost;
|
37
37
|
|
38
38
|
|
39
|
-
struct AgentOptions {
|
39
|
+
struct AgentOptions: public VariantMap {
|
40
40
|
pid_t webServerPid;
|
41
41
|
string serverInstanceDir;
|
42
42
|
string tempDir;
|
@@ -47,7 +47,6 @@ struct AgentOptions {
|
|
47
47
|
string defaultRubyCommand;
|
48
48
|
unsigned int generationNumber;
|
49
49
|
unsigned int maxPoolSize;
|
50
|
-
unsigned int maxInstancesPerApp;
|
51
50
|
unsigned int poolIdleTime;
|
52
51
|
string requestSocketFilename;
|
53
52
|
string requestSocketPassword;
|
@@ -63,7 +62,9 @@ struct AgentOptions {
|
|
63
62
|
|
64
63
|
AgentOptions() { }
|
65
64
|
|
66
|
-
AgentOptions(const VariantMap &options)
|
65
|
+
AgentOptions(const VariantMap &options)
|
66
|
+
: VariantMap(options)
|
67
|
+
{
|
67
68
|
testBinary = options.get("test_binary", false) == "1";
|
68
69
|
if (testBinary) {
|
69
70
|
return;
|
@@ -77,7 +78,6 @@ struct AgentOptions {
|
|
77
78
|
defaultUser = options.get("default_user");
|
78
79
|
defaultGroup = options.get("default_group");
|
79
80
|
maxPoolSize = options.getInt("max_pool_size");
|
80
|
-
maxInstancesPerApp = options.getInt("max_instances_per_app");
|
81
81
|
poolIdleTime = options.getInt("pool_idle_time");
|
82
82
|
|
83
83
|
// Required options only set by the Watchdog.
|
@@ -450,11 +450,10 @@ public:
|
|
450
450
|
"logging", options.loggingAgentPassword);
|
451
451
|
spawnerFactory = boost::make_shared<SpawnerFactory>(poolLoop.safe,
|
452
452
|
resourceLocator, generation, boost::make_shared<SpawnerConfig>(randomGenerator));
|
453
|
-
pool = boost::make_shared<Pool>(
|
454
|
-
randomGenerator);
|
453
|
+
pool = boost::make_shared<Pool>(spawnerFactory, loggerFactory,
|
454
|
+
randomGenerator, &options);
|
455
455
|
pool->initialize();
|
456
456
|
pool->setMax(options.maxPoolSize);
|
457
|
-
//pool->setMaxPerApp(maxInstancesPerApp);
|
458
457
|
pool->setMaxIdleTime(options.poolIdleTime * 1000000);
|
459
458
|
|
460
459
|
requestHandler = boost::make_shared<RequestHandler>(requestLoop.safe,
|
@@ -90,6 +90,7 @@
|
|
90
90
|
#include <sys/types.h>
|
91
91
|
#include <arpa/inet.h>
|
92
92
|
#include <sys/un.h>
|
93
|
+
#include <utility>
|
93
94
|
#include <typeinfo>
|
94
95
|
#include <cassert>
|
95
96
|
#include <cctype>
|
@@ -184,6 +185,7 @@ private:
|
|
184
185
|
contentLength = 0;
|
185
186
|
clientBodyAlreadyRead = 0;
|
186
187
|
checkoutSessionAfterCommit = false;
|
188
|
+
stickySession = false;
|
187
189
|
sessionCheckedOut = false;
|
188
190
|
sessionCheckoutTry = 0;
|
189
191
|
responseHeaderSeen = false;
|
@@ -283,6 +285,7 @@ public:
|
|
283
285
|
bool requestBodyIsBuffered;
|
284
286
|
bool sessionCheckedOut;
|
285
287
|
bool checkoutSessionAfterCommit;
|
288
|
+
bool stickySession;
|
286
289
|
|
287
290
|
bool responseHeaderSeen;
|
288
291
|
bool chunkedResponse;
|
@@ -1044,6 +1047,16 @@ private:
|
|
1044
1047
|
headerData.append("X-Powered-By: Phusion Passenger\r\n");
|
1045
1048
|
}
|
1046
1049
|
|
1050
|
+
// Add sticky session ID.
|
1051
|
+
if (client->stickySession && client->session != NULL) {
|
1052
|
+
StaticString cookieName = getStickySessionCookieName(client);
|
1053
|
+
headerData.append("Set-Cookie: ");
|
1054
|
+
headerData.append(cookieName.data(), cookieName.size());
|
1055
|
+
headerData.append("=");
|
1056
|
+
headerData.append(toString(client->session->getStickySessionId()));
|
1057
|
+
headerData.append("; HttpOnly\r\n");
|
1058
|
+
}
|
1059
|
+
|
1047
1060
|
// Add Date header. https://code.google.com/p/phusion-passenger/issues/detail?id=485
|
1048
1061
|
if (lookupHeader(headerData, "Date", "date").empty()) {
|
1049
1062
|
char dateStr[60];
|
@@ -1341,7 +1354,7 @@ private:
|
|
1341
1354
|
} else {
|
1342
1355
|
ClientPtr client = boost::make_shared<Client>();
|
1343
1356
|
client->associate(this, fd);
|
1344
|
-
clients.insert(make_pair
|
1357
|
+
clients.insert(make_pair((int) fd, client));
|
1345
1358
|
acceptedClients[count] = client;
|
1346
1359
|
count++;
|
1347
1360
|
RH_DEBUG(client, "New client accepted; new client count = " << clients.size());
|
@@ -1721,7 +1734,8 @@ private:
|
|
1721
1734
|
fillPoolOption(client, options.nodejs, "PASSENGER_NODEJS");
|
1722
1735
|
fillPoolOption(client, options.user, "PASSENGER_USER");
|
1723
1736
|
fillPoolOption(client, options.group, "PASSENGER_GROUP");
|
1724
|
-
fillPoolOption(client, options.minProcesses, "
|
1737
|
+
fillPoolOption(client, options.minProcesses, "PASSENGER_MIN_PROCESSES");
|
1738
|
+
fillPoolOption(client, options.maxProcesses, "PASSENGER_MAX_PROCESSES");
|
1725
1739
|
fillPoolOption(client, options.maxRequests, "PASSENGER_MAX_REQUESTS");
|
1726
1740
|
fillPoolOption(client, options.spawnMethod, "PASSENGER_SPAWN_METHOD");
|
1727
1741
|
fillPoolOption(client, options.startCommand, "PASSENGER_START_COMMAND");
|
@@ -1734,6 +1748,8 @@ private:
|
|
1734
1748
|
fillPoolOption(client, options.loadShellEnvvars, "PASSENGER_LOAD_SHELL_ENVVARS");
|
1735
1749
|
fillPoolOption(client, options.debugger, "PASSENGER_DEBUGGER");
|
1736
1750
|
fillPoolOption(client, options.raiseInternalError, "PASSENGER_RAISE_INTERNAL_ERROR");
|
1751
|
+
setStickySessionId(client);
|
1752
|
+
/******************/
|
1737
1753
|
|
1738
1754
|
for (it = client->scgiParser.begin(); it != end; it++) {
|
1739
1755
|
if (!startsWith(it->first, "PASSENGER_")
|
@@ -1788,6 +1804,53 @@ private:
|
|
1788
1804
|
}
|
1789
1805
|
}
|
1790
1806
|
|
1807
|
+
void setStickySessionId(const ClientPtr &client) {
|
1808
|
+
ScgiRequestParser &parser = client->scgiParser;
|
1809
|
+
if (parser.getHeader("PASSENGER_STICKY_SESSION") == "true") {
|
1810
|
+
// TODO: This is not entirely correct. Clients MAY send multiple Cookie
|
1811
|
+
// headers, although this is in practice extremely rare.
|
1812
|
+
// http://stackoverflow.com/questions/16305814/are-multiple-cookie-headers-allowed-in-an-http-request
|
1813
|
+
StaticString cookie = parser.getHeader("HTTP_COOKIE");
|
1814
|
+
StaticString cookieName = getStickySessionCookieName(client);
|
1815
|
+
vector<StaticString> parts;
|
1816
|
+
|
1817
|
+
client->stickySession = true;
|
1818
|
+
split(cookie, ';', parts);
|
1819
|
+
foreach (StaticString part, parts) {
|
1820
|
+
const char *begin = part.data();
|
1821
|
+
const char *end = part.data() + part.size();
|
1822
|
+
const char *sep;
|
1823
|
+
|
1824
|
+
// Skip leading whitespace in the name.
|
1825
|
+
while (begin < end && *begin == ' ') {
|
1826
|
+
begin++;
|
1827
|
+
}
|
1828
|
+
part = StaticString(begin, end - begin);
|
1829
|
+
|
1830
|
+
// Find the separator ('=').
|
1831
|
+
sep = (const char *) memchr(begin, '=', end - begin);
|
1832
|
+
if (sep != NULL) {
|
1833
|
+
StaticString name(begin, sep - begin);
|
1834
|
+
if (name == cookieName) {
|
1835
|
+
// This cookie matches the one we're looking for.
|
1836
|
+
StaticString value(sep + 1, end - (sep + 1));
|
1837
|
+
client->options.stickySessionId = stringToUint(value);
|
1838
|
+
return;
|
1839
|
+
}
|
1840
|
+
}
|
1841
|
+
}
|
1842
|
+
}
|
1843
|
+
}
|
1844
|
+
|
1845
|
+
StaticString getStickySessionCookieName(const ClientPtr &client) const {
|
1846
|
+
StaticString value = client->scgiParser.getHeader("PASSENGER_STICKY_SESSION_COOKIE_NAME");
|
1847
|
+
if (value.empty()) {
|
1848
|
+
return StaticString("_passenger_route", sizeof("_passenger_route") - 1);
|
1849
|
+
} else {
|
1850
|
+
return value;
|
1851
|
+
}
|
1852
|
+
}
|
1853
|
+
|
1791
1854
|
size_t state_readingHeader_onClientData(const ClientPtr &client, const char *data, size_t size) {
|
1792
1855
|
ScgiRequestParser &parser = client->scgiParser;
|
1793
1856
|
size_t consumed = parser.feed(data, size);
|
@@ -33,8 +33,10 @@
|
|
33
33
|
|
34
34
|
#include <string>
|
35
35
|
#include <set>
|
36
|
+
// Checking for _PCREPOSIX_H avoids conflicts with headers provided by Apache.
|
37
|
+
// https://code.google.com/p/phusion-passenger/issues/detail?id=651
|
36
38
|
#ifndef _PCREPOSIX_H
|
37
|
-
#include <regex.h>
|
39
|
+
#include <boost/regex.h>
|
38
40
|
#endif
|
39
41
|
#include <cstdio>
|
40
42
|
#include <cstring>
|