passenger 4.0.48 → 4.0.49
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 +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/.editorconfig +36 -2
- data/.travis.yml +1 -1
- data/CHANGELOG +16 -0
- data/Rakefile +0 -1
- data/build/apache2.rb +4 -4
- data/build/common_library.rb +18 -18
- data/build/cplusplus_support.rb +2 -2
- data/build/documentation.rb +1 -1
- data/build/integration_tests.rb +12 -4
- data/build/misc.rb +12 -7
- data/build/packaging.rb +14 -14
- data/build/preprocessor.rb +10 -10
- data/build/rake_extensions.rb +11 -11
- data/build/ruby_extension.rb +2 -2
- data/dev/ci/inituidgid +24 -0
- data/dev/ci/run_jenkins.sh +57 -0
- data/dev/ci/run_rpm_tests.sh +77 -0
- data/dev/{run_travis.sh → ci/run_travis.sh} +60 -4
- data/doc/Users guide Nginx.txt +2 -2
- data/doc/users_guide_snippets/environment_variables.txt +0 -2
- data/doc/users_guide_snippets/tips.txt +20 -1
- data/ext/apache2/Bucket.cpp +18 -18
- data/ext/apache2/Bucket.h +4 -4
- data/ext/apache2/Configuration.cpp +7 -7
- data/ext/apache2/Configuration.hpp +43 -43
- data/ext/apache2/DirectoryMapper.h +5 -5
- data/ext/apache2/Hooks.cpp +142 -142
- data/ext/apache2/MergeDirConfig.cpp +40 -40
- data/ext/common/Account.h +17 -17
- data/ext/common/AccountsDatabase.h +9 -9
- data/ext/common/AgentsStarter.cpp +2 -2
- data/ext/common/AgentsStarter.h +40 -40
- data/ext/common/ApplicationPool2/Common.h +10 -6
- data/ext/common/ApplicationPool2/ComponentInfo.h +2 -2
- data/ext/common/ApplicationPool2/DirectSpawner.h +17 -17
- data/ext/common/ApplicationPool2/DummySpawner.h +5 -5
- data/ext/common/ApplicationPool2/Group.h +54 -38
- data/ext/common/ApplicationPool2/Implementation.cpp +76 -49
- data/ext/common/ApplicationPool2/Options.h +98 -91
- data/ext/common/ApplicationPool2/Pool.h +70 -69
- data/ext/common/ApplicationPool2/Process.h +21 -21
- data/ext/common/ApplicationPool2/Session.h +11 -11
- data/ext/common/ApplicationPool2/SmartSpawner.h +60 -60
- data/ext/common/ApplicationPool2/Socket.h +19 -19
- data/ext/common/ApplicationPool2/Spawner.h +64 -72
- data/ext/common/ApplicationPool2/SpawnerFactory.h +4 -4
- data/ext/common/ApplicationPool2/SuperGroup.h +41 -41
- data/ext/common/BackgroundEventLoop.cpp +1 -1
- data/ext/common/BackgroundEventLoop.h +2 -2
- data/ext/common/Constants.h +1 -1
- data/ext/common/EventedBufferedInput.h +5 -5
- data/ext/common/EventedClient.h +51 -51
- data/ext/common/EventedMessageServer.h +39 -39
- data/ext/common/EventedServer.h +32 -32
- data/ext/common/Exceptions.h +23 -23
- data/ext/common/FileDescriptor.h +18 -18
- data/ext/common/Logging.cpp +1 -1
- data/ext/common/MessageClient.h +27 -27
- data/ext/common/MessageReadersWriters.h +79 -79
- data/ext/common/MessageServer.h +59 -59
- data/ext/common/RandomGenerator.h +12 -12
- data/ext/common/ResourceLocator.h +8 -8
- data/ext/common/SafeLibev.h +54 -25
- data/ext/common/ServerInstanceDir.h +31 -31
- data/ext/common/StaticString.h +50 -48
- data/ext/common/Utils.cpp +73 -78
- data/ext/common/Utils.h +6 -6
- data/ext/common/Utils/Base64.cpp +3 -3
- data/ext/common/Utils/Base64.h +7 -7
- data/ext/common/Utils/BlockingQueue.h +9 -9
- data/ext/common/Utils/BufferedIO.h +17 -17
- data/ext/common/Utils/CachedFileStat.hpp +16 -16
- data/ext/common/Utils/Dechunker.h +25 -25
- data/ext/common/Utils/FileChangeChecker.h +10 -10
- data/ext/common/Utils/MemZeroGuard.h +5 -5
- data/ext/common/Utils/MemoryBarrier.h +1 -1
- data/ext/common/Utils/MessageIO.h +61 -61
- data/ext/common/Utils/ProcessMetricsCollector.h +40 -40
- data/ext/common/Utils/ScopeGuard.h +7 -7
- data/ext/common/Utils/SpeedMeter.h +1 -1
- data/ext/common/Utils/StrIntUtils.cpp +13 -13
- data/ext/common/Utils/StrIntUtils.h +3 -3
- data/ext/common/Utils/StringScanning.h +5 -5
- data/ext/common/Utils/SystemMetricsCollector.h +2 -2
- data/ext/common/Utils/SystemTime.h +10 -10
- data/ext/common/Utils/Template.h +2 -2
- data/ext/common/Utils/Timer.h +6 -6
- data/ext/common/Utils/VariantMap.h +29 -29
- data/ext/common/agents/Base.cpp +19 -19
- data/ext/common/agents/HelperAgent/AgentOptions.h +1 -1
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +6 -6
- data/ext/common/agents/HelperAgent/Main.cpp +44 -43
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +4 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +29 -28
- data/ext/common/agents/HelperAgent/ScgiRequestParser.h +56 -50
- data/ext/common/agents/LoggingAgent/AdminController.h +8 -8
- data/ext/common/agents/LoggingAgent/DataStoreId.h +17 -17
- data/ext/common/agents/LoggingAgent/FilterSupport.h +167 -167
- data/ext/common/agents/LoggingAgent/LoggingServer.h +122 -122
- data/ext/common/agents/LoggingAgent/Main.cpp +7 -7
- data/ext/common/agents/LoggingAgent/RemoteSender.h +54 -54
- data/ext/common/agents/SpawnPreparer.cpp +4 -4
- data/ext/common/agents/TempDirToucher.c +2 -2
- data/ext/common/agents/Watchdog/AgentWatcher.cpp +47 -47
- data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +7 -7
- data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +7 -7
- data/ext/common/agents/Watchdog/Main.cpp +22 -22
- data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +9 -9
- data/ext/libeio/eio.c +1 -1
- data/ext/nginx/Configuration.c +30 -30
- data/ext/nginx/Configuration.h +1 -1
- data/ext/nginx/ContentHandler.c +54 -54
- data/ext/nginx/ContentHandler.h +3 -3
- data/ext/nginx/StaticContentHandler.c +2 -2
- data/ext/nginx/ngx_http_passenger_module.c +21 -21
- data/ext/oxt/detail/backtrace_enabled.hpp +1 -1
- data/ext/oxt/detail/context.hpp +1 -1
- data/ext/oxt/detail/spin_lock_darwin.hpp +4 -4
- data/ext/oxt/detail/spin_lock_gcc_x86.hpp +3 -3
- data/ext/oxt/detail/spin_lock_pthreads.hpp +4 -4
- data/ext/oxt/detail/tracable_exception_disabled.hpp +1 -1
- data/ext/oxt/dynamic_thread_group.hpp +18 -18
- data/ext/oxt/implementation.cpp +9 -8
- data/ext/oxt/macros.hpp +2 -2
- data/ext/oxt/system_calls.cpp +11 -11
- data/ext/oxt/system_calls.hpp +13 -13
- data/ext/oxt/thread.hpp +22 -14
- data/ext/ruby/passenger_native_support.c +55 -55
- data/lib/phusion_passenger.rb +24 -24
- data/lib/phusion_passenger/common_library.rb +2 -0
- data/lib/phusion_passenger/loader_shared_helpers.rb +18 -18
- data/lib/phusion_passenger/packaging.rb +9 -4
- data/lib/phusion_passenger/platform_info/apache.rb +45 -31
- data/lib/phusion_passenger/platform_info/compiler.rb +11 -11
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
- data/lib/phusion_passenger/request_handler/thread_handler.rb +8 -8
- data/lib/phusion_passenger/standalone/app_finder.rb +16 -16
- data/lib/phusion_passenger/standalone/command.rb +22 -22
- data/packaging/rpm/LICENSE.txt +19 -0
- data/packaging/rpm/Makefile +13 -0
- data/packaging/rpm/README.md +41 -0
- data/packaging/rpm/Vagrantfile +38 -0
- data/{rpm/Vagrantfile → packaging/rpm/Vagrantfile.centos} +0 -0
- data/packaging/rpm/build +170 -0
- data/packaging/rpm/create_project +41 -0
- data/packaging/rpm/git_update +88 -0
- data/packaging/rpm/image/Dockerfile +37 -0
- data/packaging/rpm/image/Gemfile +3 -0
- data/packaging/rpm/image/Gemfile.lock +12 -0
- data/packaging/rpm/image/RPM-GPG-KEY-amazon-ga +19 -0
- data/packaging/rpm/image/amazon2014-i386.cfg +96 -0
- data/packaging/rpm/image/amazon2014-x86_64.cfg +96 -0
- data/packaging/rpm/image/site-defaults.cfg +168 -0
- data/packaging/rpm/internal/build_tasks.rb +238 -0
- data/packaging/rpm/internal/dummygpg +11 -0
- data/packaging/rpm/internal/exec_build +42 -0
- data/packaging/rpm/internal/get_distro_arch +14 -0
- data/packaging/rpm/internal/get_distro_id +10 -0
- data/packaging/rpm/internal/git_update +27 -0
- data/packaging/rpm/internal/inituidgid +17 -0
- data/packaging/rpm/internal/my_init +344 -0
- data/packaging/rpm/internal/python27 +3 -0
- data/packaging/rpm/internal/repo_update +46 -0
- data/packaging/rpm/internal/setuser +26 -0
- data/packaging/rpm/internal/tracking_helper +40 -0
- data/packaging/rpm/jenkins_release +99 -0
- data/packaging/rpm/lib/build_tasks_support.rb +402 -0
- data/packaging/rpm/lib/preprocessor.rb +341 -0
- data/packaging/rpm/nginx_spec/404.html +119 -0
- data/packaging/rpm/nginx_spec/50x.html +119 -0
- data/packaging/rpm/nginx_spec/index.html +116 -0
- data/packaging/rpm/nginx_spec/nginx-auto-cc-gcc.patch +13 -0
- data/packaging/rpm/nginx_spec/nginx-logo.png +0 -0
- data/packaging/rpm/nginx_spec/nginx-upgrade +13 -0
- data/packaging/rpm/nginx_spec/nginx-upgrade.8 +151 -0
- data/packaging/rpm/nginx_spec/nginx.conf +131 -0
- data/packaging/rpm/nginx_spec/nginx.init +144 -0
- data/packaging/rpm/nginx_spec/nginx.logrotate +13 -0
- data/packaging/rpm/nginx_spec/nginx.service +15 -0
- data/packaging/rpm/nginx_spec/nginx.spec.template +559 -0
- data/packaging/rpm/nginx_spec/nginx.sysconfig +4 -0
- data/packaging/rpm/nginx_spec/passenger.conf +9 -0
- data/packaging/rpm/nginx_spec/poweredby.png +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/apache-passenger.conf.in +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/config.json +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger.logrotate +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger.spec.template +58 -31
- data/{rpm → packaging/rpm/passenger_spec}/passenger_dynamic_thread_group.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger_tests_default_config_example.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-GLIBC_HAVE_LONG_LONG.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-gcc47-include-sys_types.patch +0 -0
- data/packaging/rpm/repo_update +114 -0
- data/packaging/rpm/setup-system +60 -0
- data/packaging/rpm/shell +10 -0
- data/resources/templates/standalone/config.erb +3 -1
- data/test/config.json.rpm-automation +1 -1
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +11 -11
- data/test/cxx/ApplicationPool2/OptionsTest.cpp +5 -5
- data/test/cxx/ApplicationPool2/PoolTest.cpp +129 -89
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +15 -15
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +22 -22
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +11 -11
- data/test/cxx/ScgiRequestParserTest.cpp +75 -61
- data/test/cxx/UtilsTest.cpp +86 -85
- data/test/gdbinit.example +3 -0
- data/test/integration_tests/nginx_tests.rb +3 -3
- data/test/integration_tests/source_packaging_test.rb +3 -1
- data/test/stub/nginx/nginx.conf.erb +8 -1
- data/test/support/nginx_controller.rb +7 -7
- metadata +62 -17
- metadata.gz.asc +7 -7
- data/build/rpm.rb +0 -128
- data/dev/rpmtool +0 -21
- data/dev/test_rpm_packaging.sh +0 -28
- data/rpm/get_distro_id.py +0 -4
data/ext/oxt/thread.hpp
CHANGED
@@ -29,6 +29,7 @@
|
|
29
29
|
#include <boost/bind.hpp>
|
30
30
|
#include <boost/make_shared.hpp>
|
31
31
|
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
32
|
+
#include "macros.hpp"
|
32
33
|
#include "system_calls.hpp"
|
33
34
|
#include "detail/context.hpp"
|
34
35
|
#include <string>
|
@@ -38,6 +39,13 @@
|
|
38
39
|
|
39
40
|
namespace oxt {
|
40
41
|
|
42
|
+
#ifdef OXT_THREAD_LOCAL_KEYWORD_SUPPORTED
|
43
|
+
/** A thread-specific signature that you can use for identifying threads.
|
44
|
+
* It defaults to NULL. You have to set it manually in every thread.
|
45
|
+
*/
|
46
|
+
extern __thread void *thread_signature;
|
47
|
+
#endif
|
48
|
+
|
41
49
|
/**
|
42
50
|
* Enhanced thread class with support for:
|
43
51
|
* - user-defined stack size.
|
@@ -50,7 +58,7 @@ private:
|
|
50
58
|
|
51
59
|
static std::string make_thread_name(const std::string &given_name);
|
52
60
|
static void thread_main(const boost::function<void ()> func, thread_local_context_ptr ctx);
|
53
|
-
|
61
|
+
|
54
62
|
public:
|
55
63
|
/**
|
56
64
|
* Create a new thread.
|
@@ -82,7 +90,7 @@ public:
|
|
82
90
|
unsigned long min_stack_size;
|
83
91
|
bool stack_min_size_defined;
|
84
92
|
bool round_stack_size;
|
85
|
-
|
93
|
+
|
86
94
|
#ifdef PTHREAD_STACK_MIN
|
87
95
|
// PTHREAD_STACK_MIN may not be a constant macro so we need
|
88
96
|
// to evaluate it dynamically.
|
@@ -99,7 +107,7 @@ public:
|
|
99
107
|
} else {
|
100
108
|
round_stack_size = true;
|
101
109
|
}
|
102
|
-
|
110
|
+
|
103
111
|
if (round_stack_size) {
|
104
112
|
// Round stack size up to page boundary.
|
105
113
|
long page_size;
|
@@ -123,23 +131,23 @@ public:
|
|
123
131
|
attrs.set_stack_size(stack_size);
|
124
132
|
start_thread(attrs);
|
125
133
|
}
|
126
|
-
|
134
|
+
|
127
135
|
/**
|
128
136
|
* Return this thread's name. The name was set during construction.
|
129
137
|
*/
|
130
138
|
std::string name() const throw();
|
131
|
-
|
139
|
+
|
132
140
|
/**
|
133
141
|
* Return the current backtrace of the thread of execution, as a string.
|
134
142
|
*/
|
135
143
|
std::string backtrace() const throw();
|
136
|
-
|
144
|
+
|
137
145
|
/**
|
138
146
|
* Return the backtraces of all oxt::thread threads, as well as that of the
|
139
147
|
* main thread, in a nicely formatted string.
|
140
148
|
*/
|
141
149
|
static std::string all_backtraces() throw();
|
142
|
-
|
150
|
+
|
143
151
|
/**
|
144
152
|
* Interrupt the thread. This method behaves just like
|
145
153
|
* boost::thread::interrupt(), but if <em>interruptSyscalls</em> is true
|
@@ -153,7 +161,7 @@ public:
|
|
153
161
|
* pattern.
|
154
162
|
*/
|
155
163
|
void interrupt(bool interruptSyscalls = true);
|
156
|
-
|
164
|
+
|
157
165
|
/**
|
158
166
|
* Keep interrupting the thread until it's done, then join it.
|
159
167
|
*
|
@@ -169,7 +177,7 @@ public:
|
|
169
177
|
done = timed_join(boost::posix_time::millisec(10));
|
170
178
|
}
|
171
179
|
}
|
172
|
-
|
180
|
+
|
173
181
|
/**
|
174
182
|
* Keep interrupting the thread until it's done, then join it.
|
175
183
|
* This method will keep trying for at most <em>timeout</em> milliseconds.
|
@@ -195,7 +203,7 @@ public:
|
|
195
203
|
}
|
196
204
|
return joined;
|
197
205
|
}
|
198
|
-
|
206
|
+
|
199
207
|
/**
|
200
208
|
* Interrupt and join multiple threads in a way that's more efficient than calling
|
201
209
|
* interrupt_and_join() on each thread individually. It iterates over all threads,
|
@@ -217,11 +225,11 @@ public:
|
|
217
225
|
std::list<oxt::thread *>::iterator it, current;
|
218
226
|
oxt::thread *thread;
|
219
227
|
unsigned int i;
|
220
|
-
|
228
|
+
|
221
229
|
for (i = 0; i < size; i++) {
|
222
230
|
remaining_threads.push_back(threads[i]);
|
223
231
|
}
|
224
|
-
|
232
|
+
|
225
233
|
while (!remaining_threads.empty()) {
|
226
234
|
for (it = remaining_threads.begin(); it != remaining_threads.end(); it++) {
|
227
235
|
thread = *it;
|
@@ -252,7 +260,7 @@ private:
|
|
252
260
|
public:
|
253
261
|
interruptable_lock_guard(TimedLockable &m): mutex(m) {
|
254
262
|
bool locked = false;
|
255
|
-
|
263
|
+
|
256
264
|
while (!locked) {
|
257
265
|
locked = m.timed_lock(boost::posix_time::milliseconds(20));
|
258
266
|
if (!locked) {
|
@@ -260,7 +268,7 @@ public:
|
|
260
268
|
}
|
261
269
|
}
|
262
270
|
}
|
263
|
-
|
271
|
+
|
264
272
|
~interruptable_lock_guard() {
|
265
273
|
mutex.unlock();
|
266
274
|
}
|
@@ -119,7 +119,7 @@ split_by_null_into_hash(VALUE self, VALUE data) {
|
|
119
119
|
const char *current = cdata;
|
120
120
|
const char *end = cdata + len;
|
121
121
|
VALUE result, key, value;
|
122
|
-
|
122
|
+
|
123
123
|
result = rb_hash_new();
|
124
124
|
while (current < end) {
|
125
125
|
if (*current == '\0') {
|
@@ -145,10 +145,10 @@ split_by_null_into_hash(VALUE self, VALUE data) {
|
|
145
145
|
typedef struct {
|
146
146
|
/* The IO vectors in this group. */
|
147
147
|
struct iovec *io_vectors;
|
148
|
-
|
148
|
+
|
149
149
|
/* The number of IO vectors in io_vectors. */
|
150
150
|
unsigned int count;
|
151
|
-
|
151
|
+
|
152
152
|
/* The combined size of all IO vectors in this group. */
|
153
153
|
ssize_t total_size;
|
154
154
|
} IOVectorGroup;
|
@@ -162,7 +162,7 @@ update_group_written_info(IOVectorGroup *group, ssize_t bytes_written) {
|
|
162
162
|
unsigned int i;
|
163
163
|
size_t counter;
|
164
164
|
struct iovec *current_vec;
|
165
|
-
|
165
|
+
|
166
166
|
/* Find the last vector that contains data that had already been written. */
|
167
167
|
counter = 0;
|
168
168
|
for (i = 0; i < group->count; i++) {
|
@@ -198,7 +198,7 @@ update_group_written_info(IOVectorGroup *group, ssize_t bytes_written) {
|
|
198
198
|
const struct iovec *iov;
|
199
199
|
int iovcnt;
|
200
200
|
} WritevWrapperData;
|
201
|
-
|
201
|
+
|
202
202
|
static VALUE
|
203
203
|
writev_wrapper(void *ptr) {
|
204
204
|
WritevWrapperData *data = (WritevWrapperData *) ptr;
|
@@ -218,7 +218,7 @@ f_generic_writev(VALUE fd, VALUE *array_of_components, unsigned int count) {
|
|
218
218
|
#ifndef TRAP_BEG
|
219
219
|
WritevWrapperData writev_wrapper_data;
|
220
220
|
#endif
|
221
|
-
|
221
|
+
|
222
222
|
/* First determine the number of components that we have. */
|
223
223
|
total_components = 0;
|
224
224
|
for (i = 0; i < count; i++) {
|
@@ -228,7 +228,7 @@ f_generic_writev(VALUE fd, VALUE *array_of_components, unsigned int count) {
|
|
228
228
|
if (total_components == 0) {
|
229
229
|
return NUM2INT(0);
|
230
230
|
}
|
231
|
-
|
231
|
+
|
232
232
|
/* A single writev() call can only accept IOV_MAX vectors, so we
|
233
233
|
* may have to split the components into groups and perform
|
234
234
|
* multiple writev() calls, one per group. Determine the number
|
@@ -269,7 +269,7 @@ f_generic_writev(VALUE fd, VALUE *array_of_components, unsigned int count) {
|
|
269
269
|
}
|
270
270
|
groups[ngroups - 1].count = total_components % IOV_MAX;
|
271
271
|
}
|
272
|
-
|
272
|
+
|
273
273
|
/* Now distribute the components among the groups, filling the iovec
|
274
274
|
* array in each group. Also calculate the total data size while we're
|
275
275
|
* at it.
|
@@ -297,19 +297,19 @@ f_generic_writev(VALUE fd, VALUE *array_of_components, unsigned int count) {
|
|
297
297
|
}
|
298
298
|
}
|
299
299
|
}
|
300
|
-
|
300
|
+
|
301
301
|
/* We don't compare to SSIZE_MAX directly in order to shut up a compiler warning on OS X Snow Leopard. */
|
302
302
|
ssize_max = SSIZE_MAX;
|
303
303
|
if (total_size > ssize_max) {
|
304
304
|
rb_raise(rb_eArgError, "The total size of the components may not be larger than SSIZE_MAX.");
|
305
305
|
}
|
306
|
-
|
306
|
+
|
307
307
|
/* Write the data. */
|
308
308
|
fd_num = NUM2INT(fd);
|
309
309
|
for (i = 0; i < ngroups; i++) {
|
310
310
|
/* Wait until the file descriptor becomes writable before writing things. */
|
311
311
|
rb_thread_fd_writable(fd_num);
|
312
|
-
|
312
|
+
|
313
313
|
done = 0;
|
314
314
|
while (!done) {
|
315
315
|
#ifdef TRAP_BEG
|
@@ -399,11 +399,11 @@ static VALUE
|
|
399
399
|
process_times(VALUE self) {
|
400
400
|
struct rusage usage;
|
401
401
|
unsigned long long utime, stime;
|
402
|
-
|
402
|
+
|
403
403
|
if (getrusage(RUSAGE_SELF, &usage) == -1) {
|
404
404
|
rb_sys_fail("getrusage()");
|
405
405
|
}
|
406
|
-
|
406
|
+
|
407
407
|
utime = (unsigned long long) usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec;
|
408
408
|
stime = (unsigned long long) usage.ru_stime.tv_sec * 1000000 + usage.ru_stime.tv_usec;
|
409
409
|
return rb_struct_new(S_ProcessTimes, rb_ull2inum(utime), rb_ull2inum(stime));
|
@@ -424,11 +424,11 @@ detach_process(VALUE self, VALUE pid) {
|
|
424
424
|
pthread_t thr;
|
425
425
|
pthread_attr_t attr;
|
426
426
|
size_t stack_size = 96 * 1024;
|
427
|
-
|
427
|
+
|
428
428
|
unsigned long min_stack_size;
|
429
429
|
int stack_min_size_defined;
|
430
430
|
int round_stack_size;
|
431
|
-
|
431
|
+
|
432
432
|
#ifdef PTHREAD_STACK_MIN
|
433
433
|
// PTHREAD_STACK_MIN may not be a constant macro so we need
|
434
434
|
// to evaluate it dynamically.
|
@@ -445,7 +445,7 @@ detach_process(VALUE self, VALUE pid) {
|
|
445
445
|
} else {
|
446
446
|
round_stack_size = 1;
|
447
447
|
}
|
448
|
-
|
448
|
+
|
449
449
|
if (round_stack_size) {
|
450
450
|
// Round stack size up to page boundary.
|
451
451
|
long page_size;
|
@@ -464,7 +464,7 @@ detach_process(VALUE self, VALUE pid) {
|
|
464
464
|
stack_size = stack_size - (stack_size % page_size) + page_size;
|
465
465
|
}
|
466
466
|
}
|
467
|
-
|
467
|
+
|
468
468
|
pthread_attr_init(&attr);
|
469
469
|
pthread_attr_setdetachstate(&attr, 1);
|
470
470
|
pthread_attr_setstacksize(&attr, stack_size);
|
@@ -490,24 +490,24 @@ typedef struct {
|
|
490
490
|
VALUE klass;
|
491
491
|
VALUE filenames;
|
492
492
|
VALUE termination_pipe;
|
493
|
-
|
493
|
+
|
494
494
|
/* File descriptor of termination_pipe. */
|
495
495
|
int termination_fd;
|
496
|
-
|
496
|
+
|
497
497
|
/* Whether something went wrong during initialization. */
|
498
498
|
int preparation_error;
|
499
|
-
|
499
|
+
|
500
500
|
/* Information for kqueue. */
|
501
501
|
unsigned int events_len;
|
502
502
|
int *fds;
|
503
503
|
unsigned int fds_len;
|
504
504
|
int kq;
|
505
|
-
|
505
|
+
|
506
506
|
/* When the watcher thread is done it'll write to this pipe
|
507
507
|
* to signal the main (Ruby) thread.
|
508
508
|
*/
|
509
509
|
int notification_fd[2];
|
510
|
-
|
510
|
+
|
511
511
|
/* When the main (Ruby) thread is interrupted it'll write to
|
512
512
|
* this pipe to tell the watcher thread to exit.
|
513
513
|
*/
|
@@ -524,7 +524,7 @@ typedef struct {
|
|
524
524
|
static void
|
525
525
|
fs_watcher_real_close(FSWatcher *watcher) {
|
526
526
|
unsigned int i;
|
527
|
-
|
527
|
+
|
528
528
|
if (watcher->kq != -1) {
|
529
529
|
close(watcher->kq);
|
530
530
|
watcher->kq = -1;
|
@@ -572,9 +572,9 @@ fs_watcher_init(VALUE arg) {
|
|
572
572
|
VALUE filenum;
|
573
573
|
struct stat buf;
|
574
574
|
int fd;
|
575
|
-
|
575
|
+
|
576
576
|
/* Open each file in the filenames list and add each one to the events array. */
|
577
|
-
|
577
|
+
|
578
578
|
/* +2 for the termination pipe and the interruption pipe. */
|
579
579
|
events = alloca((RARRAY_LEN(watcher->filenames) + 2) * sizeof(struct kevent));
|
580
580
|
watcher->fds = malloc(RARRAY_LEN(watcher->filenames) * sizeof(int));
|
@@ -587,12 +587,12 @@ fs_watcher_init(VALUE arg) {
|
|
587
587
|
if (TYPE(filename) != T_STRING) {
|
588
588
|
filename = rb_obj_as_string(filename);
|
589
589
|
}
|
590
|
-
|
590
|
+
|
591
591
|
if (stat(RSTRING_PTR(filename), &buf) == -1) {
|
592
592
|
watcher->preparation_error = 1;
|
593
593
|
goto end;
|
594
594
|
}
|
595
|
-
|
595
|
+
|
596
596
|
#ifdef O_EVTONLY
|
597
597
|
fd = open(RSTRING_PTR(filename), O_EVTONLY);
|
598
598
|
#else
|
@@ -602,18 +602,18 @@ fs_watcher_init(VALUE arg) {
|
|
602
602
|
watcher->preparation_error = 1;
|
603
603
|
goto end;
|
604
604
|
}
|
605
|
-
|
605
|
+
|
606
606
|
watcher->fds[i] = fd;
|
607
607
|
watcher->fds_len++;
|
608
608
|
fflags = NOTE_WRITE | NOTE_EXTEND | NOTE_RENAME | NOTE_DELETE | NOTE_REVOKE;
|
609
609
|
EV_SET(&events[i], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
|
610
610
|
fflags, 0, 0);
|
611
611
|
}
|
612
|
-
|
612
|
+
|
613
613
|
watcher->events_len = watcher->fds_len;
|
614
|
-
|
614
|
+
|
615
615
|
/* Create pipes for inter-thread communication. */
|
616
|
-
|
616
|
+
|
617
617
|
if (pipe(watcher->notification_fd) == -1) {
|
618
618
|
rb_sys_fail("pipe()");
|
619
619
|
return Qnil;
|
@@ -622,15 +622,15 @@ fs_watcher_init(VALUE arg) {
|
|
622
622
|
rb_sys_fail("pipe()");
|
623
623
|
return Qnil;
|
624
624
|
}
|
625
|
-
|
625
|
+
|
626
626
|
/* Create a kqueue and register all events. */
|
627
|
-
|
627
|
+
|
628
628
|
watcher->kq = kqueue();
|
629
629
|
if (watcher->kq == -1) {
|
630
630
|
rb_sys_fail("kqueue()");
|
631
631
|
return Qnil;
|
632
632
|
}
|
633
|
-
|
633
|
+
|
634
634
|
if (watcher->termination_pipe != Qnil) {
|
635
635
|
filenum = rb_funcall(watcher->termination_pipe,
|
636
636
|
rb_intern("fileno"), 0);
|
@@ -642,12 +642,12 @@ fs_watcher_init(VALUE arg) {
|
|
642
642
|
EV_SET(&events[watcher->events_len], watcher->interruption_fd[0],
|
643
643
|
EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
|
644
644
|
watcher->events_len++;
|
645
|
-
|
645
|
+
|
646
646
|
if (kevent(watcher->kq, events, watcher->events_len, NULL, 0, NULL) == -1) {
|
647
647
|
rb_sys_fail("kevent()");
|
648
648
|
return Qnil;
|
649
649
|
}
|
650
|
-
|
650
|
+
|
651
651
|
end:
|
652
652
|
if (watcher->preparation_error) {
|
653
653
|
for (i = 0; i < watcher->fds_len; i++) {
|
@@ -665,7 +665,7 @@ fs_watcher_new(VALUE klass, VALUE filenames, VALUE termination_pipe) {
|
|
665
665
|
FSWatcher *watcher;
|
666
666
|
VALUE result;
|
667
667
|
int status;
|
668
|
-
|
668
|
+
|
669
669
|
Check_Type(filenames, T_ARRAY);
|
670
670
|
watcher = (FSWatcher *) calloc(1, sizeof(FSWatcher));
|
671
671
|
if (watcher == NULL) {
|
@@ -681,7 +681,7 @@ fs_watcher_new(VALUE klass, VALUE filenames, VALUE termination_pipe) {
|
|
681
681
|
watcher->notification_fd[1] = -1;
|
682
682
|
watcher->interruption_fd[0] = -1;
|
683
683
|
watcher->interruption_fd[1] = -1;
|
684
|
-
|
684
|
+
|
685
685
|
result = rb_protect(fs_watcher_init, (VALUE) watcher, &status);
|
686
686
|
if (status) {
|
687
687
|
fs_watcher_free(watcher);
|
@@ -698,7 +698,7 @@ fs_watcher_wait_on_kqueue(void *arg) {
|
|
698
698
|
struct kevent *events;
|
699
699
|
int nevents;
|
700
700
|
ssize_t ret;
|
701
|
-
|
701
|
+
|
702
702
|
events = alloca(sizeof(struct kevent) * watcher->events_len);
|
703
703
|
nevents = kevent(watcher->kq, NULL, 0, events, watcher->events_len, NULL);
|
704
704
|
if (nevents == -1) {
|
@@ -760,27 +760,27 @@ fs_watcher_wait_for_change(VALUE self) {
|
|
760
760
|
ssize_t ret;
|
761
761
|
int e, interrupted = 0;
|
762
762
|
FSWatcherReadByteData read_data;
|
763
|
-
|
763
|
+
|
764
764
|
Data_Get_Struct(self, FSWatcher, watcher);
|
765
|
-
|
765
|
+
|
766
766
|
if (watcher->preparation_error) {
|
767
767
|
return Qfalse;
|
768
768
|
}
|
769
|
-
|
769
|
+
|
770
770
|
/* Spawn a thread, and let the thread perform the blocking kqueue
|
771
771
|
* wait. When kevent() returns the thread will write its status to the
|
772
772
|
* notification pipe. In the mean time we let the Ruby interpreter wait
|
773
773
|
* on the other side of the pipe for us so that we don't block Ruby
|
774
774
|
* threads.
|
775
775
|
*/
|
776
|
-
|
776
|
+
|
777
777
|
e = pthread_create(&thr, NULL, fs_watcher_wait_on_kqueue, watcher);
|
778
778
|
if (e != 0) {
|
779
779
|
errno = e;
|
780
780
|
rb_sys_fail("pthread_create()");
|
781
781
|
return Qnil;
|
782
782
|
}
|
783
|
-
|
783
|
+
|
784
784
|
/* Note that rb_thread_wait() does not wait for the fd when the app
|
785
785
|
* is single threaded, so we must join the thread after we've read
|
786
786
|
* from the notification fd.
|
@@ -797,13 +797,13 @@ fs_watcher_wait_for_change(VALUE self) {
|
|
797
797
|
return Qnil;
|
798
798
|
}
|
799
799
|
pthread_join(thr, NULL);
|
800
|
-
|
800
|
+
|
801
801
|
/* Now clean up stuff. */
|
802
802
|
fs_watcher_real_close(watcher);
|
803
803
|
rb_jump_tag(interrupted);
|
804
804
|
return Qnil;
|
805
805
|
}
|
806
|
-
|
806
|
+
|
807
807
|
read_data.fd = watcher->notification_fd[0];
|
808
808
|
rb_protect(fs_watcher_read_byte_from_fd, (VALUE) &read_data, &interrupted);
|
809
809
|
if (interrupted) {
|
@@ -817,15 +817,15 @@ fs_watcher_wait_for_change(VALUE self) {
|
|
817
817
|
return Qnil;
|
818
818
|
}
|
819
819
|
pthread_join(thr, NULL);
|
820
|
-
|
820
|
+
|
821
821
|
/* Now clean up stuff. */
|
822
822
|
fs_watcher_real_close(watcher);
|
823
823
|
rb_jump_tag(interrupted);
|
824
824
|
return Qnil;
|
825
825
|
}
|
826
|
-
|
826
|
+
|
827
827
|
pthread_join(thr, NULL);
|
828
|
-
|
828
|
+
|
829
829
|
if (read_data.ret == -1) {
|
830
830
|
fs_watcher_real_close(watcher);
|
831
831
|
errno = read_data.error;
|
@@ -865,7 +865,7 @@ fs_watcher_close(VALUE self) {
|
|
865
865
|
void
|
866
866
|
Init_passenger_native_support() {
|
867
867
|
struct sockaddr_un addr;
|
868
|
-
|
868
|
+
|
869
869
|
/* Only defined on Ruby >= 1.9.3 */
|
870
870
|
#ifdef RUBY_API_VERSION_CODE
|
871
871
|
if (ruby_api_version[0] != RUBY_API_VERSION_MAJOR
|
@@ -939,14 +939,14 @@ Init_passenger_native_support() {
|
|
939
939
|
#endif
|
940
940
|
|
941
941
|
mPassenger = rb_define_module("PhusionPassenger");
|
942
|
-
|
942
|
+
|
943
943
|
/*
|
944
944
|
* Utility functions for accessing system functionality.
|
945
945
|
*/
|
946
946
|
mNativeSupport = rb_define_module_under(mPassenger, "NativeSupport");
|
947
|
-
|
947
|
+
|
948
948
|
S_ProcessTimes = rb_struct_define("ProcessTimes", "utime", "stime", NULL);
|
949
|
-
|
949
|
+
|
950
950
|
rb_define_singleton_method(mNativeSupport, "disable_stdio_buffering", disable_stdio_buffering, 0);
|
951
951
|
rb_define_singleton_method(mNativeSupport, "split_by_null_into_hash", split_by_null_into_hash, 1);
|
952
952
|
rb_define_singleton_method(mNativeSupport, "writev", f_writev, 2);
|
@@ -955,7 +955,7 @@ Init_passenger_native_support() {
|
|
955
955
|
rb_define_singleton_method(mNativeSupport, "process_times", process_times, 0);
|
956
956
|
rb_define_singleton_method(mNativeSupport, "detach_process", detach_process, 1);
|
957
957
|
rb_define_singleton_method(mNativeSupport, "freeze_process", freeze_process, 0);
|
958
|
-
|
958
|
+
|
959
959
|
#ifdef HAVE_KQUEUE
|
960
960
|
cFileSystemWatcher = rb_define_class_under(mNativeSupport,
|
961
961
|
"FileSystemWatcher", rb_cObject);
|
@@ -966,7 +966,7 @@ Init_passenger_native_support() {
|
|
966
966
|
rb_define_method(cFileSystemWatcher, "close",
|
967
967
|
fs_watcher_close, 0);
|
968
968
|
#endif
|
969
|
-
|
969
|
+
|
970
970
|
/* The maximum length of a Unix socket path, including terminating null. */
|
971
971
|
rb_define_const(mNativeSupport, "UNIX_PATH_MAX", INT2NUM(sizeof(addr.sun_path)));
|
972
972
|
/* The maximum size of the data that may be passed to #writev. */
|