passenger 5.1.10 → 5.1.11
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/CHANGELOG +18 -0
- data/Rakefile +20 -17
- data/bin/passenger-install-apache2-module +14 -11
- data/build/agent.rb +45 -18
- data/build/apache2.rb +32 -16
- data/build/basics.rb +29 -40
- data/build/common_library.rb +70 -54
- data/build/cxx_tests.rb +34 -43
- data/build/integration_tests.rb +10 -10
- data/build/misc.rb +6 -6
- data/build/node_tests.rb +1 -2
- data/build/oxt_tests.rb +7 -5
- data/build/packaging.rb +11 -441
- data/build/ruby_extension.rb +1 -1
- data/build/ruby_tests.rb +1 -2
- data/build/support/cplusplus.rb +6 -5
- data/build/support/cxx_dependency_map.rb +357 -833
- data/build/support/general.rb +23 -1
- data/build/test_basics.rb +3 -28
- data/dev/ci/tests/rpm/Jenkinsfile +68 -0
- data/dev/ci/tests/rpm/run +63 -0
- data/dev/ci/tests/source-packaging/run +1 -1
- data/dev/ci/tests/source-packaging/setup +1 -1
- data/doc/{Packaging.txt.md → Packaging.md} +0 -0
- data/resources/templates/apache2/deployment_example.txt.erb +2 -2
- data/resources/templates/apache2/multiple_apache_installations_detected.txt.erb +2 -2
- data/resources/templates/nginx/deployment_example.txt.erb +1 -1
- data/resources/templates/standalone/mass_deployment_default_server.erb +2 -2
- data/resources/templates/standalone/server.erb +2 -2
- data/src/agent/AgentMain.cpp +0 -4
- data/src/agent/Core/CoreMain.cpp +88 -5
- data/src/agent/Core/SpawningKit/Spawner.h +2 -1
- data/src/agent/Shared/Fundamentals/AbortHandler.cpp +1109 -0
- data/src/agent/Shared/Fundamentals/AbortHandler.h +63 -0
- data/src/agent/Shared/Fundamentals/Implementation.cpp +7 -0
- data/src/agent/Shared/Fundamentals/Initialization.cpp +614 -0
- data/src/agent/Shared/{Base.h → Fundamentals/Initialization.h} +23 -14
- data/src/agent/Shared/Fundamentals/Utils.cpp +127 -0
- data/src/agent/Shared/Fundamentals/Utils.h +46 -0
- data/src/agent/TempDirToucher/TempDirToucherMain.cpp +1 -1
- data/src/agent/Watchdog/CoreWatcher.cpp +3 -1
- data/src/agent/Watchdog/InstanceDirToucher.cpp +90 -53
- data/src/agent/Watchdog/WatchdogMain.cpp +13 -29
- data/src/apache2_module/Hooks.cpp +4 -1
- data/src/cxx_supportlib/ConfigKit/Store.h +32 -5
- data/src/cxx_supportlib/Constants.h +1 -2
- data/src/cxx_supportlib/Crypto.cpp +2 -1
- data/src/cxx_supportlib/Hooks.h +16 -37
- data/src/cxx_supportlib/LoggingKit/Context.h +22 -0
- data/src/cxx_supportlib/LoggingKit/Forward.h +1 -0
- data/src/cxx_supportlib/LoggingKit/Implementation.cpp +106 -22
- data/src/cxx_supportlib/ProcessManagement/Ruby.cpp +106 -0
- data/src/{agent/UstRouter/FileSink.h → cxx_supportlib/ProcessManagement/Ruby.h} +23 -47
- data/src/cxx_supportlib/ProcessManagement/Spawn.cpp +199 -0
- data/src/cxx_supportlib/ProcessManagement/Spawn.h +150 -0
- data/src/cxx_supportlib/ProcessManagement/Utils.cpp +459 -0
- data/src/cxx_supportlib/ProcessManagement/Utils.h +107 -0
- data/src/cxx_supportlib/Utils.cpp +41 -561
- data/src/cxx_supportlib/Utils.h +0 -68
- data/src/cxx_supportlib/Utils/AsyncSignalSafeUtils.h +187 -0
- data/src/cxx_supportlib/Utils/ProcessMetricsCollector.h +14 -2
- data/src/cxx_supportlib/WatchdogLauncher.h +2 -12
- data/src/cxx_supportlib/oxt/dynamic_thread_group.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/jsoncpp/json-forwards.h +4 -0
- data/src/cxx_supportlib/vendor-modified/jsoncpp/json.h +16 -1
- data/src/cxx_supportlib/vendor-modified/jsoncpp/jsoncpp.cpp +12 -9
- data/src/cxx_supportlib/vendor-modified/libev/ev++.h +4 -4
- data/src/cxx_supportlib/vendor-modified/libev/ev.h +3 -3
- data/src/nginx_module/CacheLocationConfig.c +0 -75
- data/src/nginx_module/CacheLocationConfig.c.cxxcodebuilder +1 -0
- data/src/nginx_module/Configuration.c +0 -1
- data/src/nginx_module/Configuration.h +0 -1
- data/src/nginx_module/ConfigurationCommands.c +1 -1
- data/src/nginx_module/ContentHandler.c +0 -1
- data/src/nginx_module/ContentHandler.h +0 -1
- data/src/nginx_module/CreateLocationConfig.c +0 -5
- data/src/nginx_module/CreateLocationConfig.c.cxxcodebuilder +1 -0
- data/src/nginx_module/LocationConfig.h +0 -4
- data/src/nginx_module/LocationConfig.h.cxxcodebuilder +2 -1
- data/src/nginx_module/MergeLocationConfig.c +0 -12
- data/src/nginx_module/MergeLocationConfig.c.cxxcodebuilder +1 -0
- data/src/nginx_module/ngx_http_passenger_module.h +0 -1
- data/src/ruby_supportlib/phusion_passenger.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/common_library.rb +20 -11
- data/src/ruby_supportlib/phusion_passenger/config/api_call_command.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/config/reopen_logs_command.rb +0 -1
- data/src/ruby_supportlib/phusion_passenger/config/validate_install_command.rb +10 -3
- data/src/ruby_supportlib/phusion_passenger/console_text_template.rb +3 -1
- data/src/ruby_supportlib/phusion_passenger/constants.rb +0 -1
- data/src/ruby_supportlib/phusion_passenger/debug_logging.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/loader_shared_helpers.rb +32 -6
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +0 -1
- data/src/ruby_supportlib/phusion_passenger/packaging.rb +2 -4
- data/src/ruby_supportlib/phusion_passenger/platform_info/apache.rb +101 -20
- data/src/ruby_supportlib/phusion_passenger/platform_info/apache_detector.rb +21 -9
- data/src/ruby_supportlib/phusion_passenger/platform_info/compiler.rb +34 -31
- data/src/ruby_supportlib/phusion_passenger/platform_info/cxx_portability.rb +3 -1
- data/src/ruby_supportlib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +2 -14
- data/src/ruby_supportlib/phusion_passenger/platform_info/operating_system.rb +40 -3
- data/src/ruby_supportlib/phusion_passenger/standalone/app_finder.rb +15 -14
- data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/standalone/config_utils.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +8 -3
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb +19 -18
- data/src/ruby_supportlib/phusion_passenger/standalone/stop_command.rb +6 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller.rb +17 -1
- metadata +19 -97
- data/build/documentation.rb +0 -70
- data/doc/CloudLicensingConfiguration.html +0 -172
- data/doc/CloudLicensingConfiguration.txt.md +0 -3
- data/doc/Packaging.html +0 -488
- data/doc/Security of user switching support.idmap.txt +0 -34
- data/doc/Security of user switching support.txt +0 -197
- data/doc/ServerOptimizationGuide.html +0 -172
- data/doc/ServerOptimizationGuide.txt.md +0 -3
- data/doc/images/by_sa.png +0 -0
- data/doc/images/cloud_licensing_batch_job.png +0 -0
- data/doc/images/code_walkthrough.jpg +0 -0
- data/doc/images/direct_spawning.png +0 -0
- data/doc/images/direct_spawning.svg +0 -251
- data/doc/images/glyphicons-halflings-white.png +0 -0
- data/doc/images/glyphicons-halflings.png +0 -0
- data/doc/images/icons/README +0 -5
- data/doc/images/icons/callouts/1.png +0 -0
- data/doc/images/icons/callouts/10.png +0 -0
- data/doc/images/icons/callouts/11.png +0 -0
- data/doc/images/icons/callouts/12.png +0 -0
- data/doc/images/icons/callouts/13.png +0 -0
- data/doc/images/icons/callouts/14.png +0 -0
- data/doc/images/icons/callouts/15.png +0 -0
- data/doc/images/icons/callouts/2.png +0 -0
- data/doc/images/icons/callouts/3.png +0 -0
- data/doc/images/icons/callouts/4.png +0 -0
- data/doc/images/icons/callouts/5.png +0 -0
- data/doc/images/icons/callouts/6.png +0 -0
- data/doc/images/icons/callouts/7.png +0 -0
- data/doc/images/icons/callouts/8.png +0 -0
- data/doc/images/icons/callouts/9.png +0 -0
- data/doc/images/icons/caution.png +0 -0
- data/doc/images/icons/example.png +0 -0
- data/doc/images/icons/home.png +0 -0
- data/doc/images/icons/important.png +0 -0
- data/doc/images/icons/next.png +0 -0
- data/doc/images/icons/note.png +0 -0
- data/doc/images/icons/prev.png +0 -0
- data/doc/images/icons/tip.png +0 -0
- data/doc/images/icons/up.png +0 -0
- data/doc/images/icons/warning.png +0 -0
- data/doc/images/many_web_framework_protocols.png +0 -0
- data/doc/images/passenger_architecture.png +0 -0
- data/doc/images/passenger_architecture.svg +0 -385
- data/doc/images/passenger_architecture_overview.png +0 -0
- data/doc/images/passenger_core_architecture.png +0 -0
- data/doc/images/passenger_nodejs_architecture.svg +0 -558
- data/doc/images/phusion_banner.png +0 -0
- data/doc/images/rack.png +0 -0
- data/doc/images/smart_spawning.png +0 -0
- data/doc/images/smart_spawning.svg +0 -323
- data/doc/images/spawn_server_architecture.png +0 -0
- data/doc/images/spawn_server_architecture.svg +0 -655
- data/doc/images/spawning_preparation_work.png +0 -0
- data/doc/images/startup_sequence.png +0 -0
- data/doc/images/typical_isolated_web_application.png +0 -0
- data/doc/images/typical_isolated_web_application.svg +0 -213
- data/doc/users_guide_snippets/alternative_for_flying_passenger.txt +0 -1
- data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +0 -61
- data/doc/users_guide_snippets/appendix_a_about.txt +0 -13
- data/doc/users_guide_snippets/appendix_b_terminology.txt +0 -71
- data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +0 -36
- data/doc/users_guide_snippets/deployment_basics.txt +0 -37
- data/doc/users_guide_snippets/enterprise_only.txt +0 -1
- data/doc/users_guide_snippets/environment_variables.txt +0 -44
- data/doc/users_guide_snippets/global_queueing_explained.txt +0 -74
- data/doc/users_guide_snippets/installation.txt +0 -228
- data/doc/users_guide_snippets/installation/run_installer.txt +0 -58
- data/doc/users_guide_snippets/installation/verify_running_epilogue.txt +0 -6
- data/doc/users_guide_snippets/passenger_spawn_method.txt +0 -37
- data/doc/users_guide_snippets/rackup_specifications.txt +0 -1
- data/doc/users_guide_snippets/rvm_helper_tool.txt +0 -44
- data/doc/users_guide_snippets/since_version.txt +0 -1
- data/doc/users_guide_snippets/support_information.txt +0 -8
- data/doc/users_guide_snippets/tips.txt +0 -302
- data/doc/users_guide_snippets/troubleshooting/default.txt +0 -48
- data/doc/users_guide_snippets/troubleshooting/rails.txt +0 -59
- data/doc/users_guide_snippets/under_the_hood/page_caching_support.txt +0 -24
- data/doc/users_guide_snippets/under_the_hood/relationship_with_ruby.txt +0 -10
- data/doc/users_guide_snippets/where_to_get_support.txt +0 -9
- data/src/agent/Shared/Base.cpp +0 -1678
- data/src/agent/UstRouter/ApiServer.h +0 -292
- data/src/agent/UstRouter/Client.h +0 -112
- data/src/agent/UstRouter/Controller.h +0 -1309
- data/src/agent/UstRouter/LogSink.h +0 -145
- data/src/agent/UstRouter/OptionParser.h +0 -180
- data/src/agent/UstRouter/RemoteSender.h +0 -853
- data/src/agent/UstRouter/RemoteSink.h +0 -145
- data/src/agent/UstRouter/Transaction.h +0 -278
- data/src/agent/UstRouter/UstRouterMain.cpp +0 -681
- data/src/agent/Watchdog/UstRouterWatcher.cpp +0 -80
- data/src/ruby_supportlib/phusion_passenger/platform_info/macos.rb +0 -45
@@ -0,0 +1,106 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2017 Phusion Holding B.V.
|
4
|
+
*
|
5
|
+
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
+
* trademarks of Phusion Holding B.V.
|
7
|
+
*
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
+
* of this software and associated documentation files (the "Software"), to deal
|
10
|
+
* in the Software without restriction, including without limitation the rights
|
11
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
+
* copies of the Software, and to permit persons to whom the Software is
|
13
|
+
* furnished to do so, subject to the following conditions:
|
14
|
+
*
|
15
|
+
* The above copyright notice and this permission notice shall be included in
|
16
|
+
* all copies or substantial portions of the Software.
|
17
|
+
*
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24
|
+
* THE SOFTWARE.
|
25
|
+
*/
|
26
|
+
|
27
|
+
#include <string>
|
28
|
+
#include <vector>
|
29
|
+
#include <cstddef>
|
30
|
+
#include <cstdio>
|
31
|
+
|
32
|
+
#include <ProcessManagement/Spawn.h>
|
33
|
+
#include <ProcessManagement/Ruby.h>
|
34
|
+
#include <ResourceLocator.h>
|
35
|
+
#include <Exceptions.h>
|
36
|
+
|
37
|
+
namespace Passenger {
|
38
|
+
|
39
|
+
using namespace std;
|
40
|
+
|
41
|
+
|
42
|
+
void
|
43
|
+
runInternalRubyTool(const ResourceLocator &resourceLocator,
|
44
|
+
const string &ruby, const vector<string> &args, int *status,
|
45
|
+
string *output)
|
46
|
+
{
|
47
|
+
string locationConfigFileEnv = "PASSENGER_LOCATION_CONFIGURATION_FILE="
|
48
|
+
+ resourceLocator.getInstallSpec();
|
49
|
+
string fullProgramPath;
|
50
|
+
bool isRubyProgram;
|
51
|
+
const char *command[
|
52
|
+
4 // env, locationConfigEnvFile, ruby, fullProgramPath
|
53
|
+
+ (args.size() - 1)
|
54
|
+
+ 1 // NULL
|
55
|
+
];
|
56
|
+
unsigned int i = 0, j;
|
57
|
+
|
58
|
+
if (args[0][0] == '/') {
|
59
|
+
fullProgramPath = args[0];
|
60
|
+
} else {
|
61
|
+
fullProgramPath = resourceLocator.getBinDir() + "/" + args[0];
|
62
|
+
}
|
63
|
+
|
64
|
+
// The tool may be a wrapper script, e.g. one generated by Homebrew.
|
65
|
+
// If it's a non-Ruby wrapper script then don't invoke it with Ruby.
|
66
|
+
FILE *f = fopen(fullProgramPath.c_str(), "r");
|
67
|
+
if (f == NULL) {
|
68
|
+
throw RuntimeException("Unable to open " + fullProgramPath);
|
69
|
+
}
|
70
|
+
char line[1024];
|
71
|
+
if (fgets(line, sizeof(line), f) == NULL) {
|
72
|
+
if (ferror(f) != 0) {
|
73
|
+
fclose(f);
|
74
|
+
throw RuntimeException("Unable to read " + fullProgramPath);
|
75
|
+
} else {
|
76
|
+
throw RuntimeException(fullProgramPath + " is empty");
|
77
|
+
}
|
78
|
+
} else {
|
79
|
+
isRubyProgram = strstr(line, "ruby") != NULL;
|
80
|
+
}
|
81
|
+
fclose(f);
|
82
|
+
|
83
|
+
command[i++] = "env";
|
84
|
+
command[i++] = locationConfigFileEnv.c_str();
|
85
|
+
if (isRubyProgram) {
|
86
|
+
command[i++] = ruby.c_str();
|
87
|
+
}
|
88
|
+
command[i++] = fullProgramPath.c_str();
|
89
|
+
for (j = 1; j < args.size(); j++) {
|
90
|
+
command[i++] = args[j].c_str();
|
91
|
+
}
|
92
|
+
command[i++] = NULL;
|
93
|
+
|
94
|
+
SubprocessInfo info;
|
95
|
+
if (output == NULL) {
|
96
|
+
runCommand(command, info);
|
97
|
+
} else {
|
98
|
+
runCommandAndCaptureOutput(command, info, *output);
|
99
|
+
}
|
100
|
+
if (status != NULL) {
|
101
|
+
*status = info.status;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
|
106
|
+
} // namespace Passenger
|
@@ -23,63 +23,39 @@
|
|
23
23
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24
24
|
* THE SOFTWARE.
|
25
25
|
*/
|
26
|
-
#ifndef
|
27
|
-
#define
|
26
|
+
#ifndef _PASSENGER_PROCESS_MANAGEMENT_RUBY_H_
|
27
|
+
#define _PASSENGER_PROCESS_MANAGEMENT_RUBY_H_
|
28
28
|
|
29
29
|
#include <string>
|
30
|
-
#include <
|
31
|
-
#include <
|
32
|
-
#include <Exceptions.h>
|
33
|
-
#include <FileDescriptor.h>
|
34
|
-
#include <UstRouter/LogSink.h>
|
35
|
-
#include <Utils/StrIntUtils.h>
|
30
|
+
#include <vector>
|
31
|
+
#include <cstddef>
|
36
32
|
|
37
33
|
namespace Passenger {
|
38
|
-
namespace UstRouter {
|
39
34
|
|
40
35
|
using namespace std;
|
41
|
-
using namespace oxt;
|
42
36
|
|
37
|
+
class ResourceLocator;
|
43
38
|
|
44
|
-
class FileSink: public LogSink {
|
45
|
-
public:
|
46
|
-
string filename;
|
47
|
-
FileDescriptor fd;
|
48
39
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
syscalls::write(fd, data.data(), data.size());
|
67
|
-
}
|
68
|
-
|
69
|
-
virtual Json::Value inspectStateAsJson() const {
|
70
|
-
Json::Value doc = LogSink::inspectStateAsJson();
|
71
|
-
doc["type"] = "file";
|
72
|
-
doc["filename"] = filename;
|
73
|
-
return doc;
|
74
|
-
}
|
75
|
-
|
76
|
-
string inspect() const {
|
77
|
-
return "FileSink(" + filename + ")";
|
78
|
-
}
|
79
|
-
};
|
40
|
+
/**
|
41
|
+
* Run a Passenger-internal Ruby tool, e.g. passenger-config, and optionally capture
|
42
|
+
* its stdout output. This function does not care whether the command fails.
|
43
|
+
*
|
44
|
+
* @param resourceLocator
|
45
|
+
* @param ruby The Ruby interpreter to attempt to use for running the tool.
|
46
|
+
* @param args The command as an array of strings, e.g. ["passenger-config", "system-properties"].
|
47
|
+
* @param status The status of the child process will be stored here, if non-NULL.
|
48
|
+
* When unable to waitpid() the child process because of an ECHILD
|
49
|
+
* or ESRCH, this will be set to -1.
|
50
|
+
* @param output The output of the child process will be stored here, if non-NULL.
|
51
|
+
* @throws RuntimeException
|
52
|
+
* @throws SystemException
|
53
|
+
*/
|
54
|
+
void runInternalRubyTool(const ResourceLocator &resourceLocator,
|
55
|
+
const string &ruby, const vector<string> &args,
|
56
|
+
int *status = NULL, string *output = NULL);
|
80
57
|
|
81
58
|
|
82
|
-
} // namespace UstRouter
|
83
59
|
} // namespace Passenger
|
84
60
|
|
85
|
-
#endif /*
|
61
|
+
#endif /* _PASSENGER_PROCESS_MANAGEMENT_RUBY_H_ */
|
@@ -0,0 +1,199 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2010-2017 Phusion Holding B.V.
|
4
|
+
*
|
5
|
+
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
+
* trademarks of Phusion Holding B.V.
|
7
|
+
*
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
+
* of this software and associated documentation files (the "Software"), to deal
|
10
|
+
* in the Software without restriction, including without limitation the rights
|
11
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
+
* copies of the Software, and to permit persons to whom the Software is
|
13
|
+
* furnished to do so, subject to the following conditions:
|
14
|
+
*
|
15
|
+
* The above copyright notice and this permission notice shall be included in
|
16
|
+
* all copies or substantial portions of the Software.
|
17
|
+
*
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24
|
+
* THE SOFTWARE.
|
25
|
+
*/
|
26
|
+
|
27
|
+
#include <sys/types.h>
|
28
|
+
#include <sys/wait.h>
|
29
|
+
#include <unistd.h>
|
30
|
+
#include <stdlib.h>
|
31
|
+
#include <signal.h>
|
32
|
+
|
33
|
+
#include <boost/thread.hpp>
|
34
|
+
#include <oxt/system_calls.hpp>
|
35
|
+
#include <string>
|
36
|
+
#include <cerrno>
|
37
|
+
|
38
|
+
#include <ProcessManagement/Spawn.h>
|
39
|
+
#include <ProcessManagement/Utils.h>
|
40
|
+
#include <StaticString.h>
|
41
|
+
#include <Exceptions.h>
|
42
|
+
#include <Utils/IOUtils.h>
|
43
|
+
|
44
|
+
namespace Passenger {
|
45
|
+
|
46
|
+
using namespace std;
|
47
|
+
|
48
|
+
|
49
|
+
int
|
50
|
+
runShellCommand(const StaticString &command) {
|
51
|
+
string commandNt = command;
|
52
|
+
const char *argv[] = {
|
53
|
+
"/bin/sh",
|
54
|
+
"-c",
|
55
|
+
commandNt.c_str(),
|
56
|
+
NULL
|
57
|
+
};
|
58
|
+
SubprocessInfo info;
|
59
|
+
runCommand(argv, info);
|
60
|
+
return info.status;
|
61
|
+
}
|
62
|
+
|
63
|
+
void
|
64
|
+
runCommand(const char **command, SubprocessInfo &info, bool wait, bool killSubprocessOnInterruption,
|
65
|
+
const boost::function<void ()> &afterFork,
|
66
|
+
const boost::function<void (const char **, int errcode)> &onExecFail)
|
67
|
+
{
|
68
|
+
int e, waitStatus;
|
69
|
+
pid_t waitRet;
|
70
|
+
|
71
|
+
info.pid = asyncFork();
|
72
|
+
if (info.pid == 0) {
|
73
|
+
resetSignalHandlersAndMask();
|
74
|
+
disableMallocDebugging();
|
75
|
+
if (afterFork) {
|
76
|
+
afterFork();
|
77
|
+
}
|
78
|
+
closeAllFileDescriptors(2, true);
|
79
|
+
execvp(command[0], (char * const *) command);
|
80
|
+
if (onExecFail) {
|
81
|
+
onExecFail(command, errno);
|
82
|
+
}
|
83
|
+
_exit(1);
|
84
|
+
} else if (info.pid == -1) {
|
85
|
+
e = errno;
|
86
|
+
throw SystemException("Cannot fork() a new process", e);
|
87
|
+
} else if (wait) {
|
88
|
+
try {
|
89
|
+
waitRet = syscalls::waitpid(info.pid, &waitStatus, 0);
|
90
|
+
} catch (const boost::thread_interrupted &) {
|
91
|
+
if (killSubprocessOnInterruption) {
|
92
|
+
boost::this_thread::disable_syscall_interruption dsi;
|
93
|
+
syscalls::kill(SIGKILL, info.pid);
|
94
|
+
syscalls::waitpid(info.pid, NULL, 0);
|
95
|
+
}
|
96
|
+
throw;
|
97
|
+
}
|
98
|
+
|
99
|
+
if (waitRet != -1) {
|
100
|
+
info.status = waitStatus;
|
101
|
+
} else if (errno == ECHILD || errno == ESRCH) {
|
102
|
+
info.status = -2;
|
103
|
+
} else {
|
104
|
+
int e = errno;
|
105
|
+
throw SystemException(string("Error waiting for the '") +
|
106
|
+
command[0] + "' command", e);
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
void
|
112
|
+
runCommandAndCaptureOutput(const char **command, SubprocessInfo &info,
|
113
|
+
string &output, bool killSubprocessOnInterruption,
|
114
|
+
const boost::function<void ()> &afterFork,
|
115
|
+
const boost::function<void (const char **command, int errcode)> &onExecFail)
|
116
|
+
{
|
117
|
+
pid_t waitRet;
|
118
|
+
int e, waitStatus;
|
119
|
+
Pipe p;
|
120
|
+
|
121
|
+
p = createPipe(__FILE__, __LINE__);
|
122
|
+
|
123
|
+
info.pid = asyncFork();
|
124
|
+
if (info.pid == 0) {
|
125
|
+
dup2(p[1], 1);
|
126
|
+
close(p[0]);
|
127
|
+
close(p[1]);
|
128
|
+
resetSignalHandlersAndMask();
|
129
|
+
disableMallocDebugging();
|
130
|
+
if (afterFork) {
|
131
|
+
afterFork();
|
132
|
+
}
|
133
|
+
closeAllFileDescriptors(2, true);
|
134
|
+
execvp(command[0], (char * const *) command);
|
135
|
+
if (onExecFail) {
|
136
|
+
onExecFail(command, errno);
|
137
|
+
}
|
138
|
+
_exit(1);
|
139
|
+
} else if (info.pid == -1) {
|
140
|
+
e = errno;
|
141
|
+
throw SystemException("Cannot fork() a new process", e);
|
142
|
+
} else {
|
143
|
+
bool done = false;
|
144
|
+
|
145
|
+
p[1].close();
|
146
|
+
while (!done) {
|
147
|
+
char buf[1024 * 4];
|
148
|
+
ssize_t ret;
|
149
|
+
|
150
|
+
try {
|
151
|
+
ret = syscalls::read(p[0], buf, sizeof(buf));
|
152
|
+
} catch (const boost::thread_interrupted &) {
|
153
|
+
if (killSubprocessOnInterruption) {
|
154
|
+
boost::this_thread::disable_syscall_interruption dsi;
|
155
|
+
syscalls::kill(SIGKILL, info.pid);
|
156
|
+
syscalls::waitpid(info.pid, NULL, 0);
|
157
|
+
}
|
158
|
+
throw;
|
159
|
+
}
|
160
|
+
if (ret == -1) {
|
161
|
+
e = errno;
|
162
|
+
if (killSubprocessOnInterruption) {
|
163
|
+
boost::this_thread::disable_syscall_interruption dsi;
|
164
|
+
syscalls::kill(SIGKILL, info.pid);
|
165
|
+
syscalls::waitpid(info.pid, NULL, 0);
|
166
|
+
}
|
167
|
+
throw SystemException(string("Cannot read output from the '") +
|
168
|
+
command[0] + "' command", e);
|
169
|
+
}
|
170
|
+
done = ret == 0;
|
171
|
+
output.append(buf, ret);
|
172
|
+
}
|
173
|
+
p[0].close();
|
174
|
+
|
175
|
+
try {
|
176
|
+
waitRet = syscalls::waitpid(info.pid, &waitStatus, 0);
|
177
|
+
} catch (const boost::thread_interrupted &) {
|
178
|
+
if (killSubprocessOnInterruption) {
|
179
|
+
boost::this_thread::disable_syscall_interruption dsi;
|
180
|
+
syscalls::kill(SIGKILL, info.pid);
|
181
|
+
syscalls::waitpid(info.pid, NULL, 0);
|
182
|
+
}
|
183
|
+
throw;
|
184
|
+
}
|
185
|
+
|
186
|
+
if (waitRet != -1) {
|
187
|
+
info.status = waitStatus;
|
188
|
+
} else if (errno == ECHILD || errno == ESRCH) {
|
189
|
+
info.status = -2;
|
190
|
+
} else {
|
191
|
+
int e = errno;
|
192
|
+
throw SystemException(string("Error waiting for the '") +
|
193
|
+
command[0] + "' command", e);
|
194
|
+
}
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
|
199
|
+
} // namespace Passenger
|
@@ -0,0 +1,150 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2010-2017 Phusion Holding B.V.
|
4
|
+
*
|
5
|
+
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
+
* trademarks of Phusion Holding B.V.
|
7
|
+
*
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
+
* of this software and associated documentation files (the "Software"), to deal
|
10
|
+
* in the Software without restriction, including without limitation the rights
|
11
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
+
* copies of the Software, and to permit persons to whom the Software is
|
13
|
+
* furnished to do so, subject to the following conditions:
|
14
|
+
*
|
15
|
+
* The above copyright notice and this permission notice shall be included in
|
16
|
+
* all copies or substantial portions of the Software.
|
17
|
+
*
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24
|
+
* THE SOFTWARE.
|
25
|
+
*/
|
26
|
+
#ifndef _PASSENGER_PROCESS_MANAGEMENT_SPAWN_H_
|
27
|
+
#define _PASSENGER_PROCESS_MANAGEMENT_SPAWN_H_
|
28
|
+
|
29
|
+
#include <sys/types.h>
|
30
|
+
#include <boost/function.hpp>
|
31
|
+
#include <string>
|
32
|
+
#include <StaticString.h>
|
33
|
+
|
34
|
+
namespace Passenger {
|
35
|
+
|
36
|
+
using namespace std;
|
37
|
+
|
38
|
+
struct SubprocessInfo {
|
39
|
+
/**
|
40
|
+
* The PID of the subprocess. This is set to -1 on
|
41
|
+
* object creation. If fork fails or is interrupted,
|
42
|
+
* then this field is unmodified.
|
43
|
+
*
|
44
|
+
* Attention: if you called `runCommand()` with `wait = true`,
|
45
|
+
* or if you called `runCommandAndCaptureOutput()`,
|
46
|
+
* then when that function returns, this PID no longer
|
47
|
+
* exists.
|
48
|
+
*/
|
49
|
+
pid_t pid;
|
50
|
+
|
51
|
+
/**
|
52
|
+
* The status of the subprocess, as returned by waitpid().
|
53
|
+
* This is set to -1 on object creation.
|
54
|
+
*
|
55
|
+
* Only if `runCommand()` is done waiting for the subprocess
|
56
|
+
* will this field be set. So if you call `runCommand()` with
|
57
|
+
* `wait = false` then this field will never be modified.
|
58
|
+
*
|
59
|
+
* When unable to waitpid() the subprocess because of
|
60
|
+
* an ECHILD or ESRCH, then this field is set to -2.
|
61
|
+
*/
|
62
|
+
int status;
|
63
|
+
|
64
|
+
SubprocessInfo()
|
65
|
+
: pid(-1),
|
66
|
+
status(-1)
|
67
|
+
{ }
|
68
|
+
};
|
69
|
+
|
70
|
+
|
71
|
+
// See ProcessManagement/Utils.h for definition
|
72
|
+
void printExecError(const char **command, int errcode);
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Like system(), but properly resets the signal handler mask,
|
76
|
+
* disables malloc debugging and closes file descriptors > 2.
|
77
|
+
*
|
78
|
+
* This is like `runCommand()` but runs something through the shell.
|
79
|
+
*
|
80
|
+
* @throws SystemException
|
81
|
+
* @throws boost::thread_interrupted
|
82
|
+
*/
|
83
|
+
int runShellCommand(const StaticString &command);
|
84
|
+
|
85
|
+
/**
|
86
|
+
* Run a command and (if so configured) wait for it. You can see this function
|
87
|
+
* as a more flexible version of system(): it accepts a command array
|
88
|
+
* instead of a shell command string, and you can choose whether to wait
|
89
|
+
* for the subprocess or not.
|
90
|
+
*
|
91
|
+
* In addition, this function also properly resets the signal handler mask,
|
92
|
+
* disables malloc debugging and closes file descriptors > 2.
|
93
|
+
*
|
94
|
+
* Information about the subprocess is stored inside `info`. See the comments
|
95
|
+
* for the `SubprocessInfo` structure to learn more about it.
|
96
|
+
*
|
97
|
+
* If this function encounters an error or is interrupted, then it ensures
|
98
|
+
* that as much information as possible about the current state of things
|
99
|
+
* is stored in `info` so that the caller can clean things up appropriately.
|
100
|
+
*
|
101
|
+
* @param command The argument array to pass to execvp(). Must be null-terminated.
|
102
|
+
* @param info
|
103
|
+
* @param wait Whether to wait for the subprocess before returning.
|
104
|
+
* @param killSubprocessOnInterruption Whether to automatically kill the subprocess
|
105
|
+
* when this function is interrupted.
|
106
|
+
* @param afterFork A function object to be called right after forking.
|
107
|
+
* @throws SystemException
|
108
|
+
* @throws boost::thread_interrupted
|
109
|
+
*/
|
110
|
+
void runCommand(const char **command, SubprocessInfo &info,
|
111
|
+
bool wait = true, bool killSubprocessOnInterruption = true,
|
112
|
+
const boost::function<void ()> &afterFork = boost::function<void ()>(),
|
113
|
+
const boost::function<void (const char **command, int errcode)> &onExecFail = printExecError);
|
114
|
+
|
115
|
+
/**
|
116
|
+
* Run a command, wait for it, and capture its stdout output.
|
117
|
+
* This function does not care whether the command fails.
|
118
|
+
*
|
119
|
+
* In addition (like `runCommand()`), this function also properly
|
120
|
+
* resets the signal handler mask, disables malloc debugging and
|
121
|
+
* closes file descriptors > 2.
|
122
|
+
*
|
123
|
+
* If something goes wrong or when interrupted while capturing the
|
124
|
+
* output, then `output` contains the output captured so far.
|
125
|
+
*
|
126
|
+
* Information about the subprocess is stored inside `info`. See the comments
|
127
|
+
* for the `SubprocessInfo` structure to learn more about it.
|
128
|
+
*
|
129
|
+
* If this function encounters an error or is interrupted, then it ensures
|
130
|
+
* that as much information as possible about the current state of things
|
131
|
+
* is stored in `info` so that the caller can clean things up appropriately.
|
132
|
+
*
|
133
|
+
* @param command The argument array to pass to execvp(). Must be null-terminated.
|
134
|
+
* @param info
|
135
|
+
* @param killSubprocessOnInterruption Whether to automatically kill the subprocess
|
136
|
+
* when this function is interrupted.
|
137
|
+
* @param afterFork A function object to be called right after forking.
|
138
|
+
* @param onExecFail A function object to be called if exec fails.
|
139
|
+
* @throws SystemException
|
140
|
+
* @throws boost::thread_interrupted
|
141
|
+
*/
|
142
|
+
void runCommandAndCaptureOutput(const char **command, SubprocessInfo &info,
|
143
|
+
string &output, bool killSubprocessOnInterruption = true,
|
144
|
+
const boost::function<void ()> &afterFork = boost::function<void ()>(),
|
145
|
+
const boost::function<void (const char **command, int errcode)> &onExecFail = printExecError);
|
146
|
+
|
147
|
+
|
148
|
+
} // namespace Passenger
|
149
|
+
|
150
|
+
#endif /* _PASSENGER_PROCESS_MANAGEMENT_SPAWN_H_ */
|