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.

Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +18 -0
  3. data/Rakefile +20 -17
  4. data/bin/passenger-install-apache2-module +14 -11
  5. data/build/agent.rb +45 -18
  6. data/build/apache2.rb +32 -16
  7. data/build/basics.rb +29 -40
  8. data/build/common_library.rb +70 -54
  9. data/build/cxx_tests.rb +34 -43
  10. data/build/integration_tests.rb +10 -10
  11. data/build/misc.rb +6 -6
  12. data/build/node_tests.rb +1 -2
  13. data/build/oxt_tests.rb +7 -5
  14. data/build/packaging.rb +11 -441
  15. data/build/ruby_extension.rb +1 -1
  16. data/build/ruby_tests.rb +1 -2
  17. data/build/support/cplusplus.rb +6 -5
  18. data/build/support/cxx_dependency_map.rb +357 -833
  19. data/build/support/general.rb +23 -1
  20. data/build/test_basics.rb +3 -28
  21. data/dev/ci/tests/rpm/Jenkinsfile +68 -0
  22. data/dev/ci/tests/rpm/run +63 -0
  23. data/dev/ci/tests/source-packaging/run +1 -1
  24. data/dev/ci/tests/source-packaging/setup +1 -1
  25. data/doc/{Packaging.txt.md → Packaging.md} +0 -0
  26. data/resources/templates/apache2/deployment_example.txt.erb +2 -2
  27. data/resources/templates/apache2/multiple_apache_installations_detected.txt.erb +2 -2
  28. data/resources/templates/nginx/deployment_example.txt.erb +1 -1
  29. data/resources/templates/standalone/mass_deployment_default_server.erb +2 -2
  30. data/resources/templates/standalone/server.erb +2 -2
  31. data/src/agent/AgentMain.cpp +0 -4
  32. data/src/agent/Core/CoreMain.cpp +88 -5
  33. data/src/agent/Core/SpawningKit/Spawner.h +2 -1
  34. data/src/agent/Shared/Fundamentals/AbortHandler.cpp +1109 -0
  35. data/src/agent/Shared/Fundamentals/AbortHandler.h +63 -0
  36. data/src/agent/Shared/Fundamentals/Implementation.cpp +7 -0
  37. data/src/agent/Shared/Fundamentals/Initialization.cpp +614 -0
  38. data/src/agent/Shared/{Base.h → Fundamentals/Initialization.h} +23 -14
  39. data/src/agent/Shared/Fundamentals/Utils.cpp +127 -0
  40. data/src/agent/Shared/Fundamentals/Utils.h +46 -0
  41. data/src/agent/TempDirToucher/TempDirToucherMain.cpp +1 -1
  42. data/src/agent/Watchdog/CoreWatcher.cpp +3 -1
  43. data/src/agent/Watchdog/InstanceDirToucher.cpp +90 -53
  44. data/src/agent/Watchdog/WatchdogMain.cpp +13 -29
  45. data/src/apache2_module/Hooks.cpp +4 -1
  46. data/src/cxx_supportlib/ConfigKit/Store.h +32 -5
  47. data/src/cxx_supportlib/Constants.h +1 -2
  48. data/src/cxx_supportlib/Crypto.cpp +2 -1
  49. data/src/cxx_supportlib/Hooks.h +16 -37
  50. data/src/cxx_supportlib/LoggingKit/Context.h +22 -0
  51. data/src/cxx_supportlib/LoggingKit/Forward.h +1 -0
  52. data/src/cxx_supportlib/LoggingKit/Implementation.cpp +106 -22
  53. data/src/cxx_supportlib/ProcessManagement/Ruby.cpp +106 -0
  54. data/src/{agent/UstRouter/FileSink.h → cxx_supportlib/ProcessManagement/Ruby.h} +23 -47
  55. data/src/cxx_supportlib/ProcessManagement/Spawn.cpp +199 -0
  56. data/src/cxx_supportlib/ProcessManagement/Spawn.h +150 -0
  57. data/src/cxx_supportlib/ProcessManagement/Utils.cpp +459 -0
  58. data/src/cxx_supportlib/ProcessManagement/Utils.h +107 -0
  59. data/src/cxx_supportlib/Utils.cpp +41 -561
  60. data/src/cxx_supportlib/Utils.h +0 -68
  61. data/src/cxx_supportlib/Utils/AsyncSignalSafeUtils.h +187 -0
  62. data/src/cxx_supportlib/Utils/ProcessMetricsCollector.h +14 -2
  63. data/src/cxx_supportlib/WatchdogLauncher.h +2 -12
  64. data/src/cxx_supportlib/oxt/dynamic_thread_group.hpp +2 -2
  65. data/src/cxx_supportlib/vendor-modified/jsoncpp/json-forwards.h +4 -0
  66. data/src/cxx_supportlib/vendor-modified/jsoncpp/json.h +16 -1
  67. data/src/cxx_supportlib/vendor-modified/jsoncpp/jsoncpp.cpp +12 -9
  68. data/src/cxx_supportlib/vendor-modified/libev/ev++.h +4 -4
  69. data/src/cxx_supportlib/vendor-modified/libev/ev.h +3 -3
  70. data/src/nginx_module/CacheLocationConfig.c +0 -75
  71. data/src/nginx_module/CacheLocationConfig.c.cxxcodebuilder +1 -0
  72. data/src/nginx_module/Configuration.c +0 -1
  73. data/src/nginx_module/Configuration.h +0 -1
  74. data/src/nginx_module/ConfigurationCommands.c +1 -1
  75. data/src/nginx_module/ContentHandler.c +0 -1
  76. data/src/nginx_module/ContentHandler.h +0 -1
  77. data/src/nginx_module/CreateLocationConfig.c +0 -5
  78. data/src/nginx_module/CreateLocationConfig.c.cxxcodebuilder +1 -0
  79. data/src/nginx_module/LocationConfig.h +0 -4
  80. data/src/nginx_module/LocationConfig.h.cxxcodebuilder +2 -1
  81. data/src/nginx_module/MergeLocationConfig.c +0 -12
  82. data/src/nginx_module/MergeLocationConfig.c.cxxcodebuilder +1 -0
  83. data/src/nginx_module/ngx_http_passenger_module.h +0 -1
  84. data/src/ruby_supportlib/phusion_passenger.rb +1 -1
  85. data/src/ruby_supportlib/phusion_passenger/common_library.rb +20 -11
  86. data/src/ruby_supportlib/phusion_passenger/config/api_call_command.rb +1 -1
  87. data/src/ruby_supportlib/phusion_passenger/config/reopen_logs_command.rb +0 -1
  88. data/src/ruby_supportlib/phusion_passenger/config/validate_install_command.rb +10 -3
  89. data/src/ruby_supportlib/phusion_passenger/console_text_template.rb +3 -1
  90. data/src/ruby_supportlib/phusion_passenger/constants.rb +0 -1
  91. data/src/ruby_supportlib/phusion_passenger/debug_logging.rb +1 -1
  92. data/src/ruby_supportlib/phusion_passenger/loader_shared_helpers.rb +32 -6
  93. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +0 -1
  94. data/src/ruby_supportlib/phusion_passenger/packaging.rb +2 -4
  95. data/src/ruby_supportlib/phusion_passenger/platform_info/apache.rb +101 -20
  96. data/src/ruby_supportlib/phusion_passenger/platform_info/apache_detector.rb +21 -9
  97. data/src/ruby_supportlib/phusion_passenger/platform_info/compiler.rb +34 -31
  98. data/src/ruby_supportlib/phusion_passenger/platform_info/cxx_portability.rb +3 -1
  99. data/src/ruby_supportlib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +2 -14
  100. data/src/ruby_supportlib/phusion_passenger/platform_info/operating_system.rb +40 -3
  101. data/src/ruby_supportlib/phusion_passenger/standalone/app_finder.rb +15 -14
  102. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +1 -1
  103. data/src/ruby_supportlib/phusion_passenger/standalone/config_utils.rb +1 -1
  104. data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +8 -3
  105. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb +19 -18
  106. data/src/ruby_supportlib/phusion_passenger/standalone/stop_command.rb +6 -1
  107. data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller.rb +17 -1
  108. metadata +19 -97
  109. data/build/documentation.rb +0 -70
  110. data/doc/CloudLicensingConfiguration.html +0 -172
  111. data/doc/CloudLicensingConfiguration.txt.md +0 -3
  112. data/doc/Packaging.html +0 -488
  113. data/doc/Security of user switching support.idmap.txt +0 -34
  114. data/doc/Security of user switching support.txt +0 -197
  115. data/doc/ServerOptimizationGuide.html +0 -172
  116. data/doc/ServerOptimizationGuide.txt.md +0 -3
  117. data/doc/images/by_sa.png +0 -0
  118. data/doc/images/cloud_licensing_batch_job.png +0 -0
  119. data/doc/images/code_walkthrough.jpg +0 -0
  120. data/doc/images/direct_spawning.png +0 -0
  121. data/doc/images/direct_spawning.svg +0 -251
  122. data/doc/images/glyphicons-halflings-white.png +0 -0
  123. data/doc/images/glyphicons-halflings.png +0 -0
  124. data/doc/images/icons/README +0 -5
  125. data/doc/images/icons/callouts/1.png +0 -0
  126. data/doc/images/icons/callouts/10.png +0 -0
  127. data/doc/images/icons/callouts/11.png +0 -0
  128. data/doc/images/icons/callouts/12.png +0 -0
  129. data/doc/images/icons/callouts/13.png +0 -0
  130. data/doc/images/icons/callouts/14.png +0 -0
  131. data/doc/images/icons/callouts/15.png +0 -0
  132. data/doc/images/icons/callouts/2.png +0 -0
  133. data/doc/images/icons/callouts/3.png +0 -0
  134. data/doc/images/icons/callouts/4.png +0 -0
  135. data/doc/images/icons/callouts/5.png +0 -0
  136. data/doc/images/icons/callouts/6.png +0 -0
  137. data/doc/images/icons/callouts/7.png +0 -0
  138. data/doc/images/icons/callouts/8.png +0 -0
  139. data/doc/images/icons/callouts/9.png +0 -0
  140. data/doc/images/icons/caution.png +0 -0
  141. data/doc/images/icons/example.png +0 -0
  142. data/doc/images/icons/home.png +0 -0
  143. data/doc/images/icons/important.png +0 -0
  144. data/doc/images/icons/next.png +0 -0
  145. data/doc/images/icons/note.png +0 -0
  146. data/doc/images/icons/prev.png +0 -0
  147. data/doc/images/icons/tip.png +0 -0
  148. data/doc/images/icons/up.png +0 -0
  149. data/doc/images/icons/warning.png +0 -0
  150. data/doc/images/many_web_framework_protocols.png +0 -0
  151. data/doc/images/passenger_architecture.png +0 -0
  152. data/doc/images/passenger_architecture.svg +0 -385
  153. data/doc/images/passenger_architecture_overview.png +0 -0
  154. data/doc/images/passenger_core_architecture.png +0 -0
  155. data/doc/images/passenger_nodejs_architecture.svg +0 -558
  156. data/doc/images/phusion_banner.png +0 -0
  157. data/doc/images/rack.png +0 -0
  158. data/doc/images/smart_spawning.png +0 -0
  159. data/doc/images/smart_spawning.svg +0 -323
  160. data/doc/images/spawn_server_architecture.png +0 -0
  161. data/doc/images/spawn_server_architecture.svg +0 -655
  162. data/doc/images/spawning_preparation_work.png +0 -0
  163. data/doc/images/startup_sequence.png +0 -0
  164. data/doc/images/typical_isolated_web_application.png +0 -0
  165. data/doc/images/typical_isolated_web_application.svg +0 -213
  166. data/doc/users_guide_snippets/alternative_for_flying_passenger.txt +0 -1
  167. data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +0 -61
  168. data/doc/users_guide_snippets/appendix_a_about.txt +0 -13
  169. data/doc/users_guide_snippets/appendix_b_terminology.txt +0 -71
  170. data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +0 -36
  171. data/doc/users_guide_snippets/deployment_basics.txt +0 -37
  172. data/doc/users_guide_snippets/enterprise_only.txt +0 -1
  173. data/doc/users_guide_snippets/environment_variables.txt +0 -44
  174. data/doc/users_guide_snippets/global_queueing_explained.txt +0 -74
  175. data/doc/users_guide_snippets/installation.txt +0 -228
  176. data/doc/users_guide_snippets/installation/run_installer.txt +0 -58
  177. data/doc/users_guide_snippets/installation/verify_running_epilogue.txt +0 -6
  178. data/doc/users_guide_snippets/passenger_spawn_method.txt +0 -37
  179. data/doc/users_guide_snippets/rackup_specifications.txt +0 -1
  180. data/doc/users_guide_snippets/rvm_helper_tool.txt +0 -44
  181. data/doc/users_guide_snippets/since_version.txt +0 -1
  182. data/doc/users_guide_snippets/support_information.txt +0 -8
  183. data/doc/users_guide_snippets/tips.txt +0 -302
  184. data/doc/users_guide_snippets/troubleshooting/default.txt +0 -48
  185. data/doc/users_guide_snippets/troubleshooting/rails.txt +0 -59
  186. data/doc/users_guide_snippets/under_the_hood/page_caching_support.txt +0 -24
  187. data/doc/users_guide_snippets/under_the_hood/relationship_with_ruby.txt +0 -10
  188. data/doc/users_guide_snippets/where_to_get_support.txt +0 -9
  189. data/src/agent/Shared/Base.cpp +0 -1678
  190. data/src/agent/UstRouter/ApiServer.h +0 -292
  191. data/src/agent/UstRouter/Client.h +0 -112
  192. data/src/agent/UstRouter/Controller.h +0 -1309
  193. data/src/agent/UstRouter/LogSink.h +0 -145
  194. data/src/agent/UstRouter/OptionParser.h +0 -180
  195. data/src/agent/UstRouter/RemoteSender.h +0 -853
  196. data/src/agent/UstRouter/RemoteSink.h +0 -145
  197. data/src/agent/UstRouter/Transaction.h +0 -278
  198. data/src/agent/UstRouter/UstRouterMain.cpp +0 -681
  199. data/src/agent/Watchdog/UstRouterWatcher.cpp +0 -80
  200. data/src/ruby_supportlib/phusion_passenger/platform_info/macos.rb +0 -45
@@ -1,145 +0,0 @@
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_UST_ROUTER_REMOTE_SINK_H_
27
- #define _PASSENGER_UST_ROUTER_REMOTE_SINK_H_
28
-
29
- #include <string>
30
- #include <cstring>
31
- #include <ctime>
32
- #include <ev++.h>
33
- #include <LoggingKit/LoggingKit.h>
34
- #include <UstRouter/LogSink.h>
35
- #include <UstRouter/RemoteSender.h>
36
-
37
- namespace Passenger {
38
- namespace UstRouter {
39
-
40
- using namespace std;
41
- using namespace boost;
42
-
43
- inline RemoteSender &Controller_getRemoteSender(Controller *controller);
44
-
45
-
46
- class RemoteSink: public LogSink {
47
- private:
48
- bool realFlush() {
49
- if (bufferSize > 0) {
50
- P_DEBUG("Flushing " << inspect() << ": " << bufferSize << " bytes");
51
- lastFlushed = ev_now(Controller_getLoop(controller));
52
- StaticString data(buffer, bufferSize);
53
- Controller_getRemoteSender(controller).schedule(unionStationKey,
54
- nodeName, category, &data, 1);
55
- bufferSize = 0;
56
- return true;
57
- } else {
58
- P_DEBUG("Flushing remote sink " << inspect() << ": 0 bytes");
59
- return false;
60
- }
61
- }
62
-
63
- public:
64
- /* RemoteSender compresses the data with zlib before sending it
65
- * to the server. Even including Base64 and URL encoding overhead,
66
- * this compresses the data to about 25% of its original size.
67
- * Therefore we set a buffer capacity of a little less than 4 times
68
- * the TCP maximum segment size so that we can send as much
69
- * data as possible to the server in a single TCP segment.
70
- * With the "little less" we take into account:
71
- * - HTTPS overhead. This can be as high as 2 KB.
72
- * - The fact that RemoteSink.append() might try to flush the
73
- * current buffer. Observations have shown that the data
74
- * for a request transaction is often less than 5 KB.
75
- */
76
- static const unsigned int BUFFER_CAPACITY =
77
- 4 * 64 * 1024 -
78
- 16 * 1024;
79
-
80
- string unionStationKey;
81
- string nodeName;
82
- string category;
83
- char buffer[BUFFER_CAPACITY];
84
- unsigned int bufferSize;
85
-
86
- RemoteSink(Controller *controller, const string &_unionStationKey,
87
- const string &_nodeName, const string &_category)
88
- : LogSink(controller),
89
- unionStationKey(_unionStationKey),
90
- nodeName(_nodeName),
91
- category(_category),
92
- bufferSize(0)
93
- { }
94
-
95
- ~RemoteSink() {
96
- // Calling non-virtual flush method
97
- realFlush();
98
- }
99
-
100
- virtual bool isRemote() const {
101
- return true;
102
- }
103
-
104
- virtual void append(const TransactionPtr &transaction) {
105
- StaticString data = transaction->getBody();
106
- LogSink::append(transaction);
107
- if (bufferSize + data.size() > BUFFER_CAPACITY) {
108
- StaticString data2[] = {
109
- StaticString(buffer, bufferSize),
110
- data
111
- };
112
- Controller_getRemoteSender(controller).schedule(unionStationKey,
113
- nodeName, category, data2, 2);
114
- lastFlushed = ev_now(Controller_getLoop(controller));
115
- bufferSize = 0;
116
- } else {
117
- memcpy(buffer + bufferSize, data.data(), data.size());
118
- bufferSize += data.size();
119
- }
120
- }
121
-
122
- virtual bool flush() {
123
- return realFlush();
124
- }
125
-
126
- virtual Json::Value inspectStateAsJson() const {
127
- Json::Value doc = LogSink::inspectStateAsJson();
128
- doc["type"] = "remote";
129
- doc["key"] = unionStationKey;
130
- doc["node"] = nodeName;
131
- doc["category"] = category;
132
- doc["buffer_size"] = byteSizeToJson(bufferSize);
133
- return doc;
134
- }
135
-
136
- string inspect() const {
137
- return "RemoteSink(key=" + unionStationKey + ", node=" + nodeName + ", category=" + category + ")";
138
- }
139
- };
140
-
141
-
142
- } // namespace UstRouter
143
- } // namespace Passenger
144
-
145
- #endif /* _PASSENGER_UST_ROUTER_REMOTE_SINK_H_ */
@@ -1,278 +0,0 @@
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_UST_ROUTER_TRANSACTION_H_
27
- #define _PASSENGER_UST_ROUTER_TRANSACTION_H_
28
-
29
- #include <boost/shared_ptr.hpp>
30
- #include <boost/move/move.hpp>
31
- #include <boost/container/string.hpp>
32
- #include <boost/cstdint.hpp>
33
- #include <cstdlib>
34
- #include <cstring>
35
-
36
- #include <ev++.h>
37
- #include <StaticString.h>
38
- #include <MemoryKit/palloc.h>
39
- #include <DataStructures/LString.h>
40
- #include <Utils/JsonUtils.h>
41
-
42
- namespace Passenger {
43
- namespace UstRouter {
44
-
45
- using namespace std;
46
-
47
-
48
- class Transaction {
49
- private:
50
- BOOST_MOVABLE_BUT_NOT_COPYABLE(Transaction);
51
-
52
- unsigned int groupNameOffset;
53
- unsigned int nodeNameOffset;
54
- unsigned int categoryOffset;
55
- unsigned int unionStationKeyOffset;
56
- unsigned int filtersOffset;
57
-
58
- unsigned short groupNameSize, nodeNameSize, filtersSize;
59
- boost::uint8_t txnIdSize, unionStationKeySize, categorySize;
60
-
61
- ev_tstamp createdAt;
62
- unsigned int writeCount;
63
- unsigned int refCount;
64
- unsigned int bodyOffset;
65
- bool crashProtect, discarded;
66
-
67
- boost::container::string storage;
68
-
69
- template<typename IntegerType1, typename IntegerType2>
70
- void internString(const StaticString &str, IntegerType1 *offset, IntegerType2 *size) {
71
- if (offset != NULL) {
72
- *offset = bodyOffset;
73
- }
74
- storage.append(str.data(), str.size());
75
- storage.append(1, '\0');
76
- *size = str.size();
77
- bodyOffset += str.size() + 1;
78
- }
79
-
80
- public:
81
- Transaction(const StaticString &txnId, const StaticString &groupName,
82
- const StaticString &nodeName, const StaticString &category,
83
- const StaticString &unionStationKey, ev_tstamp _createdAt,
84
- const StaticString &filters = StaticString(),
85
- unsigned int initialCapacity = 1024 * 8)
86
- : createdAt(_createdAt),
87
- writeCount(0),
88
- refCount(0),
89
- bodyOffset(0),
90
- crashProtect(false),
91
- discarded(false)
92
- {
93
- internString(txnId, (boost::uint8_t *) NULL, &txnIdSize);
94
- internString(groupName, &groupNameOffset, &groupNameSize);
95
- internString(nodeName, &nodeNameOffset, &nodeNameSize);
96
- internString(category, &categoryOffset, &categorySize);
97
- internString(unionStationKey, &unionStationKeyOffset, &unionStationKeySize);
98
- internString(filters, &filtersOffset, &filtersSize);
99
- }
100
-
101
- Transaction(BOOST_RV_REF(Transaction) other)
102
- : groupNameOffset(other.groupNameOffset),
103
- nodeNameOffset(other.nodeNameOffset),
104
- categoryOffset(other.categoryOffset),
105
- unionStationKeyOffset(other.unionStationKeyOffset),
106
- filtersOffset(other.filtersOffset),
107
- groupNameSize(other.groupNameSize),
108
- nodeNameSize(other.nodeNameSize),
109
- filtersSize(other.filtersSize),
110
- txnIdSize(other.txnIdSize),
111
- unionStationKeySize(other.unionStationKeySize),
112
- categorySize(other.categorySize),
113
- createdAt(other.createdAt),
114
- writeCount(other.writeCount),
115
- refCount(other.refCount),
116
- bodyOffset(other.bodyOffset),
117
- crashProtect(other.crashProtect),
118
- discarded(other.discarded),
119
- storage(boost::move(other.storage))
120
- {
121
- other.groupNameOffset = 0;
122
- other.nodeNameOffset = 0;
123
- other.categoryOffset = 0;
124
- other.unionStationKeyOffset = 0;
125
- other.filtersOffset = 0;
126
- other.groupNameSize = 0;
127
- other.nodeNameSize = 0;
128
- other.filtersSize = 0;
129
- other.txnIdSize = 0;
130
- other.unionStationKeySize = 0;
131
- other.categorySize = 0;
132
- other.createdAt = 0;
133
- other.writeCount = 0;
134
- other.refCount = 0;
135
- other.bodyOffset = 0;
136
- other.crashProtect = false;
137
- other.discarded = true;
138
- }
139
-
140
- Transaction &operator=(BOOST_RV_REF(Transaction) other) {
141
- if (this != &other) {
142
- groupNameOffset = other.groupNameOffset;
143
- nodeNameOffset = other.nodeNameOffset;
144
- categoryOffset = other.categoryOffset;
145
- unionStationKeyOffset = other.unionStationKeyOffset;
146
- filtersOffset = other.filtersOffset;
147
- groupNameSize = other.groupNameSize;
148
- nodeNameSize = other.nodeNameSize;
149
- filtersSize = other.filtersSize;
150
- txnIdSize = other.txnIdSize;
151
- unionStationKeySize = other.unionStationKeySize;
152
- categorySize = other.categorySize;
153
- createdAt = other.createdAt;
154
- writeCount = other.writeCount;
155
- refCount = other.refCount;
156
- bodyOffset = other.bodyOffset;
157
- crashProtect = other.crashProtect;
158
- discarded = other.discarded;
159
- storage = boost::move(other.storage);
160
-
161
- other.groupNameOffset = 0;
162
- other.nodeNameOffset = 0;
163
- other.categoryOffset = 0;
164
- other.unionStationKeyOffset = 0;
165
- other.filtersOffset = 0;
166
- other.groupNameSize = 0;
167
- other.nodeNameSize = 0;
168
- other.filtersSize = 0;
169
- other.txnIdSize = 0;
170
- other.unionStationKeySize = 0;
171
- other.categorySize = 0;
172
- other.createdAt = 0;
173
- other.writeCount = 0;
174
- other.refCount = 0;
175
- other.bodyOffset = 0;
176
- other.crashProtect = false;
177
- other.discarded = true;
178
- }
179
- return *this;
180
- }
181
-
182
- StaticString getTxnId() const {
183
- return StaticString(storage.data(), txnIdSize);
184
- }
185
-
186
- StaticString getGroupName() const {
187
- return StaticString(storage.data() + groupNameOffset, groupNameSize);
188
- }
189
-
190
- StaticString getNodeName() const {
191
- return StaticString(storage.data() + nodeNameOffset, nodeNameSize);
192
- }
193
-
194
- StaticString getCategory() const {
195
- return StaticString(storage.data() + categoryOffset, categorySize);
196
- }
197
-
198
- StaticString getUnionStationKey() const {
199
- return StaticString(storage.data() + unionStationKeyOffset, unionStationKeySize);
200
- }
201
-
202
- StaticString getFilters() const {
203
- return StaticString(storage.data() + filtersOffset, filtersSize);
204
- }
205
-
206
- StaticString getBody() const {
207
- return StaticString(storage.data() + bodyOffset, storage.size() - bodyOffset);
208
- }
209
-
210
- bool crashProtectEnabled() const {
211
- return crashProtect;
212
- }
213
-
214
- void enableCrashProtect(bool v) {
215
- crashProtect = v;
216
- }
217
-
218
- bool isDiscarded() const {
219
- return discarded;
220
- }
221
-
222
- void discard() {
223
- discarded = true;
224
- }
225
-
226
- void ref() {
227
- refCount++;
228
- }
229
-
230
- void unref() {
231
- assert(refCount > 0);
232
- refCount--;
233
- }
234
-
235
- unsigned int getRefCount() const {
236
- return refCount;
237
- }
238
-
239
- void append(const StaticString &timestamp, const StaticString &data) {
240
- char txnIdCopy[txnIdSize];
241
- char writeCountStr[sizeof(unsigned int) * 2 + 1];
242
- unsigned int writeCountStrSize = integerToHexatri(
243
- writeCount, writeCountStr);
244
-
245
- memcpy(txnIdCopy, getTxnId().data(), getTxnId().size());
246
- writeCount++;
247
-
248
- storage.append(txnIdCopy, getTxnId().size());
249
- storage.append(1, ' ');
250
- storage.append(timestamp.data(), timestamp.size());
251
- storage.append(1, ' ');
252
- storage.append(writeCountStr, writeCountStrSize);
253
- storage.append(1, ' ');
254
- storage.append(data.data(), data.size());
255
- storage.append(1, '\n');
256
- }
257
-
258
- Json::Value inspectStateAsJson() const {
259
- Json::Value doc;
260
- doc["txn_id"] = getTxnId().toString();
261
- doc["created_at"] = timeToJson(createdAt * 1000000.0);
262
- doc["group"] = getGroupName().toString();
263
- doc["node"] = getNodeName().toString();
264
- doc["category"] = getCategory().toString();
265
- doc["key"] = getUnionStationKey().toString();
266
- doc["refcount"] = refCount;
267
- doc["body_size"] = byteSizeToJson(getBody().size());
268
- return doc;
269
- }
270
- };
271
-
272
- typedef boost::shared_ptr<Transaction> TransactionPtr;
273
-
274
-
275
- } // namespace UstRouter
276
- } // namespace Passenger
277
-
278
- #endif /* _PASSENGER_UST_ROUTER_TRANSACTION_H_ */
@@ -1,681 +0,0 @@
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
- // Include ev++.h early to avoid macro clash on EV_ERROR.
27
- #include <ev++.h>
28
-
29
- #include <oxt/system_calls.hpp>
30
- #include <oxt/backtrace.hpp>
31
- #include <oxt/thread.hpp>
32
-
33
- #include <sys/types.h>
34
- #include <sys/resource.h>
35
- #include <unistd.h>
36
- #include <pwd.h>
37
- #include <grp.h>
38
- #include <cstdio>
39
- #include <cstdlib>
40
- #include <cstring>
41
- #include <cerrno>
42
- #include <algorithm>
43
- #include <stdexcept>
44
- #include <stdlib.h>
45
- #include <signal.h>
46
-
47
- #include <Shared/Base.h>
48
- #include <Shared/ApiServerUtils.h>
49
- #include <UstRouter/OptionParser.h>
50
- #include <UstRouter/Controller.h>
51
- #include <UstRouter/ApiServer.h>
52
-
53
- #include <Exceptions.h>
54
- #include <FileDescriptor.h>
55
- #include <BackgroundEventLoop.h>
56
- #include <ResourceLocator.h>
57
- #include <Constants.h>
58
- #include <ConfigKit/VariantMapUtils.h>
59
- #include <Utils.h>
60
- #include <Utils/IOUtils.h>
61
- #include <Utils/StrIntUtils.h>
62
- #include <Utils/MessageIO.h>
63
- #include <Utils/VariantMap.h>
64
-
65
- using namespace oxt;
66
- using namespace Passenger;
67
-
68
-
69
- /***** Constants and working objects *****/
70
-
71
- namespace Passenger {
72
- namespace UstRouter {
73
- struct WorkingObjects {
74
- FileDescriptor serverSocketFd;
75
- vector<int> apiSockets;
76
- ResourceLocator *resourceLocator;
77
- ApiAccountDatabase apiAccountDatabase;
78
-
79
- BackgroundEventLoop *bgloop;
80
- ServerKit::Context *serverKitContext;
81
- Controller::Schema controllerSchema;
82
- Controller *controller;
83
-
84
- BackgroundEventLoop *apiBgloop;
85
- ServerKit::Context *apiServerKitContext;
86
- ServerKit::HttpServerSchema apiServerSchema;
87
- UstRouter::ApiServer *apiServer;
88
- EventFd exitEvent;
89
- EventFd allClientsDisconnectedEvent;
90
-
91
- struct ev_signal sigintWatcher;
92
- struct ev_signal sigtermWatcher;
93
- struct ev_signal sigquitWatcher;
94
- unsigned int terminationCount;
95
-
96
- WorkingObjects()
97
- : resourceLocator(NULL),
98
- bgloop(NULL),
99
- serverKitContext(NULL),
100
- controller(NULL),
101
- apiBgloop(NULL),
102
- apiServerKitContext(NULL),
103
- apiServer(NULL),
104
- exitEvent(__FILE__, __LINE__, "WorkingObjects: exitEvent"),
105
- allClientsDisconnectedEvent(__FILE__, __LINE__, "WorkingObjects: allClientsDisconnectedEvent"),
106
- terminationCount(0)
107
- { }
108
- };
109
- } // namespace UstRouter
110
- } // namespace Passenger
111
-
112
- using namespace Passenger::UstRouter;
113
-
114
- static VariantMap *agentsOptions;
115
- static WorkingObjects *workingObjects;
116
-
117
-
118
- /***** Functions *****/
119
-
120
- static void printInfo(EV_P_ struct ev_signal *watcher, int revents);
121
- static void printInfoInThread();
122
- static void onTerminationSignal(EV_P_ struct ev_signal *watcher, int revents);
123
- static void apiServerShutdownFinished(UstRouter::ApiServer *server);
124
- static void waitForExitEvent();
125
-
126
- void
127
- ustRouterFeedbackFdBecameReadable(ev::io &watcher, int revents) {
128
- /* This event indicates that the watchdog has been killed.
129
- * In this case we'll kill all descendant
130
- * processes and exit. There's no point in keeping this agent
131
- * running because we can't detect when the web server exits,
132
- * and because this agent doesn't own the server instance
133
- * directory. As soon as passenger-status is run, the server
134
- * instance directory will be cleaned up, making this agent's
135
- * services inaccessible.
136
- */
137
- syscalls::killpg(getpgrp(), SIGKILL);
138
- _exit(2); // In case killpg() fails.
139
- }
140
-
141
- static string
142
- findUnionStationGatewayCert(const ResourceLocator &locator,
143
- const string &cert)
144
- {
145
- if (cert.empty()) {
146
- return locator.getResourcesDir() + "/union_station_gateway.crt";
147
- } else if (cert != "-") {
148
- return cert;
149
- } else {
150
- return "";
151
- }
152
- }
153
-
154
- static void
155
- makeFileWorldReadableAndWritable(const string &path) {
156
- int ret;
157
-
158
- do {
159
- ret = chmod(path.c_str(), parseModeString("u=rw,g=rw,o=rw"));
160
- } while (ret == -1 && errno == EINTR);
161
- }
162
-
163
- static void
164
- initializePrivilegedWorkingObjects() {
165
- TRACE_POINT();
166
- VariantMap &options = *agentsOptions;
167
- WorkingObjects *wo = workingObjects = new WorkingObjects();
168
-
169
- options.set("ust_router_username", "logging");
170
-
171
- string password = options.get("ust_router_password", false);
172
- if (password.empty()) {
173
- password = strip(readAll(options.get("ust_router_password_file")));
174
- options.set("ust_router_password", password);
175
- }
176
-
177
- vector<string> authorizations = options.getStrSet("ust_router_authorizations",
178
- false);
179
- string description;
180
-
181
- UPDATE_TRACE_POINT();
182
- foreach (description, authorizations) {
183
- try {
184
- wo->apiAccountDatabase.add(description);
185
- } catch (const ArgumentException &e) {
186
- throw std::runtime_error(e.what());
187
- }
188
- }
189
-
190
- // Initialize ResourceLocator here in case passenger_root's parent
191
- // directory is not executable by the unprivileged user.
192
- wo->resourceLocator = new ResourceLocator(options.get("passenger_root"));
193
- }
194
-
195
- static void
196
- setUlimits() {
197
- TRACE_POINT();
198
- VariantMap &options = *agentsOptions;
199
-
200
- if (options.has("core_file_descriptor_ulimit")) {
201
- unsigned int number = options.getUint("core_file_descriptor_ulimit");
202
- struct rlimit limit;
203
- int ret;
204
-
205
- limit.rlim_cur = number;
206
- limit.rlim_max = number;
207
- do {
208
- ret = setrlimit(RLIMIT_NOFILE, &limit);
209
- } while (ret == -1 && errno == EINTR);
210
-
211
- if (ret == -1) {
212
- int e = errno;
213
- P_ERROR("Unable to set file descriptor ulimit to " << number
214
- << ": " << strerror(e) << " (errno=" << e << ")");
215
- }
216
- }
217
- }
218
-
219
- static void
220
- startListening() {
221
- TRACE_POINT();
222
- const VariantMap &options = *agentsOptions;
223
- WorkingObjects *wo = workingObjects;
224
- string address;
225
- vector<string> apiAddresses;
226
-
227
- address = options.get("ust_router_address");
228
- wo->serverSocketFd.assign(createServer(address, 0, true,
229
- __FILE__, __LINE__), NULL, 0);
230
- P_LOG_FILE_DESCRIPTOR_PURPOSE(wo->serverSocketFd,
231
- "Server address: " << wo->serverSocketFd);
232
- if (getSocketAddressType(address) == SAT_UNIX) {
233
- makeFileWorldReadableAndWritable(parseUnixSocketAddress(address));
234
- }
235
-
236
- UPDATE_TRACE_POINT();
237
- apiAddresses = options.getStrSet("ust_router_api_addresses",
238
- false);
239
- foreach (address, apiAddresses) {
240
- wo->apiSockets.push_back(createServer(address, 0, true,
241
- __FILE__, __LINE__));
242
- P_LOG_FILE_DESCRIPTOR_PURPOSE(wo->apiSockets.back(),
243
- "Server address: " << wo->apiSockets.back());
244
- if (getSocketAddressType(address) == SAT_UNIX) {
245
- makeFileWorldReadableAndWritable(parseUnixSocketAddress(address));
246
- }
247
- }
248
- }
249
-
250
- static void
251
- lowerPrivilege() {
252
- TRACE_POINT();
253
- const VariantMap &options = *agentsOptions;
254
- string userName = options.get("analytics_log_user", false);
255
-
256
- if (geteuid() == 0 && !userName.empty()) {
257
- string groupName = options.get("analytics_log_group", false);
258
- struct passwd *pwUser = getpwnam(userName.c_str());
259
- gid_t gid;
260
-
261
- if (pwUser == NULL) {
262
- throw RuntimeException("Cannot lookup user information for user " +
263
- userName);
264
- }
265
-
266
- if (groupName.empty()) {
267
- gid = pwUser->pw_gid;
268
- groupName = getGroupName(pwUser->pw_gid);
269
- } else {
270
- gid = lookupGid(groupName);
271
- }
272
-
273
- if (initgroups(userName.c_str(), gid) != 0) {
274
- int e = errno;
275
- throw SystemException("Unable to lower " SHORT_PROGRAM_NAME " UstRouter's privilege "
276
- "to that of user '" + userName + "' and group '" + groupName +
277
- "': cannot set supplementary groups", e);
278
- }
279
- if (setgid(gid) != 0) {
280
- int e = errno;
281
- throw SystemException("Unable to lower " SHORT_PROGRAM_NAME " UstRouter's privilege "
282
- "to that of user '" + userName + "' and group '" + groupName +
283
- "': cannot set group ID to " + toString(gid), e);
284
- }
285
- if (setuid(pwUser->pw_uid) != 0) {
286
- int e = errno;
287
- throw SystemException("Unable to lower " SHORT_PROGRAM_NAME " UstRouter's privilege "
288
- "to that of user '" + userName + "' and group '" + groupName +
289
- "': cannot set user ID to " + toString(pwUser->pw_uid), e);
290
- }
291
-
292
- setenv("USER", pwUser->pw_name, 1);
293
- setenv("HOME", pwUser->pw_dir, 1);
294
- setenv("UID", toString(gid).c_str(), 1);
295
- }
296
- }
297
-
298
- static void
299
- initializeUnprivilegedWorkingObjects() {
300
- TRACE_POINT();
301
- VariantMap &options = *agentsOptions;
302
- WorkingObjects *wo = workingObjects;
303
- int fd;
304
-
305
- options.set("union_station_gateway_cert", findUnionStationGatewayCert(
306
- *wo->resourceLocator, options.get("union_station_gateway_cert", false)));
307
-
308
- UPDATE_TRACE_POINT();
309
- wo->bgloop = new BackgroundEventLoop(true, true);
310
- wo->serverKitContext = new ServerKit::Context(wo->bgloop->safe,
311
- wo->bgloop->libuv_loop);
312
- wo->controller = new Controller(wo->serverKitContext,
313
- wo->controllerSchema,
314
- ConfigKit::variantMapToJson(wo->controllerSchema, options));
315
- wo->controller->initialize();
316
- wo->controller->listen(wo->serverSocketFd);
317
-
318
- UPDATE_TRACE_POINT();
319
- if (!wo->apiSockets.empty()) {
320
- wo->apiBgloop = new BackgroundEventLoop(true, true);
321
- wo->apiServerKitContext = new ServerKit::Context(wo->apiBgloop->safe,
322
- wo->apiBgloop->libuv_loop);
323
- wo->apiServer = new UstRouter::ApiServer(wo->apiServerKitContext,
324
- wo->apiServerSchema);
325
- wo->apiServer->controller = wo->controller;
326
- wo->apiServer->apiAccountDatabase = &wo->apiAccountDatabase;
327
- wo->apiServer->instanceDir = options.get("instance_dir", false);
328
- wo->apiServer->fdPassingPassword = options.get("watchdog_fd_passing_password", false);
329
- wo->apiServer->exitEvent = &wo->exitEvent;
330
- wo->apiServer->shutdownFinishCallback = apiServerShutdownFinished;
331
- wo->apiServer->initialize();
332
- foreach (fd, wo->apiSockets) {
333
- wo->apiServer->listen(fd);
334
- }
335
- }
336
-
337
- UPDATE_TRACE_POINT();
338
- ev_signal_init(&wo->sigquitWatcher, printInfo, SIGQUIT);
339
- ev_signal_start(wo->bgloop->libev_loop, &wo->sigquitWatcher);
340
- ev_signal_init(&wo->sigintWatcher, onTerminationSignal, SIGINT);
341
- ev_signal_start(wo->bgloop->libev_loop, &wo->sigintWatcher);
342
- ev_signal_init(&wo->sigtermWatcher, onTerminationSignal, SIGTERM);
343
- ev_signal_start(wo->bgloop->libev_loop, &wo->sigtermWatcher);
344
- }
345
-
346
- static void
347
- reportInitializationInfo() {
348
- TRACE_POINT();
349
- if (feedbackFdAvailable()) {
350
- P_NOTICE(SHORT_PROGRAM_NAME " UstRouter online, PID " << getpid());
351
- writeArrayMessage(FEEDBACK_FD,
352
- "initialized",
353
- NULL);
354
- } else {
355
- vector<string> apiAddresses = agentsOptions->getStrSet("ust_router_api_addresses", false);
356
-
357
- P_NOTICE(SHORT_PROGRAM_NAME " UstRouter online, PID " << getpid()
358
- << ", listening on " << agentsOptions->get("ust_router_address"));
359
-
360
- if (!apiAddresses.empty()) {
361
- string address;
362
- P_NOTICE("API server listening on " << apiAddresses.size() << " socket(s):");
363
- foreach (address, apiAddresses) {
364
- if (startsWith(address, "tcp://")) {
365
- address.erase(0, sizeof("tcp://") - 1);
366
- address.insert(0, "http://");
367
- address.append("/");
368
- }
369
- P_NOTICE(" * " << address);
370
- }
371
- }
372
- }
373
- }
374
-
375
- static void
376
- printInfo(EV_P_ struct ev_signal *watcher, int revents) {
377
- oxt::thread(printInfoInThread, "Information printer");
378
- }
379
-
380
- static void
381
- inspectControllerStateAsJson(Controller *controller, string *result) {
382
- *result = controller->inspectStateAsJson().toStyledString();
383
- }
384
-
385
- static void
386
- getMbufStats(struct MemoryKit::mbuf_pool *input, struct MemoryKit::mbuf_pool *result) {
387
- *result = *input;
388
- }
389
-
390
- static void
391
- printInfoInThread() {
392
- TRACE_POINT();
393
- WorkingObjects *wo = workingObjects;
394
-
395
- cerr << "### Backtraces\n";
396
- cerr << "\n" << oxt::thread::all_backtraces();
397
- cerr << "\n";
398
- cerr.flush();
399
-
400
- string json;
401
- cerr << "### Controller state\n";
402
- wo->bgloop->safe->runSync(boost::bind(inspectControllerStateAsJson,
403
- wo->controller, &json));
404
- cerr << json;
405
- cerr << "\n";
406
- cerr.flush();
407
-
408
- struct MemoryKit::mbuf_pool stats;
409
- cerr << "### mbuf stats\n\n";
410
- wo->bgloop->safe->runSync(boost::bind(getMbufStats,
411
- &wo->serverKitContext->mbuf_pool,
412
- &stats));
413
- cerr << "nfree_mbuf_blockq : " << stats.nfree_mbuf_blockq << "\n";
414
- cerr << "nactive_mbuf_blockq : " << stats.nactive_mbuf_blockq << "\n";
415
- cerr << "mbuf_block_chunk_size: " << stats.mbuf_block_chunk_size << "\n";
416
- cerr << "\n";
417
- cerr.flush();
418
- }
419
-
420
- static void
421
- onTerminationSignal(EV_P_ struct ev_signal *watcher, int revents) {
422
- WorkingObjects *wo = workingObjects;
423
-
424
- // Start output after '^C'
425
- printf("\n");
426
-
427
- wo->terminationCount++;
428
- if (wo->terminationCount < 3) {
429
- P_NOTICE("Signal received. Gracefully shutting down... (send signal " <<
430
- (3 - wo->terminationCount) << " more time(s) to force shutdown)");
431
- workingObjects->exitEvent.notify();
432
- } else {
433
- P_NOTICE("Signal received. Forcing shutdown.");
434
- _exit(2);
435
- }
436
- }
437
-
438
- static void
439
- mainLoop() {
440
- workingObjects->bgloop->start("Main event loop", 0);
441
- if (workingObjects->apiBgloop != NULL) {
442
- workingObjects->apiBgloop->start("API event loop", 0);
443
- }
444
- waitForExitEvent();
445
- }
446
-
447
- static void
448
- shutdownController() {
449
- workingObjects->controller->shutdown();
450
- }
451
-
452
- static void
453
- shutdownApiServer() {
454
- workingObjects->apiServer->shutdown();
455
- }
456
-
457
- static void
458
- apiServerShutdownFinished(UstRouter::ApiServer *server) {
459
- workingObjects->allClientsDisconnectedEvent.notify();
460
- }
461
-
462
- /* Wait until the watchdog closes the feedback fd (meaning it
463
- * was killed) or until we receive an exit message.
464
- */
465
- static void
466
- waitForExitEvent() {
467
- boost::this_thread::disable_syscall_interruption dsi;
468
- WorkingObjects *wo = workingObjects;
469
- fd_set fds;
470
- int largestFd = -1;
471
-
472
- FD_ZERO(&fds);
473
- if (feedbackFdAvailable()) {
474
- FD_SET(FEEDBACK_FD, &fds);
475
- largestFd = std::max(largestFd, FEEDBACK_FD);
476
- }
477
- FD_SET(wo->exitEvent.fd(), &fds);
478
- largestFd = std::max(largestFd, wo->exitEvent.fd());
479
-
480
- TRACE_POINT();
481
- if (syscalls::select(largestFd + 1, &fds, NULL, NULL, NULL) == -1) {
482
- int e = errno;
483
- throw SystemException("select() failed", e);
484
- }
485
-
486
- if (FD_ISSET(FEEDBACK_FD, &fds)) {
487
- UPDATE_TRACE_POINT();
488
- /* If the watchdog has been killed then we'll exit. There's no
489
- * point in keeping the UstRouter running because we can't
490
- * detect when the web server exits, and because this logging
491
- * agent doesn't own the instance directory. As soon as
492
- * passenger-status is run, the instance directory will be
493
- * cleaned up, making the server inaccessible.
494
- */
495
- _exit(2);
496
- } else {
497
- UPDATE_TRACE_POINT();
498
- /* We received an exit command. */
499
- P_NOTICE("Received command to shutdown gracefully. "
500
- "Waiting until all clients have disconnected...");
501
- wo->bgloop->safe->runLater(shutdownController);
502
- if (wo->apiBgloop != NULL) {
503
- wo->apiBgloop->safe->runLater(shutdownApiServer);
504
- }
505
-
506
- UPDATE_TRACE_POINT();
507
- FD_ZERO(&fds);
508
- FD_SET(wo->allClientsDisconnectedEvent.fd(), &fds);
509
- if (syscalls::select(wo->allClientsDisconnectedEvent.fd() + 1,
510
- &fds, NULL, NULL, NULL) == -1)
511
- {
512
- int e = errno;
513
- throw SystemException("select() failed", e);
514
- }
515
-
516
- P_INFO("All clients have now disconnected. Proceeding with graceful shutdown");
517
- }
518
- }
519
-
520
- static void
521
- cleanup() {
522
- TRACE_POINT();
523
- WorkingObjects *wo = workingObjects;
524
-
525
- P_DEBUG("Shutting down " SHORT_PROGRAM_NAME " UstRouter...");
526
- wo->bgloop->stop();
527
- if (wo->apiServer != NULL) {
528
- wo->apiBgloop->stop();
529
- delete wo->apiServer;
530
- }
531
- P_NOTICE(SHORT_PROGRAM_NAME " UstRouter shutdown finished");
532
- }
533
-
534
- static int
535
- runUstRouter() {
536
- TRACE_POINT();
537
- P_NOTICE("Starting " SHORT_PROGRAM_NAME " UstRouter...");
538
-
539
- try {
540
- UPDATE_TRACE_POINT();
541
- initializePrivilegedWorkingObjects();
542
- setUlimits();
543
- startListening();
544
- lowerPrivilege();
545
- initializeUnprivilegedWorkingObjects();
546
-
547
- UPDATE_TRACE_POINT();
548
- reportInitializationInfo();
549
- mainLoop();
550
-
551
- UPDATE_TRACE_POINT();
552
- cleanup();
553
- } catch (const tracable_exception &e) {
554
- P_ERROR("ERROR: " << e.what() << "\n" << e.backtrace());
555
- return 1;
556
- } catch (const std::runtime_error &e) {
557
- P_CRITICAL("ERROR: " << e.what());
558
- return 1;
559
- }
560
-
561
- return 0;
562
- }
563
-
564
-
565
- /***** Entry point and command line argument parsing *****/
566
-
567
- static void
568
- parseOptions(int argc, const char *argv[], VariantMap &options) {
569
- OptionParser p(ustRouterUsage);
570
- int i = 2;
571
-
572
- while (i < argc) {
573
- if (parseUstRouterOption(argc, argv, i, options)) {
574
- continue;
575
- } else if (p.isFlag(argv[i], 'h', "--help")) {
576
- ustRouterUsage();
577
- exit(0);
578
- } else {
579
- fprintf(stderr, "ERROR: unrecognized argument %s. Please type "
580
- "'%s ust-router --help' for usage.\n", argv[i], argv[0]);
581
- exit(1);
582
- }
583
- }
584
- }
585
-
586
- static void
587
- preinitialize(VariantMap &options) {
588
- // Set log_level here so that initializeAgent() calls setLogLevel()
589
- // and setLogFile() with the right value.
590
- if (options.has("ust_router_log_level")) {
591
- options.setInt("log_level", options.getInt("ust_router_log_level"));
592
- }
593
- if (options.has("ust_router_log_file")) {
594
- options.setInt("debug_log_file", options.getInt("ust_router_log_file"));
595
- }
596
- }
597
-
598
- static void
599
- setAgentsOptionsDefaults() {
600
- VariantMap &options = *agentsOptions;
601
-
602
- options.setDefault("ust_router_address", DEFAULT_UST_ROUTER_LISTEN_ADDRESS);
603
- options.setDefault("ust_router_default_node_name", getHostName());
604
- }
605
-
606
- static void
607
- sanityCheckOptions() {
608
- VariantMap &options = *agentsOptions;
609
- bool ok = true;
610
-
611
- if (!options.has("passenger_root")) {
612
- fprintf(stderr, "ERROR: please set the --passenger-root argument.\n");
613
- ok = false;
614
- }
615
-
616
- if (!options.has("ust_router_password")
617
- && !options.has("ust_router_password_file"))
618
- {
619
- fprintf(stderr, "ERROR: please set the --password-file argument.\n");
620
- ok = false;
621
- }
622
-
623
- if (options.getBool("ust_router_dev_mode", false, false)) {
624
- if (!options.has("ust_router_dump_dir")) {
625
- fprintf(stderr, "ERROR: if development mode is enabled, you must also set the --dump-dir argument.\n");
626
- ok = false;
627
- } else {
628
- FileType ft = getFileType(options.get("ust_router_dump_dir"));
629
- if (ft != FT_DIRECTORY) {
630
- fprintf(stderr, "ERROR: '%s' is not a valid directory.\n",
631
- options.get("ust_router_dump_dir").c_str());
632
- ok = false;
633
- }
634
- }
635
- }
636
-
637
- // Sanity check user accounts
638
- string user = options.get("analytics_log_user", false);
639
- if (!user.empty()) {
640
- struct passwd *pwUser = getpwnam(user.c_str());
641
- if (pwUser == NULL) {
642
- fprintf(stderr, "ERROR: the username specified by --user, '%s', does not exist.\n",
643
- user.c_str());
644
- ok = false;
645
- }
646
-
647
- string group = options.get("analytics_log_group", false);
648
- if (!group.empty() && lookupGid(group) == (gid_t) -1) {
649
- fprintf(stderr, "ERROR: the group name specified by --group, '%s', does not exist.\n",
650
- group.c_str());
651
- ok = false;
652
- }
653
- } else if (options.has("analytics_log_group")) {
654
- fprintf(stderr, "ERROR: setting --group also requires you to set --user.\n");
655
- ok = false;
656
- }
657
-
658
- if (!ok) {
659
- exit(1);
660
- }
661
- }
662
-
663
- int
664
- ustRouterMain(int argc, char *argv[]) {
665
- agentsOptions = new VariantMap();
666
- *agentsOptions = initializeAgent(argc, &argv, SHORT_PROGRAM_NAME " ust-router",
667
- parseOptions, preinitialize, 2);
668
-
669
- CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
670
- if (code != CURLE_OK) {
671
- P_CRITICAL("ERROR: Could not initialize libcurl: " << curl_easy_strerror(code));
672
- exit(1);
673
- }
674
-
675
- setAgentsOptionsDefaults();
676
- sanityCheckOptions();
677
-
678
- restoreOomScore(agentsOptions);
679
-
680
- return runUstRouter();
681
- }