passenger 5.2.3 → 5.3.0
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 +13 -0
- data/CONTRIBUTORS +5 -1
- data/build/agent.rb +22 -2
- data/build/cxx_tests.rb +41 -5
- data/build/misc.rb +4 -1
- data/build/support/cxx_dependency_map.rb +1746 -908
- data/build/support/vendor/cxx_hinted_parser/CxxHintedParser.sublime-project +8 -0
- data/build/support/vendor/cxx_hinted_parser/Gemfile +5 -0
- data/build/support/vendor/cxx_hinted_parser/Gemfile.lock +30 -0
- data/{src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core → build/support/vendor/cxx_hinted_parser}/LICENSE.md +1 -1
- data/build/support/vendor/cxx_hinted_parser/README.md +95 -0
- data/build/support/vendor/cxx_hinted_parser/Rakefile +4 -0
- data/{src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/initialize.rb → build/support/vendor/cxx_hinted_parser/lib/cxx_hinted_parser.rb} +2 -9
- data/build/support/vendor/cxx_hinted_parser/lib/cxx_hinted_parser/parser.rb +239 -0
- data/dev/ci/README.md +15 -2
- data/dev/ci/lib/set-container-envvars.sh +6 -0
- data/dev/ci/lib/setup-container.sh +4 -1
- data/dev/ci/scripts/debug-console-wrapper.sh +3 -1
- data/dev/ci/setup-host +5 -0
- data/dev/ci/tests/binaries/Jenkinsfile +105 -0
- data/dev/ci/tests/binaries/build-linux +38 -0
- data/dev/ci/tests/binaries/build-macos +40 -0
- data/dev/ci/tests/binaries/prepare-macos +38 -0
- data/dev/ci/tests/binaries/test-linux +45 -0
- data/dev/ci/tests/binaries/test-macos +38 -0
- data/dev/ci/tests/debian/Jenkinsfile +2 -2
- data/dev/ci/tests/rpm/Jenkinsfile +1 -1
- data/dev/configkit-schemas/index.json +3 -24
- data/dev/vagrant/nginx_rakefile +0 -1
- data/package.json +15 -5
- data/resources/templates/error_renderer/.editorconfig +19 -0
- data/resources/templates/error_renderer/with_details/README.md +9 -0
- data/resources/templates/error_renderer/with_details/dist/bundle.js +33 -0
- data/resources/templates/error_renderer/with_details/dist/styles.css +17 -0
- data/resources/templates/error_renderer/with_details/src/DetailsView.jsx +52 -0
- data/resources/templates/error_renderer/with_details/src/GetHelpView.jsx +61 -0
- data/resources/templates/error_renderer/with_details/src/JourneyView.css +50 -0
- data/resources/templates/error_renderer/with_details/src/JourneyView.jsx +621 -0
- data/resources/templates/error_renderer/with_details/src/PageMain.css +114 -0
- data/resources/templates/error_renderer/with_details/src/PageMain.jsx +136 -0
- data/resources/templates/error_renderer/with_details/src/ProblemDescriptionView.jsx +14 -0
- data/resources/templates/error_renderer/with_details/src/ProcessDetailsView.jsx +56 -0
- data/resources/templates/error_renderer/with_details/src/SolutionDescriptionView.css +5 -0
- data/resources/templates/error_renderer/with_details/src/SolutionDescriptionView.jsx +15 -0
- data/resources/templates/error_renderer/with_details/src/SummaryView.jsx +35 -0
- data/resources/templates/error_renderer/with_details/src/SystemComponentView.css +34 -0
- data/resources/templates/error_renderer/with_details/src/SystemComponentView.jsx +168 -0
- data/resources/templates/error_renderer/with_details/src/SystemComponentsView.css +13 -0
- data/resources/templates/error_renderer/with_details/src/SystemComponentsView.jsx +116 -0
- data/resources/templates/error_renderer/with_details/src/Tab.jsx +12 -0
- data/resources/templates/error_renderer/with_details/src/Tabs.jsx +104 -0
- data/resources/templates/error_renderer/with_details/src/bootstrap/bootstrap.css +3446 -0
- data/resources/templates/error_renderer/with_details/src/bootstrap/bootstrap.js +293 -0
- data/resources/templates/error_renderer/with_details/src/bootstrap/config.json +401 -0
- data/resources/templates/error_renderer/with_details/src/index.html.template +22 -0
- data/resources/templates/error_renderer/with_details/src/index.jsx +23 -0
- data/resources/templates/error_renderer/with_details/webpack.config.js +47 -0
- data/resources/templates/error_renderer/without_details/dist/bundle.js +1 -0
- data/resources/templates/error_renderer/without_details/dist/styles.css +1 -0
- data/resources/templates/{undisclosed_error.html.template → error_renderer/without_details/src/index.html.template} +7 -11
- data/resources/templates/error_renderer/without_details/src/index.js +1 -0
- data/resources/templates/{error_layout.css → error_renderer/without_details/src/main.css} +5 -2
- data/resources/templates/error_renderer/without_details/webpack.config.js +42 -0
- data/src/agent/AgentMain.cpp +3 -3
- data/src/agent/Core/ApplicationPool/BasicProcessInfo.h +13 -0
- data/src/agent/Core/ApplicationPool/Common.h +3 -4
- data/src/agent/Core/ApplicationPool/Context.h +27 -17
- data/src/agent/Core/ApplicationPool/Group.h +3 -1
- data/src/agent/Core/ApplicationPool/Group/InitializationAndShutdown.cpp +2 -12
- data/src/agent/Core/ApplicationPool/Group/InternalUtils.cpp +55 -10
- data/src/agent/Core/ApplicationPool/Group/LifetimeAndBasics.cpp +1 -1
- data/src/agent/Core/ApplicationPool/Group/OutOfBandWork.cpp +1 -1
- data/src/agent/Core/ApplicationPool/Group/SpawningAndRestarting.cpp +13 -6
- data/src/agent/Core/ApplicationPool/Implementation.cpp +16 -100
- data/src/agent/Core/ApplicationPool/Options.h +8 -65
- data/src/agent/Core/ApplicationPool/Pool.h +4 -21
- data/src/agent/Core/ApplicationPool/Pool/AnalyticsCollection.cpp +1 -60
- data/src/agent/Core/ApplicationPool/Pool/GeneralUtils.cpp +10 -13
- data/src/agent/Core/ApplicationPool/Pool/InitializationAndShutdown.cpp +3 -8
- data/src/agent/Core/ApplicationPool/Pool/Miscellaneous.cpp +2 -34
- data/src/agent/Core/ApplicationPool/Pool/StateInspection.cpp +1 -1
- data/src/agent/Core/ApplicationPool/Process.cpp +17 -12
- data/src/agent/Core/ApplicationPool/Process.h +146 -93
- data/src/agent/Core/ApplicationPool/Session.h +2 -2
- data/src/agent/Core/ApplicationPool/Socket.h +28 -27
- data/src/agent/Core/Config.h +1 -3
- data/src/agent/Core/ConfigChange.cpp +2 -4
- data/src/agent/Core/Controller.h +2 -8
- data/src/agent/Core/Controller/BufferBody.cpp +0 -2
- data/src/agent/Core/Controller/CheckoutSession.cpp +12 -24
- data/src/agent/Core/Controller/Config.h +1 -9
- data/src/agent/Core/Controller/ForwardResponse.cpp +0 -34
- data/src/agent/Core/Controller/Hooks.cpp +0 -7
- data/src/agent/Core/Controller/InitRequest.cpp +0 -43
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +0 -4
- data/src/agent/Core/Controller/Request.h +1 -35
- data/src/agent/Core/Controller/SendRequest.cpp +0 -32
- data/src/agent/Core/CoreMain.cpp +19 -32
- data/src/agent/Core/SpawningKit/Config.h +329 -55
- data/src/agent/Core/SpawningKit/Config/AutoGeneratedCode.h +369 -0
- data/src/agent/Core/SpawningKit/Config/AutoGeneratedCode.h.cxxcodebuilder +307 -0
- data/src/agent/Core/SpawningKit/Context.h +211 -0
- data/src/agent/Core/SpawningKit/DirectSpawner.h +112 -122
- data/src/agent/Core/SpawningKit/DummySpawner.h +59 -20
- data/src/agent/Core/SpawningKit/ErrorRenderer.h +117 -0
- data/src/agent/Core/SpawningKit/Exceptions.h +1157 -0
- data/src/agent/Core/SpawningKit/Factory.h +24 -17
- data/src/agent/Core/SpawningKit/{BackgroundIOCapturer.h → Handshake/BackgroundIOCapturer.h} +48 -18
- data/src/agent/Core/SpawningKit/Handshake/Perform.h +1650 -0
- data/src/agent/Core/SpawningKit/Handshake/Prepare.h +582 -0
- data/src/agent/Core/SpawningKit/Handshake/Session.h +91 -0
- data/src/agent/Core/SpawningKit/Handshake/WorkDir.h +100 -0
- data/src/agent/Core/SpawningKit/Journey.h +561 -0
- data/src/agent/Core/SpawningKit/PipeWatcher.h +41 -18
- data/src/agent/Core/SpawningKit/README.md +534 -0
- data/src/agent/Core/SpawningKit/Result.h +182 -7
- data/src/agent/Core/SpawningKit/Result/AutoGeneratedCode.h +69 -0
- data/src/agent/Core/SpawningKit/Result/AutoGeneratedCode.h.cxxcodebuilder +110 -0
- data/src/agent/Core/SpawningKit/SmartSpawner.h +1027 -562
- data/src/agent/Core/SpawningKit/Spawner.h +70 -1134
- data/src/agent/Core/SpawningKit/UserSwitchingRules.h +3 -33
- data/src/agent/README.md +2 -3
- data/src/agent/Shared/ApiServerUtils.h +2 -3
- data/src/agent/SpawnEnvSetupper/SpawnEnvSetupperMain.cpp +932 -0
- data/src/agent/Watchdog/Config.h +1 -3
- data/src/agent/Watchdog/WatchdogMain.cpp +2 -1
- data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +5 -0
- data/src/apache2_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.cpp +5 -0
- data/src/apache2_module/ConfigGeneral/ManifestGeneration.h +22 -13
- data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp +5 -0
- data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp +3 -0
- data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp +13 -0
- data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp +7 -0
- data/src/apache2_module/DirConfig/AutoGeneratedStruct.h +13 -0
- data/src/cxx_supportlib/Constants.h +3 -1
- data/src/cxx_supportlib/Exceptions.h +0 -121
- data/src/cxx_supportlib/LoggingKit/Implementation.cpp +7 -6
- data/src/cxx_supportlib/LoggingKit/Logging.h +3 -1
- data/src/cxx_supportlib/Utils.cpp +42 -0
- data/src/cxx_supportlib/Utils.h +7 -0
- data/src/cxx_supportlib/Utils/IOUtils.cpp +58 -0
- data/src/cxx_supportlib/Utils/IOUtils.h +13 -0
- data/src/cxx_supportlib/Utils/JsonUtils.h +130 -23
- data/src/cxx_supportlib/Utils/ScopeGuard.h +9 -4
- data/src/cxx_supportlib/Utils/StrIntUtils.cpp +7 -0
- data/src/cxx_supportlib/Utils/StrIntUtils.h +1 -0
- data/src/cxx_supportlib/Utils/SystemTime.h +1 -1
- data/src/cxx_supportlib/Utils/Timer.h +1 -1
- data/src/cxx_supportlib/WebSocketCommandReverseServer.h +6 -4
- data/src/cxx_supportlib/vendor-copy/adhoc_lve.h +1 -0
- data/src/helper-scripts/node-loader.js +54 -59
- data/src/helper-scripts/rack-loader.rb +63 -60
- data/src/helper-scripts/rack-preloader.rb +125 -72
- data/src/helper-scripts/wsgi-loader.py +100 -43
- data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +120 -112
- data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c +15 -8
- data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +142 -142
- data/src/nginx_module/ConfigGeneral/ManifestGeneration.c +26 -15
- data/src/nginx_module/ConfigGeneral/ManifestGeneration.h +3 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c +76 -70
- data/src/nginx_module/LocationConfig/AutoGeneratedHeaderSerialization.c +114 -99
- data/src/nginx_module/LocationConfig/AutoGeneratedManifestGeneration.c +170 -156
- data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c +38 -35
- data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h +5 -1
- data/src/ruby_supportlib/phusion_passenger.rb +5 -5
- data/src/ruby_supportlib/phusion_passenger/admin_tools/instance.rb +14 -1
- data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +8 -0
- data/src/ruby_supportlib/phusion_passenger/common_library.rb +0 -3
- data/src/ruby_supportlib/phusion_passenger/config/nginx_engine_compiler.rb +0 -1
- data/src/ruby_supportlib/phusion_passenger/constants.rb +2 -0
- data/src/ruby_supportlib/phusion_passenger/loader_shared_helpers.rb +646 -238
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +117 -95
- data/src/ruby_supportlib/phusion_passenger/packaging.rb +0 -1
- data/src/ruby_supportlib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +5 -1
- data/src/ruby_supportlib/phusion_passenger/preloader_shared_helpers.rb +92 -69
- data/src/ruby_supportlib/phusion_passenger/public_api.rb +0 -17
- data/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb +0 -3
- data/src/ruby_supportlib/phusion_passenger/request_handler.rb +4 -5
- data/src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb +0 -22
- metadata +64 -67
- data/resources/templates/error_layout.html.template +0 -86
- data/resources/templates/general_error.html.template +0 -1
- data/resources/templates/general_error_with_html.html.template +0 -1
- data/src/agent/Core/ApplicationPool/ErrorRenderer.h +0 -131
- data/src/agent/Core/SpawningKit/Options.h +0 -41
- data/src/agent/Core/UnionStation/Connection.h +0 -173
- data/src/agent/Core/UnionStation/Context.h +0 -536
- data/src/agent/Core/UnionStation/StopwatchLog.h +0 -147
- data/src/agent/Core/UnionStation/Transaction.h +0 -249
- data/src/agent/SpawnPreparer/SpawnPreparerMain.cpp +0 -208
- data/src/cxx_supportlib/UnionStationFilterSupport.cpp +0 -67
- data/src/cxx_supportlib/UnionStationFilterSupport.h +0 -1622
- data/src/nodejs_supportlib/phusion_passenger/log_express.js +0 -106
- data/src/nodejs_supportlib/phusion_passenger/log_mongodb.js +0 -202
- data/src/nodejs_supportlib/phusion_passenger/ustreporter.js +0 -227
- data/src/nodejs_supportlib/phusion_passenger/ustrouter_connector.js +0 -448
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/CONFIG.md +0 -37
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/Gemfile +0 -17
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/Gemfile.lock +0 -59
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/README-API.md +0 -5
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/README.md +0 -117
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/Rakefile +0 -115
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core.rb +0 -423
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/api.rb +0 -238
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/connection.rb +0 -67
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/context.rb +0 -281
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/lock.rb +0 -62
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/log.rb +0 -66
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/message_channel.rb +0 -157
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter.rb +0 -150
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter/basics.rb +0 -199
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter/controllers.rb +0 -187
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter/misc.rb +0 -303
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter/view_rendering.rb +0 -91
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/simple_json.rb +0 -396
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/spec_helper.rb +0 -279
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/time_point.rb +0 -39
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/transaction.rb +0 -173
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/utils.rb +0 -177
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/version.rb +0 -32
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/version_data.rb +0 -44
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.example +0 -16
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis +0 -20
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis-with-sudo +0 -18
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/union_station_hooks_core.gemspec +0 -23
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/Gemfile +0 -14
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/Gemfile.lock +0 -45
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/LICENSE.md +0 -19
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/README.md +0 -104
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/Rakefile +0 -160
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails.rb +0 -200
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/action_controller_extension.rb +0 -45
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/action_view_subscriber.rb +0 -55
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/active_record_subscriber.rb +0 -41
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/active_support_benchmarkable_extension.rb +0 -47
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/active_support_cache_subscriber.rb +0 -79
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/exception_logger.rb +0 -57
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/version.rb +0 -32
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/version_data.rb +0 -44
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/union_station_hooks_rails.gemspec +0 -34
@@ -26,8 +26,14 @@
|
|
26
26
|
#ifndef _PASSENGER_SPAWNING_KIT_DUMMY_SPAWNER_H_
|
27
27
|
#define _PASSENGER_SPAWNING_KIT_DUMMY_SPAWNER_H_
|
28
28
|
|
29
|
-
#include <
|
29
|
+
#include <boost/shared_ptr.hpp>
|
30
30
|
#include <boost/atomic.hpp>
|
31
|
+
#include <vector>
|
32
|
+
|
33
|
+
#include <StaticString.h>
|
34
|
+
#include <Utils/StrIntUtils.h>
|
35
|
+
#include <Core/SpawningKit/Spawner.h>
|
36
|
+
#include <Core/SpawningKit/Exceptions.h>
|
31
37
|
|
32
38
|
namespace Passenger {
|
33
39
|
namespace SpawningKit {
|
@@ -41,38 +47,71 @@ class DummySpawner: public Spawner {
|
|
41
47
|
private:
|
42
48
|
boost::atomic<unsigned int> count;
|
43
49
|
|
50
|
+
void setConfigFromAppPoolOptions(Config *config, Json::Value &extraArgs,
|
51
|
+
const AppPoolOptions &options)
|
52
|
+
{
|
53
|
+
Spawner::setConfigFromAppPoolOptions(config, extraArgs, options);
|
54
|
+
config->spawnMethod = P_STATIC_STRING("dummy");
|
55
|
+
}
|
56
|
+
|
44
57
|
public:
|
45
58
|
unsigned int cleanCount;
|
46
59
|
|
47
|
-
DummySpawner(
|
48
|
-
: Spawner(
|
60
|
+
DummySpawner(Context *context)
|
61
|
+
: Spawner(context),
|
49
62
|
count(1),
|
50
63
|
cleanCount(0)
|
51
64
|
{ }
|
52
65
|
|
53
|
-
virtual Result spawn(const
|
66
|
+
virtual Result spawn(const AppPoolOptions &options) {
|
54
67
|
TRACE_POINT();
|
55
68
|
possiblyRaiseInternalError(options);
|
56
69
|
|
57
|
-
|
70
|
+
if (context->debugSupport != NULL) {
|
71
|
+
syscalls::usleep(context->debugSupport->dummySpawnDelay);
|
72
|
+
}
|
73
|
+
|
74
|
+
Config config;
|
75
|
+
Json::Value extraArgs;
|
76
|
+
setConfigFromAppPoolOptions(&config, extraArgs, options);
|
58
77
|
|
59
|
-
SocketPair adminSocket = createUnixSocketPair(__FILE__, __LINE__);
|
60
78
|
unsigned int number = count.fetch_add(1, boost::memory_order_relaxed);
|
61
79
|
Result result;
|
62
|
-
|
63
|
-
|
64
|
-
socket
|
65
|
-
socket
|
66
|
-
socket
|
67
|
-
socket
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
result
|
73
|
-
result
|
74
|
-
result
|
75
|
-
result.
|
80
|
+
Result::Socket socket;
|
81
|
+
|
82
|
+
socket.address = "tcp://127.0.0.1:1234";
|
83
|
+
socket.protocol = "session";
|
84
|
+
socket.concurrency = 1;
|
85
|
+
socket.acceptHttpRequests = true;
|
86
|
+
if (context->debugSupport != NULL) {
|
87
|
+
socket.concurrency = context->debugSupport->dummyConcurrency;
|
88
|
+
}
|
89
|
+
|
90
|
+
result.initialize(*context, &config);
|
91
|
+
result.pid = number;
|
92
|
+
result.dummy = true;
|
93
|
+
result.gupid = "gupid-" + toString(number);
|
94
|
+
result.spawnEndTime = result.spawnStartTime;
|
95
|
+
result.spawnEndTimeMonotonic = result.spawnStartTimeMonotonic;
|
96
|
+
result.sockets.push_back(socket);
|
97
|
+
|
98
|
+
vector<StaticString> internalFieldErrors;
|
99
|
+
vector<StaticString> appSuppliedFieldErrors;
|
100
|
+
if (!result.validate(internalFieldErrors, appSuppliedFieldErrors)) {
|
101
|
+
Journey journey(SPAWN_DIRECTLY, !config.genericApp && config.startsUsingWrapper);
|
102
|
+
journey.setStepErrored(SPAWNING_KIT_HANDSHAKE_PERFORM, true);
|
103
|
+
SpawnException e(INTERNAL_ERROR, journey, &config);
|
104
|
+
e.setSummary("Error spawning the web application:"
|
105
|
+
" a bug in " SHORT_PROGRAM_NAME " caused the"
|
106
|
+
" spawn result to be invalid: "
|
107
|
+
+ toString(internalFieldErrors)
|
108
|
+
+ ", " + toString(appSuppliedFieldErrors));
|
109
|
+
e.setProblemDescriptionHTML(
|
110
|
+
"Bug: the spawn result is invalid: "
|
111
|
+
+ toString(internalFieldErrors)
|
112
|
+
+ ", " + toString(appSuppliedFieldErrors));
|
113
|
+
throw e.finalize();
|
114
|
+
}
|
76
115
|
|
77
116
|
return result;
|
78
117
|
}
|
@@ -0,0 +1,117 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2014-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_SPAWNING_KIT_ERROR_RENDERER_H_
|
27
|
+
#define _PASSENGER_SPAWNING_KIT_ERROR_RENDERER_H_
|
28
|
+
|
29
|
+
#include <string>
|
30
|
+
#include <map>
|
31
|
+
#include <cctype>
|
32
|
+
|
33
|
+
#include <jsoncpp/json.h>
|
34
|
+
|
35
|
+
#include <Constants.h>
|
36
|
+
#include <StaticString.h>
|
37
|
+
#include <Utils/Template.h>
|
38
|
+
#include <Utils/IOUtils.h>
|
39
|
+
#include <Core/SpawningKit/Context.h>
|
40
|
+
#include <Core/SpawningKit/Exceptions.h>
|
41
|
+
|
42
|
+
namespace Passenger {
|
43
|
+
namespace SpawningKit {
|
44
|
+
|
45
|
+
using namespace std;
|
46
|
+
using namespace boost;
|
47
|
+
using namespace oxt;
|
48
|
+
|
49
|
+
|
50
|
+
class ErrorRenderer {
|
51
|
+
private:
|
52
|
+
string templatesDir;
|
53
|
+
|
54
|
+
public:
|
55
|
+
ErrorRenderer(const Context &context) {
|
56
|
+
templatesDir = context.resourceLocator->getResourcesDir() + "/templates/error_renderer";
|
57
|
+
}
|
58
|
+
|
59
|
+
string renderWithDetails(const SpawningKit::SpawnException &e) const {
|
60
|
+
StringMap<StaticString> params;
|
61
|
+
string htmlFile = templatesDir + "/with_details/src/index.html.template";
|
62
|
+
string cssFile = templatesDir + "/with_details/dist/styles.css";
|
63
|
+
string jsFile = templatesDir + "/with_details/dist/bundle.js";
|
64
|
+
string cssContent = readAll(cssFile);
|
65
|
+
string jsContent = readAll(jsFile);
|
66
|
+
|
67
|
+
Json::Value spec;
|
68
|
+
spec["program_name"] = PROGRAM_NAME;
|
69
|
+
spec["short_program_name"] = SHORT_PROGRAM_NAME;
|
70
|
+
spec["config"] = e.getConfig().getNonConfidentialFieldsToPassToApp();
|
71
|
+
spec["journey"] = e.getJourney().inspectAsJson();
|
72
|
+
spec["error"] = e.inspectBasicInfoAsJson();
|
73
|
+
spec["diagnostics"]["system_wide"] = e.inspectSystemWideDetailsAsJson();
|
74
|
+
spec["diagnostics"]["core_process"] = e.inspectParentProcessDetailsAsJson();
|
75
|
+
if (e.getJourney().getType() == SPAWN_THROUGH_PRELOADER) {
|
76
|
+
spec["diagnostics"]["preloader_process"] =
|
77
|
+
e.inspectPreloaderProcessDetailsAsJson();
|
78
|
+
}
|
79
|
+
spec["diagnostics"]["subprocess"] = e.inspectSubprocessDetailsAsJson();
|
80
|
+
|
81
|
+
string specContent = spec.toStyledString();
|
82
|
+
|
83
|
+
params.set("CSS", cssContent);
|
84
|
+
params.set("JS", jsContent);
|
85
|
+
params.set("TITLE", "Web application could not be started");
|
86
|
+
params.set("SPEC", specContent);
|
87
|
+
|
88
|
+
return Template::apply(readAll(htmlFile), params);
|
89
|
+
}
|
90
|
+
|
91
|
+
string renderWithoutDetails(const SpawningKit::SpawnException &e) const {
|
92
|
+
StringMap<StaticString> params;
|
93
|
+
string htmlFile = templatesDir + "/without_details/src/index.html.template";
|
94
|
+
string cssFile = templatesDir + "/without_details/dist/styles.css";
|
95
|
+
string jsFile = templatesDir + "/without_details/dist/bundle.js";
|
96
|
+
string cssContent = readAll(cssFile);
|
97
|
+
string jsContent = readAll(jsFile);
|
98
|
+
|
99
|
+
params.set("CSS", cssContent);
|
100
|
+
params.set("JS", jsContent);
|
101
|
+
params.set("TITLE", "Web application could not be started");
|
102
|
+
params.set("SUMMARY", e.getSummary());
|
103
|
+
params.set("ERROR_ID", e.getId());
|
104
|
+
params.set("PROGRAM_NAME", PROGRAM_NAME);
|
105
|
+
params.set("SHORT_PROGRAM_NAME", SHORT_PROGRAM_NAME);
|
106
|
+
params.set("PROGRAM_WEBSITE", PROGRAM_WEBSITE);
|
107
|
+
params.set("PROGRAM_AUTHOR", PROGRAM_AUTHOR);
|
108
|
+
|
109
|
+
return Template::apply(readAll(htmlFile), params);
|
110
|
+
}
|
111
|
+
};
|
112
|
+
|
113
|
+
|
114
|
+
} // namespace SpawningKit
|
115
|
+
} // namespace Passenger
|
116
|
+
|
117
|
+
#endif /* _PASSENGER_SPAWNING_KIT_ERROR_RENDERER_H_ */
|
@@ -0,0 +1,1157 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2011-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_SPAWNING_KIT_EXCEPTIONS_H_
|
27
|
+
#define _PASSENGER_SPAWNING_KIT_EXCEPTIONS_H_
|
28
|
+
|
29
|
+
#include <oxt/tracable_exception.hpp>
|
30
|
+
#include <string>
|
31
|
+
#include <stdexcept>
|
32
|
+
|
33
|
+
#include <Constants.h>
|
34
|
+
#include <Exceptions.h>
|
35
|
+
#include <LoggingKit/LoggingKit.h>
|
36
|
+
#include <DataStructures/StringKeyTable.h>
|
37
|
+
#include <ProcessManagement/Spawn.h>
|
38
|
+
#include <Utils/StrIntUtils.h>
|
39
|
+
#include <Utils/SystemMetricsCollector.h>
|
40
|
+
#include <Core/SpawningKit/Config.h>
|
41
|
+
#include <Core/SpawningKit/Journey.h>
|
42
|
+
|
43
|
+
extern "C" {
|
44
|
+
extern char **environ;
|
45
|
+
}
|
46
|
+
|
47
|
+
namespace Passenger {
|
48
|
+
namespace SpawningKit {
|
49
|
+
|
50
|
+
using namespace std;
|
51
|
+
using namespace oxt;
|
52
|
+
|
53
|
+
|
54
|
+
enum ErrorCategory {
|
55
|
+
INTERNAL_ERROR,
|
56
|
+
FILE_SYSTEM_ERROR,
|
57
|
+
OPERATING_SYSTEM_ERROR,
|
58
|
+
IO_ERROR,
|
59
|
+
TIMEOUT_ERROR,
|
60
|
+
|
61
|
+
UNKNOWN_ERROR_CATEGORY
|
62
|
+
};
|
63
|
+
|
64
|
+
inline StaticString errorCategoryToString(ErrorCategory category);
|
65
|
+
inline ErrorCategory inferErrorCategoryFromAnotherException(const std::exception &e,
|
66
|
+
JourneyStep failedJourneyStep);
|
67
|
+
|
68
|
+
|
69
|
+
/**
|
70
|
+
* For an introduction see README.md, section "Error reporting".
|
71
|
+
*/
|
72
|
+
class SpawnException: public oxt::tracable_exception {
|
73
|
+
private:
|
74
|
+
struct EnvDump {
|
75
|
+
pid_t pid;
|
76
|
+
string envvars;
|
77
|
+
string userInfo;
|
78
|
+
string ulimits;
|
79
|
+
|
80
|
+
EnvDump()
|
81
|
+
: pid(-1)
|
82
|
+
{ }
|
83
|
+
};
|
84
|
+
|
85
|
+
ErrorCategory category;
|
86
|
+
Journey journey;
|
87
|
+
Config config;
|
88
|
+
|
89
|
+
string summary;
|
90
|
+
string advancedProblemDetails;
|
91
|
+
string problemDescription;
|
92
|
+
string solutionDescription;
|
93
|
+
string stdoutAndErrData;
|
94
|
+
string id;
|
95
|
+
|
96
|
+
EnvDump parentProcessEnvDump;
|
97
|
+
EnvDump preloaderEnvDump;
|
98
|
+
EnvDump subprocessEnvDump;
|
99
|
+
string systemMetrics;
|
100
|
+
StringKeyTable<string> annotations;
|
101
|
+
|
102
|
+
static string createDefaultSummary(ErrorCategory category,
|
103
|
+
const Journey &journey, const StaticString &advancedProblemDetails)
|
104
|
+
{
|
105
|
+
string message;
|
106
|
+
|
107
|
+
switch (category) {
|
108
|
+
case TIMEOUT_ERROR:
|
109
|
+
// We only return a single error message instead of a customized
|
110
|
+
// one based on the failed step, because the timeout
|
111
|
+
// applies to the entire journey, not just to a specific step.
|
112
|
+
// A timeout at a specific step could be the result of a previous
|
113
|
+
// step taking too much time.
|
114
|
+
// The way to debug a timeout error is by looking at the timings
|
115
|
+
// of each step.
|
116
|
+
switch (journey.getType()) {
|
117
|
+
case START_PRELOADER:
|
118
|
+
message = "A timeout occurred while starting a preloader process";
|
119
|
+
break;
|
120
|
+
default:
|
121
|
+
message = "A timeout occurred while spawning an application process";
|
122
|
+
break;
|
123
|
+
}
|
124
|
+
default:
|
125
|
+
string categoryPhraseWithIndefiniteArticle =
|
126
|
+
getErrorCategoryPhraseWithIndefiniteArticle(
|
127
|
+
category, true);
|
128
|
+
switch (journey.getType()) {
|
129
|
+
case START_PRELOADER:
|
130
|
+
switch (journey.getFirstFailedStep()) {
|
131
|
+
case SPAWNING_KIT_PREPARATION:
|
132
|
+
message = categoryPhraseWithIndefiniteArticle
|
133
|
+
+ " occurred while preparing to start a preloader process";
|
134
|
+
break;
|
135
|
+
default:
|
136
|
+
message = categoryPhraseWithIndefiniteArticle
|
137
|
+
+ " occurred while starting a preloader process";
|
138
|
+
break;
|
139
|
+
}
|
140
|
+
default:
|
141
|
+
switch (journey.getFirstFailedStep()) {
|
142
|
+
case SPAWNING_KIT_PREPARATION:
|
143
|
+
message = categoryPhraseWithIndefiniteArticle
|
144
|
+
+ " occurred while preparing to spawn an application process";
|
145
|
+
break;
|
146
|
+
case SPAWNING_KIT_FORK_SUBPROCESS:
|
147
|
+
message = categoryPhraseWithIndefiniteArticle
|
148
|
+
+ " occurred while creating (forking) subprocess";
|
149
|
+
break;
|
150
|
+
case SPAWNING_KIT_CONNECT_TO_PRELOADER:
|
151
|
+
message = categoryPhraseWithIndefiniteArticle
|
152
|
+
+ " occurred while connecting to the preloader process";
|
153
|
+
break;
|
154
|
+
case SPAWNING_KIT_SEND_COMMAND_TO_PRELOADER:
|
155
|
+
message = categoryPhraseWithIndefiniteArticle
|
156
|
+
+ " occurred while sending a command to the preloader process";
|
157
|
+
break;
|
158
|
+
case SPAWNING_KIT_READ_RESPONSE_FROM_PRELOADER:
|
159
|
+
message = categoryPhraseWithIndefiniteArticle
|
160
|
+
+ " occurred while receiving a response from the preloader process";
|
161
|
+
break;
|
162
|
+
case SPAWNING_KIT_PARSE_RESPONSE_FROM_PRELOADER:
|
163
|
+
message = categoryPhraseWithIndefiniteArticle
|
164
|
+
+ " occurred while parsing a response from the preloader process";
|
165
|
+
break;
|
166
|
+
case SPAWNING_KIT_PROCESS_RESPONSE_FROM_PRELOADER:
|
167
|
+
message = categoryPhraseWithIndefiniteArticle
|
168
|
+
+ " occurred while processing a response from the preloader process";
|
169
|
+
break;
|
170
|
+
default:
|
171
|
+
message = categoryPhraseWithIndefiniteArticle
|
172
|
+
+ " occurred while spawning an application process";
|
173
|
+
break;
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
if (advancedProblemDetails.empty()) {
|
179
|
+
message.append(".");
|
180
|
+
} else {
|
181
|
+
message.append(": ");
|
182
|
+
message.append(advancedProblemDetails);
|
183
|
+
}
|
184
|
+
return message;
|
185
|
+
}
|
186
|
+
|
187
|
+
static string createDefaultProblemDescription(ErrorCategory category,
|
188
|
+
const Journey &journey, const Config &config,
|
189
|
+
const StaticString &advancedProblemDetails,
|
190
|
+
const StaticString &stdoutAndErrData)
|
191
|
+
{
|
192
|
+
StaticString categoryStringWithIndefiniteArticle =
|
193
|
+
getErrorCategoryPhraseWithIndefiniteArticle(category,
|
194
|
+
false);
|
195
|
+
|
196
|
+
switch (category) {
|
197
|
+
case INTERNAL_ERROR:
|
198
|
+
case OPERATING_SYSTEM_ERROR:
|
199
|
+
case IO_ERROR:
|
200
|
+
switch (journey.getType()) {
|
201
|
+
case START_PRELOADER:
|
202
|
+
switch (journey.getFirstFailedStep()) {
|
203
|
+
case SPAWNING_KIT_PREPARATION:
|
204
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
205
|
+
"The " PROGRAM_NAME " application server tried to"
|
206
|
+
" start the web application. In doing so, "
|
207
|
+
SHORT_PROGRAM_NAME " had to first start an internal"
|
208
|
+
" helper tool called the \"preloader\". But "
|
209
|
+
SHORT_PROGRAM_NAME " encountered "
|
210
|
+
+ categoryStringWithIndefiniteArticle +
|
211
|
+
" while performing this preparation work",
|
212
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
213
|
+
case SPAWNING_KIT_FORK_SUBPROCESS:
|
214
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
215
|
+
"The " PROGRAM_NAME " application server tried to"
|
216
|
+
" start the web application. But " SHORT_PROGRAM_NAME
|
217
|
+
" encountered " + categoryStringWithIndefiniteArticle
|
218
|
+
+ " while creating a subprocess",
|
219
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
220
|
+
case SPAWNING_KIT_HANDSHAKE_PERFORM:
|
221
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
222
|
+
"The " PROGRAM_NAME " application server tried to"
|
223
|
+
" start the web application. In doing so, "
|
224
|
+
SHORT_PROGRAM_NAME " first started an internal"
|
225
|
+
" helper tool called the \"preloader\". But "
|
226
|
+
SHORT_PROGRAM_NAME " encountered "
|
227
|
+
+ categoryStringWithIndefiniteArticle +
|
228
|
+
" while communicating with"
|
229
|
+
" this tool about its startup",
|
230
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
231
|
+
case SUBPROCESS_BEFORE_FIRST_EXEC:
|
232
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
233
|
+
"The " PROGRAM_NAME " application server tried to"
|
234
|
+
" start the web application. In doing so, "
|
235
|
+
SHORT_PROGRAM_NAME " had to first start an internal"
|
236
|
+
" helper tool called the \"preloader\". But"
|
237
|
+
" the subprocess which was supposed to execute this"
|
238
|
+
" preloader encountered "
|
239
|
+
+ categoryStringWithIndefiniteArticle,
|
240
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
241
|
+
case SUBPROCESS_OS_SHELL:
|
242
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
243
|
+
"The " PROGRAM_NAME " application server tried to"
|
244
|
+
" start the web application. In doing so, "
|
245
|
+
SHORT_PROGRAM_NAME " had to first start an internal"
|
246
|
+
" helper tool called the \"preloader\", which"
|
247
|
+
" in turn had to be started through the operating"
|
248
|
+
" system (OS) shell. But the OS shell encountered "
|
249
|
+
+ categoryStringWithIndefiniteArticle,
|
250
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
251
|
+
case SUBPROCESS_SPAWN_ENV_SETUPPER_BEFORE_SHELL:
|
252
|
+
case SUBPROCESS_SPAWN_ENV_SETUPPER_AFTER_SHELL:
|
253
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
254
|
+
"The " PROGRAM_NAME " application server tried to"
|
255
|
+
" start the web application. In doing so, "
|
256
|
+
SHORT_PROGRAM_NAME " had to first start an internal"
|
257
|
+
" helper tool called the \"preloader\", which"
|
258
|
+
" in turn had to be started through another internal"
|
259
|
+
" tool called the \"SpawnEnvSetupper\". But the"
|
260
|
+
" SpawnEnvSetupper encountered "
|
261
|
+
+ categoryStringWithIndefiniteArticle,
|
262
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
263
|
+
case SUBPROCESS_EXEC_WRAPPER:
|
264
|
+
if (!config.genericApp && config.startsUsingWrapper && config.wrapperSuppliedByThirdParty) {
|
265
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
266
|
+
"The " PROGRAM_NAME " application server tried to"
|
267
|
+
" start the web application through a "
|
268
|
+
SHORT_PROGRAM_NAME " helper tool called"
|
269
|
+
" the \"wrapper\". This helper tool is not part of "
|
270
|
+
SHORT_PROGRAM_NAME ". But " SHORT_PROGRAM_NAME
|
271
|
+
" was unable to execute that helper tool"
|
272
|
+
" because it encountered "
|
273
|
+
+ categoryStringWithIndefiniteArticle,
|
274
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
275
|
+
} else {
|
276
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
277
|
+
"The " PROGRAM_NAME " application server tried to"
|
278
|
+
" start the web application through a "
|
279
|
+
SHORT_PROGRAM_NAME "-internal helper tool called"
|
280
|
+
" the \"wrapper\". But " SHORT_PROGRAM_NAME
|
281
|
+
" was unable to execute that helper tool"
|
282
|
+
" because it encountered "
|
283
|
+
+ categoryStringWithIndefiniteArticle,
|
284
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
285
|
+
}
|
286
|
+
case SUBPROCESS_WRAPPER_PREPARATION:
|
287
|
+
if (!config.genericApp && config.startsUsingWrapper && config.wrapperSuppliedByThirdParty) {
|
288
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
289
|
+
"The " PROGRAM_NAME " application server tried to"
|
290
|
+
" start the web application through a "
|
291
|
+
SHORT_PROGRAM_NAME " helper tool called"
|
292
|
+
" the \"wrapper\"). This tool is not part of "
|
293
|
+
SHORT_PROGRAM_NAME ". But that helper tool encountered "
|
294
|
+
+ categoryStringWithIndefiniteArticle,
|
295
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
296
|
+
} else {
|
297
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
298
|
+
"The " PROGRAM_NAME " application server tried to"
|
299
|
+
" start the web application through a "
|
300
|
+
SHORT_PROGRAM_NAME "-internal helper tool called"
|
301
|
+
" the \"wrapper\"). But that helper tool encountered "
|
302
|
+
+ categoryStringWithIndefiniteArticle,
|
303
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
304
|
+
}
|
305
|
+
case SUBPROCESS_APP_LOAD_OR_EXEC:
|
306
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
307
|
+
"The " PROGRAM_NAME " application server tried to"
|
308
|
+
" start the web application. But the application"
|
309
|
+
" itself (and not " SHORT_PROGRAM_NAME ") encountered "
|
310
|
+
+ categoryStringWithIndefiniteArticle,
|
311
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
312
|
+
case SUBPROCESS_LISTEN:
|
313
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
314
|
+
"The " PROGRAM_NAME " application server tried to"
|
315
|
+
" start the web application. The application tried "
|
316
|
+
" to setup a socket for accepting connections,"
|
317
|
+
" but in doing so it encountered "
|
318
|
+
+ categoryStringWithIndefiniteArticle,
|
319
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
320
|
+
case SUBPROCESS_FINISH:
|
321
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
322
|
+
"The " PROGRAM_NAME " application server tried to"
|
323
|
+
" start the web application, but the application"
|
324
|
+
" encountered "
|
325
|
+
+ categoryStringWithIndefiniteArticle
|
326
|
+
+ " while finalizing its startup procedure",
|
327
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
328
|
+
default:
|
329
|
+
P_BUG("Unsupported preloader journey step "
|
330
|
+
<< toString((int) journey.getFirstFailedStep()));
|
331
|
+
}
|
332
|
+
default:
|
333
|
+
switch (journey.getFirstFailedStep()) {
|
334
|
+
case SPAWNING_KIT_PREPARATION:
|
335
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
336
|
+
"The " PROGRAM_NAME " application server tried to"
|
337
|
+
" start the web application, but " SHORT_PROGRAM_NAME
|
338
|
+
" encountered " + categoryStringWithIndefiniteArticle
|
339
|
+
+ " while performing preparation work",
|
340
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
341
|
+
case SPAWNING_KIT_FORK_SUBPROCESS:
|
342
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
343
|
+
"The " PROGRAM_NAME " application server tried to"
|
344
|
+
" start the web application. But " SHORT_PROGRAM_NAME
|
345
|
+
" encountered " + categoryStringWithIndefiniteArticle
|
346
|
+
+ " while creating a subprocess",
|
347
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
348
|
+
case SPAWNING_KIT_CONNECT_TO_PRELOADER:
|
349
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
350
|
+
"The " PROGRAM_NAME " application server tried to"
|
351
|
+
" start the web application by communicating with a"
|
352
|
+
" helper process that we call a \"preloader\". However, "
|
353
|
+
SHORT_PROGRAM_NAME " encountered "
|
354
|
+
+ categoryStringWithIndefiniteArticle
|
355
|
+
+ " while connecting to this helper process",
|
356
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
357
|
+
case SPAWNING_KIT_SEND_COMMAND_TO_PRELOADER:
|
358
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
359
|
+
"The " PROGRAM_NAME " application server tried to"
|
360
|
+
" start the web application by communicating with a"
|
361
|
+
" helper process that we call a \"preloader\". However, "
|
362
|
+
SHORT_PROGRAM_NAME " encountered "
|
363
|
+
+ categoryStringWithIndefiniteArticle
|
364
|
+
+ " while sending a command to this helper process",
|
365
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
366
|
+
case SPAWNING_KIT_READ_RESPONSE_FROM_PRELOADER:
|
367
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
368
|
+
"The " PROGRAM_NAME " application server tried to"
|
369
|
+
" start the web application by communicating with a"
|
370
|
+
" helper process that we call a \"preloader\". However, "
|
371
|
+
SHORT_PROGRAM_NAME " encountered "
|
372
|
+
+ categoryStringWithIndefiniteArticle
|
373
|
+
+ " while receiving a response to this helper process",
|
374
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
375
|
+
case SPAWNING_KIT_PARSE_RESPONSE_FROM_PRELOADER:
|
376
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
377
|
+
"The " PROGRAM_NAME " application server tried to"
|
378
|
+
" start the web application by communicating with a"
|
379
|
+
" helper process that we call a \"preloader\". However, "
|
380
|
+
SHORT_PROGRAM_NAME " encountered "
|
381
|
+
+ categoryStringWithIndefiniteArticle
|
382
|
+
+ " while parsing a response from this helper process",
|
383
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
384
|
+
case SPAWNING_KIT_PROCESS_RESPONSE_FROM_PRELOADER:
|
385
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
386
|
+
"The " PROGRAM_NAME " application server tried to"
|
387
|
+
" start the web application by communicating with a"
|
388
|
+
" helper process that we call a \"preloader\". However, "
|
389
|
+
SHORT_PROGRAM_NAME " encountered "
|
390
|
+
+ categoryStringWithIndefiniteArticle
|
391
|
+
+ " while processing a response from this helper process",
|
392
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
393
|
+
case SPAWNING_KIT_HANDSHAKE_PERFORM:
|
394
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
395
|
+
"The " PROGRAM_NAME " application server tried to"
|
396
|
+
" start the web application. Everything was looking OK,"
|
397
|
+
" but then suddenly " SHORT_PROGRAM_NAME " encountered "
|
398
|
+
+ categoryStringWithIndefiniteArticle,
|
399
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
400
|
+
case SUBPROCESS_BEFORE_FIRST_EXEC:
|
401
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
402
|
+
"The " PROGRAM_NAME " application server tried to"
|
403
|
+
" start the web application. " SHORT_PROGRAM_NAME
|
404
|
+
" launched a subprocess which was supposed to"
|
405
|
+
" execute the application, but instead that"
|
406
|
+
" subprocess encountered "
|
407
|
+
+ categoryStringWithIndefiniteArticle,
|
408
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
409
|
+
case SUBPROCESS_OS_SHELL:
|
410
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
411
|
+
"The " PROGRAM_NAME " application server tried to"
|
412
|
+
" start the web application through the operating"
|
413
|
+
" system (OS) shell. But the OS shell encountered "
|
414
|
+
+ categoryStringWithIndefiniteArticle,
|
415
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
416
|
+
case SUBPROCESS_SPAWN_ENV_SETUPPER_BEFORE_SHELL:
|
417
|
+
case SUBPROCESS_SPAWN_ENV_SETUPPER_AFTER_SHELL:
|
418
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
419
|
+
"The " PROGRAM_NAME " application server tried to"
|
420
|
+
" start the web application through a "
|
421
|
+
SHORT_PROGRAM_NAME "-internal helper tool called the"
|
422
|
+
" SpawnEnvSetupper. But that helper tool encountered "
|
423
|
+
+ categoryStringWithIndefiniteArticle,
|
424
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
425
|
+
case SUBPROCESS_EXEC_WRAPPER:
|
426
|
+
if (!config.genericApp && config.startsUsingWrapper && config.wrapperSuppliedByThirdParty) {
|
427
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
428
|
+
"The " PROGRAM_NAME " application server tried to"
|
429
|
+
" start the web application through a "
|
430
|
+
SHORT_PROGRAM_NAME " helper tool called"
|
431
|
+
" the \"wrapper\". This helper tool is not part of "
|
432
|
+
SHORT_PROGRAM_NAME ". But " SHORT_PROGRAM_NAME
|
433
|
+
" was unable to execute that helper tool because"
|
434
|
+
" it encountered "
|
435
|
+
+ categoryStringWithIndefiniteArticle,
|
436
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
437
|
+
} else {
|
438
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
439
|
+
"The " PROGRAM_NAME " application server tried to"
|
440
|
+
" start the web application through a "
|
441
|
+
SHORT_PROGRAM_NAME "-internal helper tool called"
|
442
|
+
" the \"wrapper\". But " SHORT_PROGRAM_NAME
|
443
|
+
" was unable to execute that helper tool because"
|
444
|
+
" it encountered "
|
445
|
+
+ categoryStringWithIndefiniteArticle,
|
446
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
447
|
+
}
|
448
|
+
case SUBPROCESS_WRAPPER_PREPARATION:
|
449
|
+
if (!config.genericApp && config.startsUsingWrapper && config.wrapperSuppliedByThirdParty) {
|
450
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
451
|
+
"The " PROGRAM_NAME " application server tried to"
|
452
|
+
" start the web application through a "
|
453
|
+
SHORT_PROGRAM_NAME " helper tool called"
|
454
|
+
" the \"wrapper\". This helper tool is not part of "
|
455
|
+
SHORT_PROGRAM_NAME ". But that helper tool encountered "
|
456
|
+
+ categoryStringWithIndefiniteArticle,
|
457
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
458
|
+
} else {
|
459
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
460
|
+
"The " PROGRAM_NAME " application server tried to"
|
461
|
+
" start the web application through a "
|
462
|
+
SHORT_PROGRAM_NAME "-internal helper tool called"
|
463
|
+
" the \"wrapper\". But that helper tool encountered "
|
464
|
+
+ categoryStringWithIndefiniteArticle,
|
465
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
466
|
+
}
|
467
|
+
case SUBPROCESS_APP_LOAD_OR_EXEC:
|
468
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
469
|
+
"The " PROGRAM_NAME " application server tried to"
|
470
|
+
" start the web application. But the application"
|
471
|
+
" itself (and not " SHORT_PROGRAM_NAME ") encountered "
|
472
|
+
+ categoryStringWithIndefiniteArticle,
|
473
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
474
|
+
case SUBPROCESS_PREPARE_AFTER_FORKING_FROM_PRELOADER:
|
475
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
476
|
+
"The " PROGRAM_NAME " application server tried to"
|
477
|
+
" start the web application through a "
|
478
|
+
SHORT_PROGRAM_NAME "-internal helper tool called"
|
479
|
+
" the \"preloader\". But the preloader encountered "
|
480
|
+
+ categoryStringWithIndefiniteArticle,
|
481
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
482
|
+
case SUBPROCESS_LISTEN:
|
483
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
484
|
+
"The " PROGRAM_NAME " application server tried to"
|
485
|
+
" start the web application. The application tried "
|
486
|
+
" to setup a socket for accepting connections,"
|
487
|
+
" but in doing so it encountered "
|
488
|
+
+ categoryStringWithIndefiniteArticle,
|
489
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
490
|
+
case SUBPROCESS_FINISH:
|
491
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
492
|
+
"The " PROGRAM_NAME " application server tried to"
|
493
|
+
" start the web application, but the application"
|
494
|
+
" encountered "
|
495
|
+
+ categoryStringWithIndefiniteArticle
|
496
|
+
+ " while finalizing its startup procedure",
|
497
|
+
category, advancedProblemDetails, stdoutAndErrData);
|
498
|
+
default:
|
499
|
+
P_BUG("Unrecognized journey step " <<
|
500
|
+
toString((int) journey.getFirstFailedStep()));
|
501
|
+
}
|
502
|
+
}
|
503
|
+
|
504
|
+
case TIMEOUT_ERROR:
|
505
|
+
// We only return a single error message instead of a customized
|
506
|
+
// one based on the failed step, because the timeout
|
507
|
+
// applies to the entire journey, not just to a specific step.
|
508
|
+
// A timeout at a specific step could be the result of a previous
|
509
|
+
// step taking too much time.
|
510
|
+
// The way to debug a timeout error is by looking at the timings
|
511
|
+
// of each step.
|
512
|
+
return wrapInParaAndMaybeAddErrorMessages(
|
513
|
+
"The " PROGRAM_NAME " application server tried"
|
514
|
+
" to start the web application, but this took too much time,"
|
515
|
+
" so " SHORT_PROGRAM_NAME " put a stop to that",
|
516
|
+
TIMEOUT_ERROR, string(), stdoutAndErrData);
|
517
|
+
|
518
|
+
default:
|
519
|
+
P_BUG("Unrecognized error category " + toString((int) category));
|
520
|
+
return string(); // Never reached, shut up compiler warning.
|
521
|
+
}
|
522
|
+
}
|
523
|
+
|
524
|
+
static string createDefaultSolutionDescription(ErrorCategory category,
|
525
|
+
const Journey &journey, const Config &config)
|
526
|
+
{
|
527
|
+
string message;
|
528
|
+
|
529
|
+
switch (category) {
|
530
|
+
case INTERNAL_ERROR:
|
531
|
+
return "<p class=\"sole-solution\">"
|
532
|
+
"Unfortunately, " SHORT_PROGRAM_NAME " does not know"
|
533
|
+
" how to solve this problem. Please try troubleshooting"
|
534
|
+
" the problem by studying the <strong>error message</strong>"
|
535
|
+
" and the <strong>diagnostics</strong> reports. You can also"
|
536
|
+
" consult <a href=\"" SUPPORT_URL "\">the " SHORT_PROGRAM_NAME
|
537
|
+
" support resources</a> for help.</p>";
|
538
|
+
|
539
|
+
case FILE_SYSTEM_ERROR:
|
540
|
+
return "<p class=\"sole-solution\">"
|
541
|
+
"Unfortunately, " SHORT_PROGRAM_NAME " does not know how to"
|
542
|
+
" solve this problem. But it looks like some kind of filesystem error."
|
543
|
+
" This generally means that you need to fix nonexistant"
|
544
|
+
" files/directories or fix filesystem permissions. Please"
|
545
|
+
" try troubleshooting the problem by studying the"
|
546
|
+
" <strong>error message</strong> and the"
|
547
|
+
" <strong>diagnostics</strong> reports.</p>";
|
548
|
+
|
549
|
+
case OPERATING_SYSTEM_ERROR:
|
550
|
+
case IO_ERROR:
|
551
|
+
return "<div class=\"multiple-solutions\">"
|
552
|
+
|
553
|
+
"<h3>Check whether the server is low on resources</h3>"
|
554
|
+
"<p>Maybe the server is currently low on resources. This would"
|
555
|
+
" cause errors to occur. Please study the <em>error"
|
556
|
+
" message</em> and the <em>diagnostics reports</em> to"
|
557
|
+
" verify whether this is the case. Key things to check for:</p>"
|
558
|
+
"<ul>"
|
559
|
+
"<li>Excessive CPU usage</li>"
|
560
|
+
"<li>Memory and swap</li>"
|
561
|
+
"<li>Ulimits</li>"
|
562
|
+
"</ul>"
|
563
|
+
"<p>If the server is indeed low on resources, find a way to"
|
564
|
+
" free up some resources.</p>"
|
565
|
+
|
566
|
+
"<h3>Check your (filesystem) security settings</h3>"
|
567
|
+
"<p>Maybe security settings are preventing " SHORT_PROGRAM_NAME
|
568
|
+
" from doing the work it needs to do. Please check whether the"
|
569
|
+
" error may be caused by your system's security settings, or"
|
570
|
+
" whether it may be caused by wrong permissions on a file or"
|
571
|
+
" directory.</p>"
|
572
|
+
|
573
|
+
"<h3>Still no luck?</h3>"
|
574
|
+
"<p>Please try troubleshooting the problem by studying the"
|
575
|
+
" <em>diagnostics</em> reports.</p>"
|
576
|
+
|
577
|
+
"</div>";
|
578
|
+
|
579
|
+
case TIMEOUT_ERROR:
|
580
|
+
message = "<div class=\"multiple-solutions\">"
|
581
|
+
|
582
|
+
"<h3>Check whether the server is low on resources</h3>"
|
583
|
+
"<p>Maybe the server is currently so low on resources that"
|
584
|
+
" all the work that needed to be done, could not finish within"
|
585
|
+
" the given time limit."
|
586
|
+
" Please inspect the server resource utilization statistics"
|
587
|
+
" in the <em>diagnostics</em> section to verify"
|
588
|
+
" whether server is indeed low on resources.</p>"
|
589
|
+
"<p>If so, then either increase the spawn timeout (currently"
|
590
|
+
" configured at " + toString(config.startTimeoutMsec / 1000)
|
591
|
+
+ " sec), or find a way to lower the server's resource"
|
592
|
+
" utilization.</p>";
|
593
|
+
|
594
|
+
switch (journey.getFirstFailedStep()) {
|
595
|
+
case SUBPROCESS_OS_SHELL:
|
596
|
+
message.append(
|
597
|
+
"<h3>Check whether your OS shell's startup scripts can"
|
598
|
+
" take a long time or get stuck</h3>"
|
599
|
+
"<p>One of your OS shell's startup scripts may do too much work,"
|
600
|
+
" or it may have invoked a command that then got stuck."
|
601
|
+
" Please investigate and debug your OS shell's startup"
|
602
|
+
" scripts.</p>");
|
603
|
+
break;
|
604
|
+
case SUBPROCESS_APP_LOAD_OR_EXEC:
|
605
|
+
if (config.appType == "node") {
|
606
|
+
message.append(
|
607
|
+
"<h3>Check whether the application calls <code>http.Server.listen()</code></h3>"
|
608
|
+
"<p>" SHORT_PROGRAM_NAME " requires that the application calls"
|
609
|
+
" <code>listen()</code> on an http.Server object. If"
|
610
|
+
" the application never calls this, then "
|
611
|
+
SHORT_PROGRAM_NAME " will think the application is"
|
612
|
+
" stuck. <a href=\"https://www.phusionpassenger.com/"
|
613
|
+
"library/indepth/nodejs/reverse_port_binding.html\">"
|
614
|
+
"Learn more about this problem.</a></p>");
|
615
|
+
}
|
616
|
+
message.append(
|
617
|
+
"<h3>Check whether the application is stuck during startup</h3>"
|
618
|
+
"<p>The easiest way find out where the application is stuck"
|
619
|
+
"is by inserting print statements into the application's code.</p>");
|
620
|
+
break;
|
621
|
+
default:
|
622
|
+
break;
|
623
|
+
}
|
624
|
+
|
625
|
+
message.append("<h3>Still no luck?</h3>"
|
626
|
+
"<p>Please try troubleshooting the problem by studying the"
|
627
|
+
" <em>diagnostics</em> reports.</p>"
|
628
|
+
|
629
|
+
"</div>");
|
630
|
+
return message;
|
631
|
+
|
632
|
+
default:
|
633
|
+
return "(error generating solution description: unknown error category)";
|
634
|
+
}
|
635
|
+
}
|
636
|
+
|
637
|
+
static string createDefaultAdvancedProblemDetails(const std::exception &e) {
|
638
|
+
const oxt::tracable_exception *te = dynamic_cast<const oxt::tracable_exception *>(&e);
|
639
|
+
if (te != NULL) {
|
640
|
+
return string(e.what()) + "\n" + te->backtrace();
|
641
|
+
} else {
|
642
|
+
return e.what();
|
643
|
+
}
|
644
|
+
}
|
645
|
+
|
646
|
+
static StaticString getErrorCategoryPhraseWithIndefiniteArticle(
|
647
|
+
ErrorCategory category, bool beginOfSentence)
|
648
|
+
{
|
649
|
+
switch (category) {
|
650
|
+
case INTERNAL_ERROR:
|
651
|
+
if (beginOfSentence) {
|
652
|
+
return P_STATIC_STRING("An internal error");
|
653
|
+
} else {
|
654
|
+
return P_STATIC_STRING("an internal error");
|
655
|
+
}
|
656
|
+
case FILE_SYSTEM_ERROR:
|
657
|
+
if (beginOfSentence) {
|
658
|
+
return P_STATIC_STRING("A file system error");
|
659
|
+
} else {
|
660
|
+
return P_STATIC_STRING("a file system error");
|
661
|
+
}
|
662
|
+
case OPERATING_SYSTEM_ERROR:
|
663
|
+
if (beginOfSentence) {
|
664
|
+
return P_STATIC_STRING("An operating system error");
|
665
|
+
} else {
|
666
|
+
return P_STATIC_STRING("an operating system error");
|
667
|
+
}
|
668
|
+
case IO_ERROR:
|
669
|
+
if (beginOfSentence) {
|
670
|
+
return P_STATIC_STRING("An I/O error");
|
671
|
+
} else {
|
672
|
+
return P_STATIC_STRING("an I/O error");
|
673
|
+
}
|
674
|
+
case TIMEOUT_ERROR:
|
675
|
+
if (beginOfSentence) {
|
676
|
+
return P_STATIC_STRING("A timeout error");
|
677
|
+
} else {
|
678
|
+
return P_STATIC_STRING("a timeout error");
|
679
|
+
}
|
680
|
+
default:
|
681
|
+
P_BUG("Unsupported error category " + toString((int) category));
|
682
|
+
return StaticString();
|
683
|
+
}
|
684
|
+
}
|
685
|
+
|
686
|
+
static StaticString getErrorCategoryPhraseWithIndefiniteArticle(
|
687
|
+
const std::exception &e, const Journey &journey,
|
688
|
+
bool beginOfSentence)
|
689
|
+
{
|
690
|
+
ErrorCategory category =
|
691
|
+
inferErrorCategoryFromAnotherException(
|
692
|
+
e, journey.getFirstFailedStep());
|
693
|
+
return getErrorCategoryPhraseWithIndefiniteArticle(category, beginOfSentence);
|
694
|
+
}
|
695
|
+
|
696
|
+
static string wrapInParaAndMaybeAddErrorMessages(const StaticString &message,
|
697
|
+
ErrorCategory category, const StaticString &advancedProblemDetails,
|
698
|
+
const StaticString &stdoutAndErrData)
|
699
|
+
{
|
700
|
+
string result = "<p>" + message + ".</p>";
|
701
|
+
if (!advancedProblemDetails.empty()) {
|
702
|
+
if (category == INTERNAL_ERROR || category == FILE_SYSTEM_ERROR) {
|
703
|
+
result.append("<p>Error details:</p>"
|
704
|
+
"<pre>" + escapeHTML(advancedProblemDetails) + "</pre>");
|
705
|
+
} else if (category == IO_ERROR) {
|
706
|
+
result.append("<p>The error reported by the I/O layer is:</p>"
|
707
|
+
"<pre>" + escapeHTML(advancedProblemDetails) + "</pre>");
|
708
|
+
} else {
|
709
|
+
P_ASSERT_EQ(category, OPERATING_SYSTEM_ERROR);
|
710
|
+
result.append("<p>The error reported by the operating system is:</p>"
|
711
|
+
"<pre>" + escapeHTML(advancedProblemDetails) + "</pre>");
|
712
|
+
}
|
713
|
+
}
|
714
|
+
if (!stdoutAndErrData.empty()) {
|
715
|
+
result.append("<p>The stdout/stderr output of the subprocess so far is:</p>"
|
716
|
+
"<pre>" + escapeHTML(stdoutAndErrData) + "</pre>");
|
717
|
+
}
|
718
|
+
return result;
|
719
|
+
}
|
720
|
+
|
721
|
+
static string gatherEnvvars() {
|
722
|
+
string result;
|
723
|
+
|
724
|
+
unsigned int i = 0;
|
725
|
+
while (environ[i] != NULL) {
|
726
|
+
result.append(environ[i]);
|
727
|
+
result.append(1, '\n');
|
728
|
+
i++;
|
729
|
+
}
|
730
|
+
|
731
|
+
return result;
|
732
|
+
}
|
733
|
+
|
734
|
+
static string gatherUlimits() {
|
735
|
+
// On Linux, ulimit is a shell builtin and not a command.
|
736
|
+
const char *command[] = { "/bin/sh", "-c", "ulimit -a", NULL };
|
737
|
+
try {
|
738
|
+
SubprocessInfo info;
|
739
|
+
string result;
|
740
|
+
runCommandAndCaptureOutput(command, info, result);
|
741
|
+
if (result.empty()) {
|
742
|
+
result.assign("Error: command 'ulimit -a' failed");
|
743
|
+
}
|
744
|
+
return result;
|
745
|
+
} catch (const SystemException &e) {
|
746
|
+
return P_STATIC_STRING("Error: command 'ulimit -a' failed: ") + e.what();
|
747
|
+
}
|
748
|
+
}
|
749
|
+
|
750
|
+
static string gatherUserInfo() {
|
751
|
+
const char *command[] = { "id", "-a", NULL };
|
752
|
+
try {
|
753
|
+
SubprocessInfo info;
|
754
|
+
string result;
|
755
|
+
runCommandAndCaptureOutput(command, info, result);
|
756
|
+
if (result.empty()) {
|
757
|
+
result.assign("Error: command 'id -a' failed");
|
758
|
+
}
|
759
|
+
return result;
|
760
|
+
} catch (const SystemException &e) {
|
761
|
+
return P_STATIC_STRING("Error: command 'id -a' failed: ") + e.what();
|
762
|
+
}
|
763
|
+
}
|
764
|
+
|
765
|
+
static string gatherSystemMetrics() {
|
766
|
+
SystemMetrics metrics;
|
767
|
+
|
768
|
+
try {
|
769
|
+
SystemMetricsCollector().collect(metrics);
|
770
|
+
} catch (const RuntimeException &e) {
|
771
|
+
return "Error: cannot parse system metrics: " + StaticString(e.what());
|
772
|
+
}
|
773
|
+
|
774
|
+
FastStringStream<> stream;
|
775
|
+
metrics.toDescription(stream);
|
776
|
+
return string(stream.data(), stream.size());
|
777
|
+
}
|
778
|
+
|
779
|
+
public:
|
780
|
+
SpawnException(ErrorCategory _category, const Journey &_journey,
|
781
|
+
const Config *_config)
|
782
|
+
: category(_category),
|
783
|
+
journey(_journey),
|
784
|
+
config(*_config)
|
785
|
+
{
|
786
|
+
assert(_journey.getFirstFailedStep() != UNKNOWN_JOURNEY_STEP);
|
787
|
+
config.internStrings();
|
788
|
+
}
|
789
|
+
|
790
|
+
SpawnException(const std::exception &originalException,
|
791
|
+
const Journey &_journey, const Config *_config)
|
792
|
+
: category(inferErrorCategoryFromAnotherException(
|
793
|
+
originalException, _journey.getFirstFailedStep())),
|
794
|
+
journey(_journey),
|
795
|
+
config(*_config),
|
796
|
+
summary(createDefaultSummary(
|
797
|
+
category, _journey, originalException.what())),
|
798
|
+
advancedProblemDetails(createDefaultAdvancedProblemDetails(originalException))
|
799
|
+
{
|
800
|
+
assert(_journey.getFirstFailedStep() != UNKNOWN_JOURNEY_STEP);
|
801
|
+
config.internStrings();
|
802
|
+
}
|
803
|
+
|
804
|
+
virtual ~SpawnException() throw() {}
|
805
|
+
|
806
|
+
|
807
|
+
virtual const char *what() const throw() {
|
808
|
+
return summary.c_str();
|
809
|
+
}
|
810
|
+
|
811
|
+
ErrorCategory getErrorCategory() const {
|
812
|
+
return category;
|
813
|
+
}
|
814
|
+
|
815
|
+
const Journey &getJourney() const {
|
816
|
+
return journey;
|
817
|
+
}
|
818
|
+
|
819
|
+
const Config &getConfig() const {
|
820
|
+
return config;
|
821
|
+
}
|
822
|
+
|
823
|
+
|
824
|
+
const string &getSummary() const {
|
825
|
+
return summary;
|
826
|
+
}
|
827
|
+
|
828
|
+
void setSummary(const string &value) {
|
829
|
+
summary = value;
|
830
|
+
}
|
831
|
+
|
832
|
+
const string &getAdvancedProblemDetails() const {
|
833
|
+
return advancedProblemDetails;
|
834
|
+
}
|
835
|
+
|
836
|
+
void setAdvancedProblemDetails(const string &value) {
|
837
|
+
advancedProblemDetails = value;
|
838
|
+
}
|
839
|
+
|
840
|
+
const string &getProblemDescriptionHTML() const {
|
841
|
+
return problemDescription;
|
842
|
+
}
|
843
|
+
|
844
|
+
void setProblemDescriptionHTML(const string &value) {
|
845
|
+
problemDescription = value;
|
846
|
+
}
|
847
|
+
|
848
|
+
const string &getSolutionDescriptionHTML() const {
|
849
|
+
return solutionDescription;
|
850
|
+
}
|
851
|
+
|
852
|
+
void setSolutionDescriptionHTML(const string &value) {
|
853
|
+
solutionDescription = value;
|
854
|
+
}
|
855
|
+
|
856
|
+
const string &getStdoutAndErrData() const {
|
857
|
+
return stdoutAndErrData;
|
858
|
+
}
|
859
|
+
|
860
|
+
void setStdoutAndErrData(const string &value) {
|
861
|
+
stdoutAndErrData = value;
|
862
|
+
}
|
863
|
+
|
864
|
+
const string &getId() const {
|
865
|
+
return id;
|
866
|
+
}
|
867
|
+
|
868
|
+
void setId(const string &value) {
|
869
|
+
id = value;
|
870
|
+
}
|
871
|
+
|
872
|
+
SpawnException &finalize() {
|
873
|
+
TRACE_POINT();
|
874
|
+
if (summary.empty()) {
|
875
|
+
summary = createDefaultSummary(category, journey,
|
876
|
+
advancedProblemDetails);
|
877
|
+
}
|
878
|
+
if (problemDescription.empty()) {
|
879
|
+
problemDescription = createDefaultProblemDescription(
|
880
|
+
category, journey, config, advancedProblemDetails,
|
881
|
+
stdoutAndErrData);
|
882
|
+
}
|
883
|
+
if (solutionDescription.empty()) {
|
884
|
+
solutionDescription = createDefaultSolutionDescription(
|
885
|
+
category, journey, config);
|
886
|
+
}
|
887
|
+
parentProcessEnvDump.pid = getpid();
|
888
|
+
parentProcessEnvDump.envvars = gatherEnvvars();
|
889
|
+
parentProcessEnvDump.userInfo = gatherUserInfo();
|
890
|
+
parentProcessEnvDump.ulimits = gatherUlimits();
|
891
|
+
systemMetrics = gatherSystemMetrics();
|
892
|
+
return *this;
|
893
|
+
}
|
894
|
+
|
895
|
+
|
896
|
+
const string &getParentProcessEnvvars() const {
|
897
|
+
return parentProcessEnvDump.envvars;
|
898
|
+
}
|
899
|
+
|
900
|
+
const string &getParentProcessUserInfo() const {
|
901
|
+
return parentProcessEnvDump.userInfo;
|
902
|
+
}
|
903
|
+
|
904
|
+
const string &getParentProcessUlimits() const {
|
905
|
+
return parentProcessEnvDump.ulimits;
|
906
|
+
}
|
907
|
+
|
908
|
+
|
909
|
+
pid_t getPreloaderPid() const {
|
910
|
+
return preloaderEnvDump.pid;
|
911
|
+
}
|
912
|
+
|
913
|
+
void setPreloaderPid(pid_t pid) {
|
914
|
+
preloaderEnvDump.pid = pid;
|
915
|
+
}
|
916
|
+
|
917
|
+
const string &getPreloaderEnvvars() const {
|
918
|
+
return preloaderEnvDump.envvars;
|
919
|
+
}
|
920
|
+
|
921
|
+
void setPreloaderEnvvars(const string &value) {
|
922
|
+
preloaderEnvDump.envvars = value;
|
923
|
+
}
|
924
|
+
|
925
|
+
const string &getPreloaderUserInfo() const {
|
926
|
+
return preloaderEnvDump.userInfo;
|
927
|
+
}
|
928
|
+
|
929
|
+
void setPreloaderUserInfo(const string &value) {
|
930
|
+
preloaderEnvDump.userInfo = value;
|
931
|
+
}
|
932
|
+
|
933
|
+
const string &getPreloaderUlimits() const {
|
934
|
+
return preloaderEnvDump.ulimits;
|
935
|
+
}
|
936
|
+
|
937
|
+
void setPreloaderUlimits(const string &value) {
|
938
|
+
preloaderEnvDump.ulimits = value;
|
939
|
+
}
|
940
|
+
|
941
|
+
|
942
|
+
pid_t getSubprocessPid() const {
|
943
|
+
return subprocessEnvDump.pid;
|
944
|
+
}
|
945
|
+
|
946
|
+
void setSubprocessPid(pid_t pid) {
|
947
|
+
subprocessEnvDump.pid = pid;
|
948
|
+
}
|
949
|
+
|
950
|
+
const string &getSubprocessEnvvars() const {
|
951
|
+
return subprocessEnvDump.envvars;
|
952
|
+
}
|
953
|
+
|
954
|
+
void setSubprocessEnvvars(const string &value) {
|
955
|
+
subprocessEnvDump.envvars = value;
|
956
|
+
}
|
957
|
+
|
958
|
+
const string &getSubprocessUserInfo() const {
|
959
|
+
return subprocessEnvDump.userInfo;
|
960
|
+
}
|
961
|
+
|
962
|
+
void setSubprocessUserInfo(const string &value) {
|
963
|
+
subprocessEnvDump.userInfo = value;
|
964
|
+
}
|
965
|
+
|
966
|
+
const string &getSubprocessUlimits() const {
|
967
|
+
return subprocessEnvDump.ulimits;
|
968
|
+
}
|
969
|
+
|
970
|
+
void setSubprocessUlimits(const string &value) {
|
971
|
+
subprocessEnvDump.ulimits = value;
|
972
|
+
}
|
973
|
+
|
974
|
+
|
975
|
+
const string &getSystemMetrics() const {
|
976
|
+
return systemMetrics;
|
977
|
+
}
|
978
|
+
|
979
|
+
const StringKeyTable<string> &getAnnotations() const {
|
980
|
+
return annotations;
|
981
|
+
}
|
982
|
+
|
983
|
+
void setAnnotation(const HashedStaticString &name, const string &value,
|
984
|
+
bool overwrite = true)
|
985
|
+
{
|
986
|
+
annotations.insert(name, value, overwrite);
|
987
|
+
}
|
988
|
+
|
989
|
+
Json::Value inspectBasicInfoAsJson() const {
|
990
|
+
Json::Value doc;
|
991
|
+
|
992
|
+
doc["category"] = errorCategoryToString(category).toString();
|
993
|
+
doc["summary"] = summary;
|
994
|
+
doc["problem_description_html"] = problemDescription;
|
995
|
+
doc["solution_description_html"] = solutionDescription;
|
996
|
+
if (!advancedProblemDetails.empty()) {
|
997
|
+
doc["aux_details"] = advancedProblemDetails;
|
998
|
+
}
|
999
|
+
if (!id.empty()) {
|
1000
|
+
doc["id"] = id;
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
return doc;
|
1004
|
+
}
|
1005
|
+
|
1006
|
+
Json::Value inspectSystemWideDetailsAsJson() const {
|
1007
|
+
Json::Value doc;
|
1008
|
+
|
1009
|
+
doc["system_metrics"] = systemMetrics;
|
1010
|
+
|
1011
|
+
return doc;
|
1012
|
+
}
|
1013
|
+
|
1014
|
+
Json::Value inspectParentProcessDetailsAsJson() const {
|
1015
|
+
Json::Value doc;
|
1016
|
+
|
1017
|
+
doc["backtrace"] = backtrace();
|
1018
|
+
doc["pid"] = (Json::Int) parentProcessEnvDump.pid;
|
1019
|
+
doc["envvars"] = getParentProcessEnvvars();
|
1020
|
+
doc["user_info"] = getParentProcessUserInfo();
|
1021
|
+
doc["ulimits"] = getParentProcessUlimits();
|
1022
|
+
|
1023
|
+
return doc;
|
1024
|
+
}
|
1025
|
+
|
1026
|
+
Json::Value inspectPreloaderProcessDetailsAsJson() const {
|
1027
|
+
Json::Value doc, annotations(Json::objectValue);
|
1028
|
+
|
1029
|
+
if (getPreloaderPid() != (pid_t) -1) {
|
1030
|
+
doc["pid"] = getPreloaderPid();
|
1031
|
+
}
|
1032
|
+
doc["envvars"] = getPreloaderEnvvars();
|
1033
|
+
doc["user_info"] = getPreloaderUserInfo();
|
1034
|
+
doc["ulimits"] = getPreloaderUlimits();
|
1035
|
+
|
1036
|
+
StringKeyTable<string>::ConstIterator it(this->annotations);
|
1037
|
+
while (*it != NULL) {
|
1038
|
+
annotations[it.getKey().toString()] = it.getValue();
|
1039
|
+
it.next();
|
1040
|
+
}
|
1041
|
+
doc["annotations"] = annotations;
|
1042
|
+
|
1043
|
+
return doc;
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
Json::Value inspectSubprocessDetailsAsJson() const {
|
1047
|
+
Json::Value doc, annotations(Json::objectValue);
|
1048
|
+
|
1049
|
+
if (getSubprocessPid() != (pid_t) -1) {
|
1050
|
+
doc["pid"] = getSubprocessPid();
|
1051
|
+
}
|
1052
|
+
doc["envvars"] = getSubprocessEnvvars();
|
1053
|
+
doc["user_info"] = getSubprocessUserInfo();
|
1054
|
+
doc["ulimits"] = getSubprocessUlimits();
|
1055
|
+
doc["stdout_and_err"] = getStdoutAndErrData();
|
1056
|
+
|
1057
|
+
StringKeyTable<string>::ConstIterator it(this->annotations);
|
1058
|
+
while (*it != NULL) {
|
1059
|
+
annotations[it.getKey().toString()] = it.getValue();
|
1060
|
+
it.next();
|
1061
|
+
}
|
1062
|
+
doc["annotations"] = annotations;
|
1063
|
+
|
1064
|
+
return doc;
|
1065
|
+
}
|
1066
|
+
};
|
1067
|
+
|
1068
|
+
|
1069
|
+
inline StaticString
|
1070
|
+
errorCategoryToString(ErrorCategory category) {
|
1071
|
+
switch (category) {
|
1072
|
+
case INTERNAL_ERROR:
|
1073
|
+
return P_STATIC_STRING("INTERNAL_ERROR");
|
1074
|
+
case FILE_SYSTEM_ERROR:
|
1075
|
+
return P_STATIC_STRING("FILE_SYSTEM_ERROR");
|
1076
|
+
case OPERATING_SYSTEM_ERROR:
|
1077
|
+
return P_STATIC_STRING("OPERATING_SYSTEM_ERROR");
|
1078
|
+
case IO_ERROR:
|
1079
|
+
return P_STATIC_STRING("IO_ERROR");
|
1080
|
+
case TIMEOUT_ERROR:
|
1081
|
+
return P_STATIC_STRING("TIMEOUT_ERROR");
|
1082
|
+
|
1083
|
+
case UNKNOWN_ERROR_CATEGORY:
|
1084
|
+
return P_STATIC_STRING("UNKNOWN_ERROR_CATEGORY");
|
1085
|
+
|
1086
|
+
default:
|
1087
|
+
return P_STATIC_STRING("(invalid value)");
|
1088
|
+
}
|
1089
|
+
}
|
1090
|
+
|
1091
|
+
inline bool
|
1092
|
+
_isFileSystemError(const std::exception &e) {
|
1093
|
+
if (dynamic_cast<const FileSystemException *>(&e) != NULL) {
|
1094
|
+
return true;
|
1095
|
+
}
|
1096
|
+
|
1097
|
+
const SystemException *sysEx = dynamic_cast<const SystemException *>(&e);
|
1098
|
+
if (sysEx != NULL) {
|
1099
|
+
return sysEx->code() == ENOENT
|
1100
|
+
|| sysEx->code() == ENAMETOOLONG
|
1101
|
+
|| sysEx->code() == EEXIST
|
1102
|
+
|| sysEx->code() == EACCES;
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
return false;
|
1106
|
+
}
|
1107
|
+
|
1108
|
+
inline bool
|
1109
|
+
_systemErrorIsActuallyIoError(JourneyStep failedJourneyStep) {
|
1110
|
+
return failedJourneyStep == SPAWNING_KIT_CONNECT_TO_PRELOADER
|
1111
|
+
|| failedJourneyStep == SPAWNING_KIT_SEND_COMMAND_TO_PRELOADER
|
1112
|
+
|| failedJourneyStep == SPAWNING_KIT_READ_RESPONSE_FROM_PRELOADER;
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
inline ErrorCategory
|
1116
|
+
inferErrorCategoryFromAnotherException(const std::exception &e,
|
1117
|
+
JourneyStep failedJourneyStep)
|
1118
|
+
{
|
1119
|
+
if (dynamic_cast<const SystemException *>(&e) != NULL) {
|
1120
|
+
if (_systemErrorIsActuallyIoError(failedJourneyStep)) {
|
1121
|
+
return IO_ERROR;
|
1122
|
+
} else {
|
1123
|
+
return OPERATING_SYSTEM_ERROR;
|
1124
|
+
}
|
1125
|
+
} else if (_isFileSystemError(e)) {
|
1126
|
+
return FILE_SYSTEM_ERROR;
|
1127
|
+
} else if (dynamic_cast<const IOException *>(&e) != NULL) {
|
1128
|
+
return IO_ERROR;
|
1129
|
+
} else if (dynamic_cast<const TimeoutException *>(&e) != NULL) {
|
1130
|
+
return TIMEOUT_ERROR;
|
1131
|
+
} else {
|
1132
|
+
return INTERNAL_ERROR;
|
1133
|
+
}
|
1134
|
+
}
|
1135
|
+
|
1136
|
+
inline ErrorCategory
|
1137
|
+
stringToErrorCategory(const StaticString &value) {
|
1138
|
+
if (value == P_STATIC_STRING("INTERNAL_ERROR")) {
|
1139
|
+
return INTERNAL_ERROR;
|
1140
|
+
} else if (value == P_STATIC_STRING("FILE_SYSTEM_ERROR")) {
|
1141
|
+
return FILE_SYSTEM_ERROR;
|
1142
|
+
} else if (value == P_STATIC_STRING("OPERATING_SYSTEM_ERROR")) {
|
1143
|
+
return OPERATING_SYSTEM_ERROR;
|
1144
|
+
} else if (value == P_STATIC_STRING("IO_ERROR")) {
|
1145
|
+
return IO_ERROR;
|
1146
|
+
} else if (value == P_STATIC_STRING("TIMEOUT_ERROR")) {
|
1147
|
+
return TIMEOUT_ERROR;
|
1148
|
+
} else {
|
1149
|
+
return UNKNOWN_ERROR_CATEGORY;
|
1150
|
+
}
|
1151
|
+
}
|
1152
|
+
|
1153
|
+
|
1154
|
+
} // namespace SpawningKit
|
1155
|
+
} // namespace Passenger
|
1156
|
+
|
1157
|
+
#endif /* _PASSENGER_SPAWNING_KIT_EXCEPTIONS_H_ */
|