passenger 5.1.11 → 5.1.12
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 +4 -4
- data/.editorconfig +8 -0
- data/CHANGELOG +17 -0
- data/CONTRIBUTING.md +2 -2
- data/build/support/cxx_dependency_map.rb +1 -0
- data/dev/ci/tests/debian/Jenkinsfile +90 -0
- data/dev/ci/tests/debian/run +60 -0
- data/resources/templates/standalone/server.erb +1 -0
- data/src/agent/Core/ApplicationPool/Session.h +1 -1
- data/src/agent/Core/ApplicationPool/Socket.h +1 -1
- data/src/agent/Core/Controller/InitRequest.cpp +1 -1
- data/src/agent/Core/SecurityUpdateChecker.h +1 -1
- data/src/agent/Shared/ApiServerUtils.h +7 -1
- data/src/agent/Shared/Fundamentals/Initialization.cpp +5 -2
- data/src/apache2_module/Hooks.cpp +25 -0
- data/src/cxx_supportlib/ConfigKit/Schema.h +2 -0
- data/src/cxx_supportlib/Constants.h +1 -1
- data/src/cxx_supportlib/InstanceDirectory.h +2 -0
- data/src/cxx_supportlib/LoggingKit/Implementation.cpp +53 -22
- data/src/cxx_supportlib/WatchdogLauncher.h +2 -1
- data/src/nginx_module/ngx_http_passenger_module.c +78 -38
- data/src/ruby_supportlib/phusion_passenger.rb +8 -8
- data/src/ruby_supportlib/phusion_passenger/platform_info.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/standalone/config_utils.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0ca744c34e7b85ec574e802d3d5f51ba0e65ba4
|
4
|
+
data.tar.gz: f886554ad447e878969606ef9bf7facb430d9467
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bf8a6e154ee6fe1128ee388e716bcd297d60ab84976c3969741d48cff84864276561759a52e7af2e2f23ef8ce9b0b93d82b1ae08fd1c9fee7113560f06f0552
|
7
|
+
data.tar.gz: 43e60afd9fb51149dcdaefb513d3d8ee6b9237828313d25bd9ca1f9cbde1c22ab26fa426ce49858b3e827734f3fe2cde654901bd8bd488fa4b1f8c8379a7b9d8
|
data/.editorconfig
CHANGED
@@ -90,6 +90,14 @@ indent_size = 4
|
|
90
90
|
indent_style = space
|
91
91
|
indent_size = 4
|
92
92
|
|
93
|
+
[src/nginx_module/*/*.c]
|
94
|
+
indent_style = space
|
95
|
+
indent_size = 4
|
96
|
+
|
97
|
+
[src/nginx_module/*/*.h]
|
98
|
+
indent_style = space
|
99
|
+
indent_size = 4
|
100
|
+
|
93
101
|
[src/cxx_supportlib/vendor-modified/libev/*.c]
|
94
102
|
indent_style = space
|
95
103
|
indent_size = 2
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
Release 5.1.12
|
2
|
+
---------------------------------
|
3
|
+
|
4
|
+
* Changes the Debian/Ubuntu install script to completely restart Apache upon upgrade. This prevents issues due to a "half upgraded" state (old Passenger Apache module + new Passenger core). Closes GH-2000.
|
5
|
+
* Adds Ubuntu 17.10 "Artful" packages.
|
6
|
+
* Fixes a case in which -- when Passenger is configured with user switching turned off -- it is unable to open the web server log file and aborts during startup. This regression was introduced in 5.1.8. Closes GH-1990.
|
7
|
+
* [Nginx] The preferred Nginx version is now 1.12.2
|
8
|
+
* [Nginx] The preferred PCRE version is now 8.41 (previously 8.39).
|
9
|
+
* [Standalone] Adds support for using `start_timeout` in Passengerfile.json.
|
10
|
+
* [Enterprise] Uses libuv to detect total system RAM, allows for compilation on pre-10.11 macOS.
|
11
|
+
* [Enterprise] Added a max request queue time option, to limit time requests spend in the request queue. Closes GH-1688.
|
12
|
+
* Updated libcurl version used in precompiled binaries (used for e.g. gem installs) to 7.56.1 (was: 7.54.1).
|
13
|
+
* Updated OpenSSL version used in precompiled binaries (used for e.g. gem installs) to 1.0.2m (was: 1.0.2l).
|
14
|
+
* Updated PCRE version used in precompiled binaries (used for e.g. gem installs) to 8.41 (was: 8.40).
|
15
|
+
* Updated Ruby versions used in precompiled binaries (used for e.g. gem installs) to include 2.1.10, 2.2.8, 2.3.5, and 2.4.2 (removed: 2.1.9, 2.2.7, 2.3.4, and 2.4.1).
|
16
|
+
|
17
|
+
|
1
18
|
Release 5.1.11
|
2
19
|
--------------
|
3
20
|
|
data/CONTRIBUTING.md
CHANGED
@@ -54,7 +54,7 @@ When filing a bug report, please ensure that you include the following informati
|
|
54
54
|
<a name="contrib_docs"></a>
|
55
55
|
## Contributing documentation
|
56
56
|
|
57
|
-
All good software should have good documentation, and we take this very seriously. However writing and
|
57
|
+
All good software should have good documentation, and we take this very seriously. However writing and maintaining quality documentation is not an easy task. If you are not skilled in C++ or programming, then writing documentation is the easiest way to contribute.
|
58
58
|
|
59
59
|
Most documentation can be located in the `doc` directory, and are either written in Markdown or in Asciidoc format. They can be compiled to HTML with `rake doc`. You need [Mizuho](https://github.com/FooBarWidget/mizuho) to compile Asciidoc and [BlueCloth](http://deveiate.org/projects/BlueCloth) to compile Markdown. Both gems are automatically installed as part of the Phusion Passenger developer tools.
|
60
60
|
|
@@ -278,7 +278,7 @@ Less important directories:
|
|
278
278
|
|
279
279
|
foo (1, 2, 3);
|
280
280
|
|
281
|
-
*
|
281
|
+
* Separate arguments and parts of expressions by spaces:
|
282
282
|
|
283
283
|
foo(1, 2, foo == bar, 5 + 6);
|
284
284
|
if (foo && bar) {
|
@@ -6683,6 +6683,7 @@ CXX_DEPENDENCY_MAP =
|
|
6683
6683
|
"src/cxx_supportlib/Utils/IOUtils.h",
|
6684
6684
|
"src/cxx_supportlib/Utils/LargeFiles.h",
|
6685
6685
|
"src/cxx_supportlib/Utils/StrIntUtils.h",
|
6686
|
+
"src/cxx_supportlib/Utils/SystemTime.h",
|
6686
6687
|
"src/cxx_supportlib/oxt/backtrace.hpp",
|
6687
6688
|
"src/cxx_supportlib/oxt/detail/backtrace_disabled.hpp",
|
6688
6689
|
"src/cxx_supportlib/oxt/detail/backtrace_enabled.hpp",
|
@@ -0,0 +1,90 @@
|
|
1
|
+
def getDefaultDistros() {
|
2
|
+
def distroInfo = readFile("packaging/debian/internal/lib/distro_info.sh")
|
3
|
+
def matcher = distroInfo =~ /DEFAULT_DISTROS="(.+?)"/
|
4
|
+
if (matcher.find()) {
|
5
|
+
matcher.group(1).split().sort()
|
6
|
+
} else {
|
7
|
+
error("Unable to parse packaging/debian/internal/lib/distro_info.sh")
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
def testDebianPackages(distro, params) {
|
12
|
+
if ((!distro in params) || params[distro]) {
|
13
|
+
node('linux') {
|
14
|
+
def env = [
|
15
|
+
"CACHE_DIR=${env.JENKINS_HOME}/cache/${env.JOB_NAME}/${distro}",
|
16
|
+
"DISTRIBUTION=${distro}",
|
17
|
+
"ARCHITECTURE=amd64"
|
18
|
+
]
|
19
|
+
withEnv(env) {
|
20
|
+
checkout scm
|
21
|
+
sh './dev/ci/tests/debian/run'
|
22
|
+
}
|
23
|
+
}
|
24
|
+
} else {
|
25
|
+
echo 'Test skipped.'
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
pipeline {
|
30
|
+
agent any
|
31
|
+
|
32
|
+
options {
|
33
|
+
buildDiscarder(logRotator(numToKeepStr: '10'))
|
34
|
+
timeout(time: 45, unit: 'MINUTES')
|
35
|
+
disableConcurrentBuilds()
|
36
|
+
timestamps()
|
37
|
+
ansiColor('xterm')
|
38
|
+
}
|
39
|
+
|
40
|
+
parameters {
|
41
|
+
booleanParam(name: 'trusty', defaultValue: true, description: 'Test Ubuntu 14.04 packages')
|
42
|
+
booleanParam(name: 'xenial', defaultValue: true, description: 'Test Ubuntu 16.04 packages')
|
43
|
+
booleanParam(name: 'zesty', defaultValue: true, description: 'Test Ubuntu 17.04 packages')
|
44
|
+
booleanParam(name: 'artful', defaultValue: true, description: 'Test Ubuntu 17.10 packages')
|
45
|
+
|
46
|
+
booleanParam(name: 'wheezy', defaultValue: true, description: 'Test Debian 7 packages')
|
47
|
+
booleanParam(name: 'jessie', defaultValue: true, description: 'Test Debian 8 packages')
|
48
|
+
booleanParam(name: 'stretch', defaultValue: true, description: 'Test Debian 9 packages')
|
49
|
+
}
|
50
|
+
|
51
|
+
stages {
|
52
|
+
stage('Initialize') {
|
53
|
+
steps {
|
54
|
+
script {
|
55
|
+
if (env.JOB_NAME.indexOf('Enterprise') != -1) {
|
56
|
+
env.ENTERPRISE = '1'
|
57
|
+
} else {
|
58
|
+
env.ENTERPRISE = '0'
|
59
|
+
}
|
60
|
+
|
61
|
+
// For debugging purposes
|
62
|
+
sh 'env | sort'
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
stage('Test') {
|
70
|
+
steps {
|
71
|
+
script {
|
72
|
+
def defaultDistros = getDefaultDistros()
|
73
|
+
def i
|
74
|
+
def parallelSteps = [:]
|
75
|
+
|
76
|
+
// We use a plain loop over .each because of this bug:
|
77
|
+
// https://issues.jenkins-ci.org/browse/JENKINS-27421
|
78
|
+
for (i = 0; i < defaultDistros.length; i++) {
|
79
|
+
def distro = defaultDistros[i]
|
80
|
+
parallelSteps[distro] = {
|
81
|
+
testDebianPackages(distro, params)
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
parallel(parallelSteps)
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# This script is from the "Passenger Debian packaging test" Jenkins job. It builds
|
3
|
+
# packages for a specific distribution and architecture and runs tests on the resulting packages.
|
4
|
+
#
|
5
|
+
# Required environment variables:
|
6
|
+
#
|
7
|
+
# WORKSPACE
|
8
|
+
# DISTRIBUTION
|
9
|
+
# ARCHITECTURE
|
10
|
+
#
|
11
|
+
# Optional environment variables:
|
12
|
+
#
|
13
|
+
# PASSENGER_ROOT (defaults to $WORKSPACE)
|
14
|
+
# CACHE_DIR (defaults to $WORKSPACE/cache)
|
15
|
+
# ENTERPRISE
|
16
|
+
# DEBUG_CONSOLE
|
17
|
+
#
|
18
|
+
# Sample invocation in Vagrant dev environment:
|
19
|
+
#
|
20
|
+
# env WORKSPACE=$HOME DISTRIBUTION=el7 ARCHITECTURE=x86_64 PASSENGER_ROOT=/passenger ./dev/ci/debian/run
|
21
|
+
|
22
|
+
set -e
|
23
|
+
SELFDIR=$(dirname "$0")
|
24
|
+
cd "$SELFDIR/../../../../packaging/debian"
|
25
|
+
# shellcheck source=../../../../packaging/debian/internal/lib/library.sh
|
26
|
+
source "./internal/lib/library.sh"
|
27
|
+
|
28
|
+
require_envvar WORKSPACE "$WORKSPACE"
|
29
|
+
require_envvar DISTRIBUTION "$DISTRIBUTION"
|
30
|
+
require_envvar ARCHITECTURE "$ARCHITECTURE"
|
31
|
+
|
32
|
+
PASSENGER_ROOT="${PASSENGER_ROOT:-$WORKSPACE}"
|
33
|
+
CACHE_DIR="${CACHE_DIR:-$WORKSPACE/cache}"
|
34
|
+
|
35
|
+
if [[ "$DEBUG_CONSOLE" = true ]]; then
|
36
|
+
EXTRA_TEST_PARAMS=-D
|
37
|
+
else
|
38
|
+
EXTRA_TEST_PARAMS=
|
39
|
+
fi
|
40
|
+
if [[ "$ENTERPRISE" = 1 ]]; then
|
41
|
+
EXTRA_TEST_PARAMS="$EXTRA_TEST_PARAMS -e /etc/passenger-enterprise-license"
|
42
|
+
fi
|
43
|
+
|
44
|
+
run mkdir -p "$CACHE_DIR"
|
45
|
+
run ./build \
|
46
|
+
-w "$WORKSPACE/work" \
|
47
|
+
-c "$CACHE_DIR" \
|
48
|
+
-o "$WORKSPACE/output" \
|
49
|
+
-p "$PASSENGER_ROOT" \
|
50
|
+
-d "$DISTRIBUTION" \
|
51
|
+
-a "$ARCHITECTURE" \
|
52
|
+
-R \
|
53
|
+
pkg:all
|
54
|
+
run ./test \
|
55
|
+
-p "$PASSENGER_ROOT" \
|
56
|
+
-d "$WORKSPACE/output/$DISTRIBUTION" \
|
57
|
+
-c "$CACHE_DIR" \
|
58
|
+
-x "$DISTRIBUTION" \
|
59
|
+
-j \
|
60
|
+
$EXTRA_TEST_PARAMS
|
@@ -41,6 +41,7 @@ passenger_enabled on;
|
|
41
41
|
<%= nginx_option(app, :spawn_method) %>
|
42
42
|
<%= nginx_option(app, :app_type) %>
|
43
43
|
<%= nginx_option(app, :startup_file) %>
|
44
|
+
<%= nginx_option(app, :start_timeout) %>
|
44
45
|
<%= nginx_option(app, :min_instances) %>
|
45
46
|
<%= nginx_option(app, :max_request_queue_size) %>
|
46
47
|
<%= nginx_option(app, :restart_dir) %>
|
@@ -206,7 +206,7 @@ public:
|
|
206
206
|
}
|
207
207
|
|
208
208
|
/**
|
209
|
-
* This Session object becomes fully
|
209
|
+
* This Session object becomes fully unusable after closing.
|
210
210
|
*/
|
211
211
|
virtual void close(bool success, bool wantKeepAlive = false) {
|
212
212
|
if (OXT_LIKELY(initiated())) {
|
@@ -172,7 +172,7 @@ Controller::initializePoolOptions(Client *client, Request *req, RequestAnalysis
|
|
172
172
|
req->envvars->size);
|
173
173
|
}
|
174
174
|
|
175
|
-
// Allow certain options to be
|
175
|
+
// Allow certain options to be overridden on a per-request basis
|
176
176
|
fillPoolOption(req, req->options.maxRequests, PASSENGER_MAX_REQUESTS);
|
177
177
|
}
|
178
178
|
}
|
@@ -151,7 +151,7 @@ private:
|
|
151
151
|
// A problem occurred somewhere in the SSL/TLS handshake. Not sure what's up, but in this case the
|
152
152
|
// error buffer (printed in DEBUG) should pinpoint the problem slightly more.
|
153
153
|
case CURLE_OPERATION_TIMEDOUT:
|
154
|
-
// This is not a normal connect timeout, there are some refs to it
|
154
|
+
// This is not a normal connect timeout, there are some refs to it occurring while downloading large
|
155
155
|
// files, but we don't do that so fall through to default.
|
156
156
|
default:
|
157
157
|
error.append(" while connecting to " CHECK_URL_DEFAULT " " +
|
@@ -784,7 +784,12 @@ apiServerProcessReopenLogs(Server *server, Client *client, Request *req) {
|
|
784
784
|
vector<ConfigKit::Error> errors;
|
785
785
|
bool ok;
|
786
786
|
try {
|
787
|
-
|
787
|
+
// We deliberately ignore the target.stderr key.
|
788
|
+
// If the log file was equal to stderr then we'll want
|
789
|
+
// to reopen the log file anyway.
|
790
|
+
Json::Value updates;
|
791
|
+
updates["target"] = config["target"]["path"];
|
792
|
+
ok = LoggingKit::context->prepareConfigChange(updates,
|
788
793
|
errors, configReq);
|
789
794
|
} catch (const SystemException &e) {
|
790
795
|
unsigned int bufsize = 2048;
|
@@ -867,6 +872,7 @@ _apiServerProcessReinheritLogsResponseBody(
|
|
867
872
|
|
868
873
|
config["target"] = oldConfig["target"];
|
869
874
|
config["target"]["fd"] = fd;
|
875
|
+
config["target"].removeMember("stderr");
|
870
876
|
try {
|
871
877
|
ok = LoggingKit::context->prepareConfigChange(config,
|
872
878
|
errors, configReq);
|
@@ -445,9 +445,12 @@ initializeLoggingKit(const char *processName, VariantMap &options) {
|
|
445
445
|
config["level"] = options.get("log_level");
|
446
446
|
|
447
447
|
if (options.has("log_file")) {
|
448
|
-
config["target"] = options.get("log_file");
|
448
|
+
config["target"]["path"] = options.get("log_file");
|
449
449
|
} else if (options.has("debug_log_file")) {
|
450
|
-
config["target"] = options.get("debug_log_file");
|
450
|
+
config["target"]["path"] = options.get("debug_log_file");
|
451
|
+
}
|
452
|
+
if (options.getBool("log_file_is_stderr", false, false)) {
|
453
|
+
config["target"]["stderr"] = true;
|
451
454
|
}
|
452
455
|
|
453
456
|
if (options.has("file_descriptor_log_file")) {
|
@@ -42,8 +42,10 @@
|
|
42
42
|
|
43
43
|
#include <sys/time.h>
|
44
44
|
#include <sys/resource.h>
|
45
|
+
#include <sys/stat.h>
|
45
46
|
#include <exception>
|
46
47
|
#include <cstdio>
|
48
|
+
#include <fcntl.h>
|
47
49
|
#include <unistd.h>
|
48
50
|
|
49
51
|
#include <oxt/initialize.hpp>
|
@@ -358,6 +360,27 @@ private:
|
|
358
360
|
return m_hasModXsendfile == YES;
|
359
361
|
}
|
360
362
|
|
363
|
+
static bool stderrEqualsFile(const char *path) {
|
364
|
+
struct stat s1, s2;
|
365
|
+
|
366
|
+
if (fstat(STDERR_FILENO, &s1) == -1) {
|
367
|
+
return false;
|
368
|
+
}
|
369
|
+
|
370
|
+
// No O_CREAT: we don't care if the file does not exist.
|
371
|
+
int fd = open(path, O_WRONLY | O_APPEND, 0600);
|
372
|
+
if (fd == -1) {
|
373
|
+
return false;
|
374
|
+
}
|
375
|
+
if (fstat(fd, &s2) == -1) {
|
376
|
+
close(fd);
|
377
|
+
return false;
|
378
|
+
}
|
379
|
+
close(fd);
|
380
|
+
|
381
|
+
return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino && s1.st_rdev == s2.st_rdev;
|
382
|
+
}
|
383
|
+
|
361
384
|
int reportBusyException(request_rec *r) {
|
362
385
|
ap_custom_response(r, HTTP_SERVICE_UNAVAILABLE,
|
363
386
|
"This website is too busy right now. Please try again later.");
|
@@ -1347,6 +1370,8 @@ public:
|
|
1347
1370
|
" with an explicit log file using the `PassengerLogFile` directive.");
|
1348
1371
|
} else {
|
1349
1372
|
params.set("log_file", ap_server_root_relative(pconf, s->error_fname));
|
1373
|
+
params.setBool("log_file_is_stderr", stderrEqualsFile(
|
1374
|
+
ap_server_root_relative(pconf, s->error_fname)));
|
1350
1375
|
}
|
1351
1376
|
|
1352
1377
|
serverConfig.ctl.addTo(params);
|
@@ -82,7 +82,7 @@
|
|
82
82
|
#define PASSENGER_API_VERSION_MAJOR 0
|
83
83
|
#define PASSENGER_API_VERSION_MINOR 3
|
84
84
|
#define PASSENGER_DEFAULT_USER "nobody"
|
85
|
-
#define PASSENGER_VERSION "5.1.
|
85
|
+
#define PASSENGER_VERSION "5.1.12"
|
86
86
|
#define POOL_HELPER_THREAD_STACK_SIZE 262144
|
87
87
|
#define PROCESS_SHUTDOWN_TIMEOUT 60
|
88
88
|
#define PROCESS_SHUTDOWN_TIMEOUT_DISPLAY "1 minute"
|
@@ -43,6 +43,7 @@
|
|
43
43
|
#include <RandomGenerator.h>
|
44
44
|
#include <Utils.h>
|
45
45
|
#include <Utils/IOUtils.h>
|
46
|
+
#include <Utils/SystemTime.h>
|
46
47
|
#include <jsoncpp/json.h>
|
47
48
|
|
48
49
|
namespace Passenger {
|
@@ -220,6 +221,7 @@ private:
|
|
220
221
|
props["instance_dir"]["major_version"] = SERVER_INSTANCE_DIR_STRUCTURE_MAJOR_VERSION;
|
221
222
|
props["instance_dir"]["minor_version"] = SERVER_INSTANCE_DIR_STRUCTURE_MINOR_VERSION;
|
222
223
|
props["instance_dir"]["created_at"] = (Json::Int64) time(NULL);
|
224
|
+
props["instance_dir"]["created_at_monotonic_usec"] = (Json::UInt64) SystemTime::getMonotonicUsec();
|
223
225
|
props["passenger_version"] = PASSENGER_VERSION;
|
224
226
|
props["watchdog_pid"] = (Json::UInt64) getpid();
|
225
227
|
|
@@ -577,18 +577,24 @@ Schema::validateTarget(const string &key, const ConfigKit::Store &store,
|
|
577
577
|
return;
|
578
578
|
}
|
579
579
|
|
580
|
+
// Allowed formats:
|
581
|
+
// "/path-to-file"
|
582
|
+
// { "stderr": true }
|
583
|
+
// { "path": "/path" }
|
584
|
+
// { "path": "/path", "fd": 123 }
|
585
|
+
// { "path": "/path", "stderr": true }
|
586
|
+
|
580
587
|
if (value.isObject()) {
|
581
588
|
if (value.isMember("stderr")) {
|
582
|
-
if (value.
|
583
|
-
errors.push_back(Error("When " + keyQuote
|
584
|
-
+ " is an object containing the 'stderr' key,"
|
585
|
-
" it may not contain any other keys"));
|
586
|
-
} else if (!value["stderr"].asBool()) {
|
589
|
+
if (!value["stderr"].isBool() || !value["stderr"].asBool()) {
|
587
590
|
errors.push_back(Error("When " + keyQuote
|
588
591
|
+ " is an object containing the 'stderr' key,"
|
589
592
|
" it must have the 'true' value"));
|
593
|
+
return;
|
590
594
|
}
|
591
|
-
}
|
595
|
+
}
|
596
|
+
|
597
|
+
if (value.isMember("path")) {
|
592
598
|
if (!value["path"].isString()) {
|
593
599
|
errors.push_back(Error("When " + keyQuote
|
594
600
|
+ " is an object containing the 'path' key,"
|
@@ -605,6 +611,21 @@ Schema::validateTarget(const string &key, const ConfigKit::Store &store,
|
|
605
611
|
" it must be 0 or greater"));
|
606
612
|
}
|
607
613
|
}
|
614
|
+
if (value.isMember("fd") && value.isMember("stderr")) {
|
615
|
+
errors.push_back(Error(keyQuote
|
616
|
+
+ " may contain either the 'fd' or the"
|
617
|
+
" 'stderr' key, but not both"));
|
618
|
+
}
|
619
|
+
} else if (value.isMember("stderr")) {
|
620
|
+
if (value.size() > 1) {
|
621
|
+
errors.push_back(Error("When " + keyQuote
|
622
|
+
+ " is an object containing the 'stderr' key,"
|
623
|
+
" it may not contain any other keys"));
|
624
|
+
} else if (!value["stderr"].asBool()) {
|
625
|
+
errors.push_back(Error("When " + keyQuote
|
626
|
+
+ " is an object containing the 'stderr' key,"
|
627
|
+
" it must have the 'true' value"));
|
628
|
+
}
|
608
629
|
} else {
|
609
630
|
errors.push_back(Error("When " + keyQuote
|
610
631
|
+ " is an object, it must contain either"
|
@@ -661,15 +682,20 @@ ConfigRealization::ConfigRealization(const ConfigKit::Store &store)
|
|
661
682
|
} else if (store["target"]["fd"].isNull()) {
|
662
683
|
string path = store["target"]["path"].asString();
|
663
684
|
targetType = FILE_TARGET;
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
685
|
+
if (store["target"]["stderr"].asBool()) {
|
686
|
+
targetFd = STDERR_FILENO;
|
687
|
+
targetFdClosePolicy = NEVER_CLOSE;
|
688
|
+
} else {
|
689
|
+
targetFd = syscalls::open(path.c_str(),
|
690
|
+
O_WRONLY | O_APPEND | O_CREAT, 0644);
|
691
|
+
if (targetFd == -1) {
|
692
|
+
int e = errno;
|
693
|
+
throw FileSystemException(
|
694
|
+
"Cannot open " + path + " for writing",
|
695
|
+
e, path);
|
696
|
+
}
|
697
|
+
targetFdClosePolicy = ALWAYS_CLOSE;
|
671
698
|
}
|
672
|
-
targetFdClosePolicy = ALWAYS_CLOSE;
|
673
699
|
} else {
|
674
700
|
targetType = FILE_TARGET;
|
675
701
|
targetFd = store["target"]["fd"].asInt();
|
@@ -690,15 +716,20 @@ ConfigRealization::ConfigRealization(const ConfigKit::Store &store)
|
|
690
716
|
} else if (store["file_descriptor_log_target"]["fd"].isNull()) {
|
691
717
|
string path = store["file_descriptor_log_target"]["path"].asString();
|
692
718
|
fileDescriptorLogTargetType = FILE_TARGET;
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
719
|
+
if (store["file_descriptor_log_target"]["stderr"].asBool()) {
|
720
|
+
fileDescriptorLogTargetFd = STDERR_FILENO;
|
721
|
+
fileDescriptorLogTargetFdClosePolicy = NEVER_CLOSE;
|
722
|
+
} else {
|
723
|
+
fileDescriptorLogTargetFd = syscalls::open(path.c_str(),
|
724
|
+
O_WRONLY | O_APPEND | O_CREAT, 0644);
|
725
|
+
if (fileDescriptorLogTargetFd == -1) {
|
726
|
+
int e = errno;
|
727
|
+
throw FileSystemException(
|
728
|
+
"Cannot open " + path + " for writing",
|
729
|
+
e, path);
|
730
|
+
}
|
731
|
+
fileDescriptorLogTargetFdClosePolicy = ALWAYS_CLOSE;
|
700
732
|
}
|
701
|
-
fileDescriptorLogTargetFdClosePolicy = ALWAYS_CLOSE;
|
702
733
|
} else {
|
703
734
|
fileDescriptorLogTargetType = FILE_TARGET;
|
704
735
|
fileDescriptorLogTargetFd = store["file_descriptor_log_target"]["fd"].asInt();
|
@@ -390,7 +390,6 @@ public:
|
|
390
390
|
// except stdin, stdout, stderr and 3.
|
391
391
|
close(fds[0]);
|
392
392
|
installFeedbackFd(fds[1]);
|
393
|
-
closeAllFileDescriptors(FEEDBACK_FD);
|
394
393
|
|
395
394
|
setenv("PASSENGER_USE_FEEDBACK_FD", "true", 1);
|
396
395
|
|
@@ -398,6 +397,8 @@ public:
|
|
398
397
|
afterFork();
|
399
398
|
}
|
400
399
|
|
400
|
+
closeAllFileDescriptors(FEEDBACK_FD, true);
|
401
|
+
|
401
402
|
execl(agentFilename.c_str(), AGENT_EXE, "watchdog",
|
402
403
|
// Some extra space to allow the child process to change its process title.
|
403
404
|
" ",
|
@@ -35,6 +35,7 @@
|
|
35
35
|
#include <unistd.h>
|
36
36
|
#include <stdio.h>
|
37
37
|
#include <stdlib.h>
|
38
|
+
#include <fcntl.h>
|
38
39
|
#include <time.h>
|
39
40
|
#include <signal.h>
|
40
41
|
#include <string.h>
|
@@ -124,16 +125,18 @@ save_master_process_pid(ngx_cycle_t *cycle) {
|
|
124
125
|
return NGX_OK;
|
125
126
|
}
|
126
127
|
|
128
|
+
typedef struct {
|
129
|
+
ngx_cycle_t *cycle;
|
130
|
+
int log_fd;
|
131
|
+
int stderr_equals_log_file;
|
132
|
+
} AfterForkData;
|
133
|
+
|
127
134
|
/**
|
128
135
|
* This function is called after forking and just before exec()ing the watchdog.
|
129
136
|
*/
|
130
137
|
static void
|
131
|
-
starting_watchdog_after_fork(void *
|
132
|
-
|
133
|
-
PsgVariantMap *params = (void *) paramParams;
|
134
|
-
|
135
|
-
char *log_filename;
|
136
|
-
FILE *log_file;
|
138
|
+
starting_watchdog_after_fork(void *_data, void *_params) {
|
139
|
+
AfterForkData *data = (AfterForkData *) _data;
|
137
140
|
ngx_core_conf_t *ccf;
|
138
141
|
ngx_uint_t i;
|
139
142
|
ngx_str_t *envs;
|
@@ -142,48 +145,74 @@ starting_watchdog_after_fork(void *paramCycle, void *paramParams) {
|
|
142
145
|
/* At this point, stdout and stderr may still point to the console.
|
143
146
|
* Make sure that they're both redirected to the log file.
|
144
147
|
*/
|
145
|
-
|
148
|
+
if (data->log_fd != -1) {
|
149
|
+
dup2(data->log_fd, 1);
|
150
|
+
dup2(data->log_fd, 2);
|
151
|
+
close(data->log_fd);
|
152
|
+
}
|
153
|
+
|
154
|
+
/* Set environment variables in Nginx config file. */
|
155
|
+
ccf = (ngx_core_conf_t *) ngx_get_conf(data->cycle->conf_ctx, ngx_core_module);
|
156
|
+
envs = ccf->env.elts;
|
157
|
+
for (i = 0; i < ccf->env.nelts; i++) {
|
158
|
+
env = (const char *) envs[i].data;
|
159
|
+
if (strchr(env, '=') != NULL) {
|
160
|
+
putenv(strdup(env));
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
/**
|
166
|
+
* This function provides a file descriptor that will be used
|
167
|
+
* to redirect stderr to after the upcoming fork. This prevents
|
168
|
+
* EIO errors on Linux if the user disconnects from the console
|
169
|
+
* on which Nginx is started.
|
170
|
+
*
|
171
|
+
* The fd will point to the log file, or to /dev/null if that
|
172
|
+
* fails (or -1 if that fails too).
|
173
|
+
*/
|
174
|
+
static void
|
175
|
+
open_log_file_for_after_forking(AfterForkData *data, PsgVariantMap *params) {
|
176
|
+
char *log_filename;
|
177
|
+
int fd;
|
178
|
+
|
146
179
|
log_filename = psg_variant_map_get_optional(params, "log_file");
|
147
180
|
if (log_filename == NULL) {
|
148
|
-
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
149
|
-
|
181
|
+
ngx_log_error(NGX_LOG_ALERT, data->cycle->log, 0,
|
182
|
+
"no " PROGRAM_NAME " log file configured, discarding log output");
|
183
|
+
fd = -1;
|
150
184
|
} else {
|
151
|
-
|
152
|
-
if (
|
153
|
-
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
154
|
-
|
185
|
+
fd = open(log_filename, O_WRONLY | O_APPEND | O_CREAT, 0644);
|
186
|
+
if (fd == -1) {
|
187
|
+
ngx_log_error(NGX_LOG_ALERT, data->cycle->log, ngx_errno,
|
188
|
+
"could not open the " PROGRAM_NAME " log file for writing during Nginx startup,"
|
189
|
+
" some log lines might be lost (will retry from " SHORT_PROGRAM_NAME " core)");
|
155
190
|
}
|
156
191
|
free(log_filename);
|
157
192
|
log_filename = NULL;
|
158
193
|
}
|
159
194
|
|
160
|
-
if (
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
*/
|
166
|
-
log_file = fopen("/dev/null", "w");
|
167
|
-
if (log_file == NULL) {
|
168
|
-
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
169
|
-
"could not open /dev/null for logs, this will probably cause EIO errors");
|
195
|
+
if (fd == -1) {
|
196
|
+
fd = open("/dev/null", O_WRONLY | O_APPEND);
|
197
|
+
if (fd == -1) {
|
198
|
+
ngx_log_error(NGX_LOG_ALERT, data->cycle->log, ngx_errno,
|
199
|
+
"could not open /dev/null for logs, this will probably cause EIO errors");
|
170
200
|
}
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
201
|
+
/**
|
202
|
+
* The log file open failed, so the after fork isn't going to be able to redirect
|
203
|
+
* stderr to it.
|
204
|
+
*/
|
205
|
+
data->stderr_equals_log_file = 0;
|
206
|
+
} else {
|
207
|
+
/**
|
208
|
+
* Technically not true until after the fork when starting_watchdog_after_fork does
|
209
|
+
* the redirection (dup2), but that never seems to fail and we need to know here
|
210
|
+
* already.
|
211
|
+
*/
|
212
|
+
data->stderr_equals_log_file = 1;
|
176
213
|
}
|
177
214
|
|
178
|
-
|
179
|
-
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
|
180
|
-
envs = ccf->env.elts;
|
181
|
-
for (i = 0; i < ccf->env.nelts; i++) {
|
182
|
-
env = (const char *) envs[i].data;
|
183
|
-
if (strchr(env, '=') != NULL) {
|
184
|
-
putenv(strdup(env));
|
185
|
-
}
|
186
|
-
}
|
215
|
+
data->log_fd = fd;
|
187
216
|
}
|
188
217
|
|
189
218
|
static ngx_int_t
|
@@ -228,6 +257,7 @@ start_watchdog(ngx_cycle_t *cycle) {
|
|
228
257
|
ngx_uint_t i;
|
229
258
|
ngx_str_t *prestart_uris;
|
230
259
|
char **prestart_uris_ary = NULL;
|
260
|
+
AfterForkData after_fork_data;
|
231
261
|
ngx_keyval_t *ctl = NULL;
|
232
262
|
PsgVariantMap *params = NULL;
|
233
263
|
u_char filename[NGX_MAX_PATH], *last;
|
@@ -237,6 +267,8 @@ start_watchdog(ngx_cycle_t *cycle) {
|
|
237
267
|
core_conf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
|
238
268
|
result = NGX_OK;
|
239
269
|
params = psg_variant_map_new();
|
270
|
+
after_fork_data.cycle = cycle;
|
271
|
+
after_fork_data.log_fd = -1;
|
240
272
|
passenger_root = ngx_str_null_terminate(&passenger_main_conf.root_dir);
|
241
273
|
if (passenger_root == NULL) {
|
242
274
|
goto error_enomem;
|
@@ -304,6 +336,10 @@ start_watchdog(ngx_cycle_t *cycle) {
|
|
304
336
|
psg_variant_map_set_ngx_str(params, "log_file", &cycle->log->file->name);
|
305
337
|
}
|
306
338
|
|
339
|
+
open_log_file_for_after_forking(&after_fork_data, params);
|
340
|
+
psg_variant_map_set_bool(params, "log_file_is_stderr",
|
341
|
+
after_fork_data.stderr_equals_log_file);
|
342
|
+
|
307
343
|
ctl = (ngx_keyval_t *) passenger_main_conf.ctl->elts;
|
308
344
|
for (i = 0; i < passenger_main_conf.ctl->nelts; i++) {
|
309
345
|
psg_variant_map_set2(params,
|
@@ -315,7 +351,7 @@ start_watchdog(ngx_cycle_t *cycle) {
|
|
315
351
|
passenger_root,
|
316
352
|
params,
|
317
353
|
starting_watchdog_after_fork,
|
318
|
-
|
354
|
+
&after_fork_data,
|
319
355
|
&error_message);
|
320
356
|
if (!ret) {
|
321
357
|
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "%s", error_message);
|
@@ -354,6 +390,10 @@ cleanup:
|
|
354
390
|
free(prestart_uris_ary);
|
355
391
|
}
|
356
392
|
|
393
|
+
if (after_fork_data.log_fd != -1) {
|
394
|
+
close(after_fork_data.log_fd);
|
395
|
+
}
|
396
|
+
|
357
397
|
if (result == NGX_ERROR && passenger_main_conf.abort_on_startup_error) {
|
358
398
|
exit(1);
|
359
399
|
}
|
@@ -31,18 +31,18 @@ module PhusionPassenger
|
|
31
31
|
|
32
32
|
PACKAGE_NAME = 'passenger'
|
33
33
|
# Run 'rake src/cxx_supportlib/Constants.h' after changing this number.
|
34
|
-
VERSION_STRING = '5.1.
|
34
|
+
VERSION_STRING = '5.1.12'
|
35
35
|
|
36
|
-
PREFERRED_NGINX_VERSION = '1.12.
|
37
|
-
NGINX_SHA256_CHECKSUM = '
|
36
|
+
PREFERRED_NGINX_VERSION = '1.12.2'
|
37
|
+
NGINX_SHA256_CHECKSUM = '305f379da1d5fb5aefa79e45c829852ca6983c7cd2a79328f8e084a324cf0416'
|
38
38
|
|
39
39
|
# Packaging may be locked to an older version due to the specific module configuration being
|
40
40
|
# incompatible with the version we prefer (latest stable).
|
41
|
-
PACKAGING_PREFERRED_NGINX_VERSION = '1.12.
|
42
|
-
PACKAGING_NGINX_SHA256_CHECKSUM = '
|
41
|
+
PACKAGING_PREFERRED_NGINX_VERSION = '1.12.2'
|
42
|
+
PACKAGING_NGINX_SHA256_CHECKSUM = '305f379da1d5fb5aefa79e45c829852ca6983c7cd2a79328f8e084a324cf0416'
|
43
43
|
|
44
|
-
PREFERRED_PCRE_VERSION = '8.
|
45
|
-
PCRE_SHA256_CHECKSUM = '
|
44
|
+
PREFERRED_PCRE_VERSION = '8.41'
|
45
|
+
PCRE_SHA256_CHECKSUM = '244838e1f1d14f7e2fa7681b857b3a8566b74215f28133f14a8f5e59241b682c'
|
46
46
|
|
47
47
|
STANDALONE_INTERFACE_VERSION = 1
|
48
48
|
|
@@ -173,7 +173,7 @@ module PhusionPassenger
|
|
173
173
|
|
174
174
|
# Whether the current Phusion Passenger installation is installed
|
175
175
|
# from a release package, e.g. an official gem or official tarball.
|
176
|
-
#
|
176
|
+
# Returns false if e.g. the gem was built by the user, or if this
|
177
177
|
# install is from a git repository.
|
178
178
|
def self.installed_from_release_package?
|
179
179
|
File.exist?("#{resources_dir}/release.txt")
|
@@ -100,7 +100,7 @@ module PhusionPassenger
|
|
100
100
|
if cache_file && #{cache_to_disk} # if cache_file && #{cache_to_disk}
|
101
101
|
begin # begin
|
102
102
|
if !File.directory?(@@cache_dir) # if !File.directory?(@@cache_dir)
|
103
|
-
|
103
|
+
FileUtils.mkdir_p(@@cache_dir) # FileUtils.mkdir_p(@@cache_dir)
|
104
104
|
end # end
|
105
105
|
File.open(cache_file, "wb") do |f| # File.open(cache_file, "wb") do |f|
|
106
106
|
f.write(Marshal.dump(#{variable_name})) # f.write(Marshal.dump(@@memoized_httpd))
|
@@ -174,7 +174,7 @@ module PhusionPassenger
|
|
174
174
|
# We want the command line options to override the options in the local
|
175
175
|
# config file, but the local config file could only be parsed when the
|
176
176
|
# command line options have been parsed. This method remerges all the
|
177
|
-
# config options from different sources so that options are
|
177
|
+
# config options from different sources so that options are overridden
|
178
178
|
# according to the following order:
|
179
179
|
#
|
180
180
|
# - CONFIG_DEFAULTS
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passenger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.1.
|
4
|
+
version: 5.1.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Phusion - http://www.phusion.nl/
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -114,6 +114,8 @@ files:
|
|
114
114
|
- dev/ci/tests/apache2/setup
|
115
115
|
- dev/ci/tests/cxx/run
|
116
116
|
- dev/ci/tests/cxx/setup
|
117
|
+
- dev/ci/tests/debian/Jenkinsfile
|
118
|
+
- dev/ci/tests/debian/run
|
117
119
|
- dev/ci/tests/nginx-dynamic/run
|
118
120
|
- dev/ci/tests/nginx-dynamic/setup
|
119
121
|
- dev/ci/tests/nginx/run
|