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
@@ -49,16 +49,12 @@ private:
|
|
49
49
|
BackgroundIOCapturerPtr stderrCapturer;
|
50
50
|
DebugDirPtr debugDir;
|
51
51
|
const Options *options;
|
52
|
-
bool forwardStderr;
|
53
|
-
int forwardStderrTo;
|
54
52
|
|
55
53
|
/****** Working state ******/
|
56
54
|
unsigned long long timeout;
|
57
55
|
|
58
56
|
StartupDetails() {
|
59
57
|
options = NULL;
|
60
|
-
forwardStderr = false;
|
61
|
-
forwardStderrTo = STDERR_FILENO;
|
62
58
|
timeout = 0;
|
63
59
|
}
|
64
60
|
};
|
@@ -268,13 +264,13 @@ private:
|
|
268
264
|
details.stderrCapturer =
|
269
265
|
make_shared<BackgroundIOCapturer>(
|
270
266
|
errorPipe.first,
|
271
|
-
|
272
|
-
|
267
|
+
pid,
|
268
|
+
// The cast works around a compilation problem in Clang.
|
269
|
+
(const char *) "stderr");
|
273
270
|
details.stderrCapturer->start();
|
274
271
|
details.debugDir = debugDir;
|
275
272
|
details.options = &options;
|
276
273
|
details.timeout = options.startTimeout * 1000;
|
277
|
-
details.forwardStderr = config->forwardStderr;
|
278
274
|
|
279
275
|
{
|
280
276
|
this_thread::restore_interruption ri(di);
|
@@ -290,12 +286,12 @@ private:
|
|
290
286
|
PipeWatcherPtr watcher;
|
291
287
|
|
292
288
|
watcher = boost::make_shared<PipeWatcher>(adminSocket.second,
|
293
|
-
"stdout", pid
|
289
|
+
"stdout", pid);
|
294
290
|
watcher->initialize();
|
295
291
|
watcher->start();
|
296
292
|
|
297
293
|
watcher = boost::make_shared<PipeWatcher>(errorPipe.first,
|
298
|
-
"stderr", pid
|
294
|
+
"stderr", pid);
|
299
295
|
watcher->initialize();
|
300
296
|
watcher->start();
|
301
297
|
|
@@ -777,7 +773,6 @@ public:
|
|
777
773
|
details.adminSocket = result.adminSocket;
|
778
774
|
details.io = result.io;
|
779
775
|
details.options = &options;
|
780
|
-
details.forwardStderr = config->forwardStderr;
|
781
776
|
ProcessPtr process = negotiateSpawn(details);
|
782
777
|
P_DEBUG("Process spawning done: appRoot=" << options.appRoot <<
|
783
778
|
", pid=" << process->pid);
|
@@ -118,8 +118,8 @@ protected:
|
|
118
118
|
class BackgroundIOCapturer {
|
119
119
|
private:
|
120
120
|
FileDescriptor fd;
|
121
|
-
|
122
|
-
|
121
|
+
pid_t pid;
|
122
|
+
const char *channelName;
|
123
123
|
boost::mutex dataSyncher;
|
124
124
|
string data;
|
125
125
|
oxt::thread *thr;
|
@@ -148,16 +148,16 @@ protected:
|
|
148
148
|
data.append(buf, ret);
|
149
149
|
}
|
150
150
|
UPDATE_TRACE_POINT();
|
151
|
-
if (
|
152
|
-
|
153
|
-
} else
|
151
|
+
if (ret == 1 && buf[0] == '\n') {
|
152
|
+
printAppOutput(pid, channelName, "", 0);
|
153
|
+
} else {
|
154
154
|
vector<StaticString> lines;
|
155
155
|
if (ret > 0 && buf[ret - 1] == '\n') {
|
156
156
|
ret--;
|
157
157
|
}
|
158
158
|
split(StaticString(buf, ret), '\n', lines);
|
159
159
|
foreach (const StaticString line, lines) {
|
160
|
-
|
160
|
+
printAppOutput(pid, channelName, line.data(), line.size());
|
161
161
|
}
|
162
162
|
}
|
163
163
|
}
|
@@ -165,10 +165,10 @@ protected:
|
|
165
165
|
}
|
166
166
|
|
167
167
|
public:
|
168
|
-
BackgroundIOCapturer(const FileDescriptor &_fd,
|
168
|
+
BackgroundIOCapturer(const FileDescriptor &_fd, pid_t _pid, const char *_channelName)
|
169
169
|
: fd(_fd),
|
170
|
-
|
171
|
-
|
170
|
+
pid(_pid),
|
171
|
+
channelName(_channelName),
|
172
172
|
thr(NULL)
|
173
173
|
{ }
|
174
174
|
|
@@ -344,8 +344,6 @@ protected:
|
|
344
344
|
FileDescriptor adminSocket;
|
345
345
|
FileDescriptor errorPipe;
|
346
346
|
const Options *options;
|
347
|
-
bool forwardStderr;
|
348
|
-
int forwardStderrTo;
|
349
347
|
DebugDirPtr debugDir;
|
350
348
|
|
351
349
|
/****** Working state ******/
|
@@ -359,8 +357,6 @@ protected:
|
|
359
357
|
preparation = NULL;
|
360
358
|
pid = 0;
|
361
359
|
options = NULL;
|
362
|
-
forwardStderr = false;
|
363
|
-
forwardStderrTo = STDERR_FILENO;
|
364
360
|
spawnStartTime = 0;
|
365
361
|
timeout = 0;
|
366
362
|
}
|
@@ -792,8 +788,7 @@ protected:
|
|
792
788
|
if (details.stderrCapturer != NULL) {
|
793
789
|
details.stderrCapturer->appendToBuffer(result);
|
794
790
|
}
|
795
|
-
|
796
|
-
"[App " << details.pid << " stdout] " << line);
|
791
|
+
printAppOutput(details.pid, "stdout", line.data(), line.size());
|
797
792
|
}
|
798
793
|
}
|
799
794
|
}
|
@@ -192,6 +192,9 @@ private:
|
|
192
192
|
static boost::mutex &getPoolSyncher(const PoolPtr &pool);
|
193
193
|
static void runAllActions(const vector<Callback> &actions);
|
194
194
|
string generateSecret() const;
|
195
|
+
void runInitializationHooks() const;
|
196
|
+
void runDestructionHooks() const;
|
197
|
+
void setupInitializationOrDestructionHook(HookScriptOptions &options) const;
|
195
198
|
|
196
199
|
void createInterruptableThread(const boost::function<void ()> &func, const string &name,
|
197
200
|
unsigned int stackSize);
|
@@ -273,8 +276,8 @@ private:
|
|
273
276
|
}
|
274
277
|
|
275
278
|
while (!group->getWaitlist.empty()) {
|
276
|
-
getWaitlist.
|
277
|
-
group->getWaitlist.
|
279
|
+
getWaitlist.push_back(group->getWaitlist.front());
|
280
|
+
group->getWaitlist.pop_front();
|
278
281
|
}
|
279
282
|
detachedGroups.push_back(group);
|
280
283
|
group->shutdown(
|
@@ -299,7 +302,7 @@ private:
|
|
299
302
|
postLockActions.push_back(boost::bind(
|
300
303
|
waiter.callback, session, ExceptionPtr()));
|
301
304
|
}
|
302
|
-
getWaitlist.
|
305
|
+
getWaitlist.pop_front();
|
303
306
|
}
|
304
307
|
}
|
305
308
|
|
@@ -321,9 +324,7 @@ private:
|
|
321
324
|
void doDestroy(SuperGroupPtr self, unsigned int generation, ShutdownCallback callback) {
|
322
325
|
TRACE_POINT();
|
323
326
|
|
324
|
-
|
325
|
-
// without holding the lock. Note that any destruction
|
326
|
-
// code may not interfere with doInitialize().
|
327
|
+
runDestructionHooks();
|
327
328
|
|
328
329
|
// Wait until 'detachedGroups' is empty.
|
329
330
|
UPDATE_TRACE_POINT();
|
@@ -398,7 +399,7 @@ public:
|
|
398
399
|
* if !getWaitlist.empty():
|
399
400
|
* state == INITIALIZING
|
400
401
|
*/
|
401
|
-
|
402
|
+
deque<GetWaiter> getWaitlist;
|
402
403
|
|
403
404
|
/**
|
404
405
|
* Groups which are being shut down right now. These Groups contain a
|
@@ -575,7 +576,7 @@ public:
|
|
575
576
|
SessionPtr get(const Options &newOptions, const GetCallback &callback) {
|
576
577
|
switch (state) {
|
577
578
|
case INITIALIZING:
|
578
|
-
getWaitlist.
|
579
|
+
getWaitlist.push_back(GetWaiter(newOptions, callback));
|
579
580
|
verifyInvariants();
|
580
581
|
return SessionPtr();
|
581
582
|
case READY:
|
@@ -595,7 +596,7 @@ public:
|
|
595
596
|
}
|
596
597
|
case DESTROYING:
|
597
598
|
case DESTROYED:
|
598
|
-
getWaitlist.
|
599
|
+
getWaitlist.push_back(GetWaiter(newOptions, callback));
|
599
600
|
setState(INITIALIZING);
|
600
601
|
createInterruptableThread(
|
601
602
|
boost::bind(
|
data/ext/common/Constants.h
CHANGED
@@ -48,8 +48,6 @@
|
|
48
48
|
|
49
49
|
#define DEFAULT_LOG_LEVEL 0
|
50
50
|
|
51
|
-
#define DEFAULT_MAX_INSTANCES_PER_APP 0
|
52
|
-
|
53
51
|
#define DEFAULT_MAX_POOL_SIZE 6
|
54
52
|
|
55
53
|
#define DEFAULT_NODEJS "node"
|
@@ -80,7 +78,7 @@
|
|
80
78
|
|
81
79
|
#define NGINX_DOC_URL "http://www.modrails.com/documentation/Users%20guide%20Nginx.html"
|
82
80
|
|
83
|
-
#define PASSENGER_VERSION "4.0.
|
81
|
+
#define PASSENGER_VERSION "4.0.28"
|
84
82
|
|
85
83
|
#define POOL_HELPER_THREAD_STACK_SIZE 262144
|
86
84
|
|
data/ext/common/Hooks.h
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2010-2013 Phusion
|
4
|
+
*
|
5
|
+
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
|
+
*
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
12
|
+
* furnished to do so, subject to the following conditions:
|
13
|
+
*
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
15
|
+
* all copies or substantial portions of the Software.
|
16
|
+
*
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
* THE SOFTWARE.
|
24
|
+
*/
|
25
|
+
#ifndef _PASSENGER_HOOKS_H_
|
26
|
+
#define _PASSENGER_HOOKS_H_
|
27
|
+
|
28
|
+
#include <string>
|
29
|
+
#include <vector>
|
30
|
+
#include <utility>
|
31
|
+
|
32
|
+
#include <oxt/backtrace.hpp>
|
33
|
+
|
34
|
+
#include <sys/types.h>
|
35
|
+
#include <sys/wait.h>
|
36
|
+
#include <cstdio>
|
37
|
+
#include <cerrno>
|
38
|
+
#include <cstring>
|
39
|
+
#include <cctype>
|
40
|
+
#include <stdlib.h>
|
41
|
+
#include <unistd.h>
|
42
|
+
|
43
|
+
#include <Logging.h>
|
44
|
+
#include <Utils.h>
|
45
|
+
#include <Utils/StrIntUtils.h>
|
46
|
+
#include <Utils/VariantMap.h>
|
47
|
+
|
48
|
+
namespace Passenger {
|
49
|
+
|
50
|
+
using namespace std;
|
51
|
+
using namespace oxt;
|
52
|
+
|
53
|
+
|
54
|
+
struct HookScriptOptions {
|
55
|
+
// Required.
|
56
|
+
string name;
|
57
|
+
string spec;
|
58
|
+
|
59
|
+
// Optional.
|
60
|
+
const VariantMap *agentsOptions;
|
61
|
+
vector< pair<string, string> > environment;
|
62
|
+
|
63
|
+
HookScriptOptions()
|
64
|
+
: agentsOptions(NULL)
|
65
|
+
{ }
|
66
|
+
};
|
67
|
+
|
68
|
+
namespace {
|
69
|
+
inline vector< pair<string, string> >
|
70
|
+
agentsOptionsToEnvVars(const VariantMap &agentsOptions) {
|
71
|
+
vector< pair<string, string> > result;
|
72
|
+
VariantMap::ConstIterator it, end = agentsOptions.end();
|
73
|
+
|
74
|
+
result.reserve(agentsOptions.size());
|
75
|
+
for (it = agentsOptions.begin(); it != end; it++) {
|
76
|
+
string key = "PASSENGER_";
|
77
|
+
const char *data = it->first.data();
|
78
|
+
const char *end = it->first.data() + it->first.size();
|
79
|
+
|
80
|
+
while (data < end) {
|
81
|
+
key.append(1, toupper(*data));
|
82
|
+
data++;
|
83
|
+
}
|
84
|
+
result.push_back(make_pair(key, it->second));
|
85
|
+
}
|
86
|
+
|
87
|
+
return result;
|
88
|
+
}
|
89
|
+
|
90
|
+
inline void
|
91
|
+
setEnvVarsFromVector(const vector< pair<string, string> > &envvars) {
|
92
|
+
vector< pair<string, string> >::const_iterator it;
|
93
|
+
|
94
|
+
for (it = envvars.begin(); it != envvars.end(); it++) {
|
95
|
+
setenv(it->first.c_str(), it->second.c_str(), 1);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
inline void
|
100
|
+
createHookScriptEnvironment(const HookScriptOptions &options, vector< pair<string, string> > &envvars) {
|
101
|
+
vector< pair<string, string> >::const_iterator it, end = options.environment.end();
|
102
|
+
if (options.agentsOptions) {
|
103
|
+
envvars = agentsOptionsToEnvVars(*options.agentsOptions);
|
104
|
+
}
|
105
|
+
for (it = options.environment.begin(); it != end; it++) {
|
106
|
+
envvars.push_back(*it);
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
inline void
|
111
|
+
parseHookScriptSpec(const HookScriptOptions &options, vector<string> &commands) {
|
112
|
+
split(options.spec, ';', commands);
|
113
|
+
|
114
|
+
vector<string>::iterator it, end = commands.end();
|
115
|
+
for (it = commands.begin(); it != end; it++) {
|
116
|
+
*it = strip(*it);
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
inline bool
|
122
|
+
runSingleHookScript(HookScriptOptions &options, const string &command,
|
123
|
+
const vector< pair<string, string> > &envvars)
|
124
|
+
{
|
125
|
+
TRACE_POINT_WITH_DATA(command.c_str());
|
126
|
+
pid_t pid;
|
127
|
+
int e, status;
|
128
|
+
|
129
|
+
P_INFO("Running " << options.name << " hook script: " << command);
|
130
|
+
|
131
|
+
pid = fork();
|
132
|
+
if (pid == 0) {
|
133
|
+
resetSignalHandlersAndMask();
|
134
|
+
disableMallocDebugging();
|
135
|
+
closeAllFileDescriptors(2);
|
136
|
+
setEnvVarsFromVector(envvars);
|
137
|
+
|
138
|
+
execlp(command.c_str(), command.c_str(), (const char * const) 0);
|
139
|
+
e = errno;
|
140
|
+
fprintf(stderr, "*** ERROR: Cannot execute %s hook script %s: %s (errno=%d)\n",
|
141
|
+
options.name.c_str(), command.c_str(), strerror(e), e);
|
142
|
+
fflush(stderr);
|
143
|
+
_exit(1);
|
144
|
+
return true; // Never reached.
|
145
|
+
|
146
|
+
} else if (pid == -1) {
|
147
|
+
e = errno;
|
148
|
+
P_ERROR("Cannot fork a process for hook script " << command <<
|
149
|
+
": " << strerror(e) << " (errno=" << e << ")");
|
150
|
+
return false;
|
151
|
+
|
152
|
+
} else if (waitpid(pid, &status, 0) == -1) {
|
153
|
+
e = errno;
|
154
|
+
P_ERROR("Unable to wait for hook script " << command <<
|
155
|
+
" (PID " << pid << "): " << strerror(e) << " (errno=" <<
|
156
|
+
e << ")");
|
157
|
+
return false;
|
158
|
+
|
159
|
+
} else {
|
160
|
+
P_INFO("Hook script " << command << " (PID " << pid <<
|
161
|
+
") exited with status " << WEXITSTATUS(status));
|
162
|
+
return WEXITSTATUS(status) == 0;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
inline bool
|
167
|
+
runHookScripts(HookScriptOptions &options) {
|
168
|
+
TRACE_POINT();
|
169
|
+
if (options.spec.empty()) {
|
170
|
+
return true;
|
171
|
+
}
|
172
|
+
|
173
|
+
vector<string> commands;
|
174
|
+
vector< pair<string, string> > envvars;
|
175
|
+
|
176
|
+
parseHookScriptSpec(options, commands);
|
177
|
+
if (commands.empty()) {
|
178
|
+
return true;
|
179
|
+
}
|
180
|
+
createHookScriptEnvironment(options, envvars);
|
181
|
+
|
182
|
+
foreach (const string command, commands) {
|
183
|
+
if (!runSingleHookScript(options, command, envvars)) {
|
184
|
+
return false;
|
185
|
+
}
|
186
|
+
}
|
187
|
+
return true;
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
} // namespace Passenger
|
192
|
+
|
193
|
+
#endif /* _PASSENGER_HOOKS_H_ */
|
data/ext/common/Logging.cpp
CHANGED
@@ -27,6 +27,7 @@
|
|
27
27
|
#include <fcntl.h>
|
28
28
|
#include <unistd.h>
|
29
29
|
#include <Logging.h>
|
30
|
+
#include <StaticString.h>
|
30
31
|
#include <Utils/StrIntUtils.h>
|
31
32
|
#include <Utils/IOUtils.h>
|
32
33
|
|
@@ -34,6 +35,7 @@ namespace Passenger {
|
|
34
35
|
|
35
36
|
int _logLevel = 0;
|
36
37
|
int _logOutput = STDERR_FILENO;
|
38
|
+
static bool printAppOutputAsDebuggingMessages = false;
|
37
39
|
|
38
40
|
int
|
39
41
|
getLogLevel() {
|
@@ -86,8 +88,8 @@ _prepareLogEntry(std::stringstream &sstream, const char *file, unsigned int line
|
|
86
88
|
" ]: ";
|
87
89
|
}
|
88
90
|
|
89
|
-
void
|
90
|
-
_writeLogEntry(const
|
91
|
+
static void
|
92
|
+
_writeLogEntry(const StaticString &str) {
|
91
93
|
try {
|
92
94
|
writeExact(_logOutput, str.data(), str.size());
|
93
95
|
} catch (const SystemException &) {
|
@@ -101,5 +103,68 @@ _writeLogEntry(const std::string &str) {
|
|
101
103
|
}
|
102
104
|
}
|
103
105
|
|
106
|
+
void
|
107
|
+
_writeLogEntry(const std::string &str) {
|
108
|
+
_writeLogEntry(StaticString(str));
|
109
|
+
}
|
110
|
+
|
111
|
+
static void
|
112
|
+
realPrintAppOutput(char *buf, unsigned int bufSize,
|
113
|
+
const char *pidStr, unsigned int pidStrLen,
|
114
|
+
const char *channelName, unsigned int channelNameLen,
|
115
|
+
const char *message, unsigned int messageLen)
|
116
|
+
{
|
117
|
+
char *pos = buf;
|
118
|
+
char *end = buf + bufSize;
|
119
|
+
|
120
|
+
pos = appendData(pos, end, "App ");
|
121
|
+
pos = appendData(pos, end, pidStr, pidStrLen);
|
122
|
+
pos = appendData(pos, end, " ");
|
123
|
+
pos = appendData(pos, end, channelName, channelNameLen);
|
124
|
+
pos = appendData(pos, end, ": ");
|
125
|
+
pos = appendData(pos, end, message, messageLen);
|
126
|
+
pos = appendData(pos, end, "\n");
|
127
|
+
_writeLogEntry(StaticString(buf, pos - buf));
|
128
|
+
}
|
129
|
+
|
130
|
+
void
|
131
|
+
printAppOutput(pid_t pid, const char *channelName, const char *message, unsigned int size) {
|
132
|
+
if (printAppOutputAsDebuggingMessages) {
|
133
|
+
P_DEBUG("App " << pid << " " << channelName << ": " << StaticString(message, size));
|
134
|
+
} else {
|
135
|
+
char pidStr[sizeof("4294967295")];
|
136
|
+
unsigned int pidStrLen, channelNameLen, totalLen;
|
137
|
+
|
138
|
+
try {
|
139
|
+
pidStrLen = integerToOtherBase<pid_t, 10>(pid, pidStr, sizeof(pidStr));
|
140
|
+
} catch (const std::length_error &) {
|
141
|
+
pidStr[0] = '?';
|
142
|
+
pidStr[1] = '\0';
|
143
|
+
pidStrLen = 1;
|
144
|
+
}
|
145
|
+
|
146
|
+
channelNameLen = strlen(channelName);
|
147
|
+
totalLen = (sizeof("App X Y: \n") - 2) + pidStrLen + channelNameLen + size;
|
148
|
+
if (totalLen < 1024) {
|
149
|
+
char buf[1024];
|
150
|
+
realPrintAppOutput(buf, sizeof(buf),
|
151
|
+
pidStr, pidStrLen,
|
152
|
+
channelName, channelNameLen,
|
153
|
+
message, size);
|
154
|
+
} else {
|
155
|
+
DynamicBuffer buf(totalLen);
|
156
|
+
realPrintAppOutput(buf.data, totalLen,
|
157
|
+
pidStr, pidStrLen,
|
158
|
+
channelName, channelNameLen,
|
159
|
+
message, size);
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
void
|
165
|
+
setPrintAppOutputAsDebuggingMessages(bool enabled) {
|
166
|
+
printAppOutputAsDebuggingMessages = enabled;
|
167
|
+
}
|
168
|
+
|
104
169
|
} // namespace Passenger
|
105
170
|
|