passenger 4.0.0.rc4 → 4.0.0.rc6
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.
- data.tar.gz.asc +12 -0
- data/.travis.yml +4 -4
- data/NEWS +46 -0
- data/bin/passenger-config +31 -1
- data/bin/passenger-install-apache2-module +1 -1
- data/bin/passenger-install-nginx-module +1 -0
- data/build/common_library.rb +4 -0
- data/build/cplusplus_support.rb +27 -6
- data/build/cxx_tests.rb +1 -1
- data/build/misc.rb +28 -6
- data/build/packaging.rb +72 -65
- data/build/test_basics.rb +1 -1
- data/dev/googlecode_upload.py +265 -0
- data/dev/run_travis.sh +9 -0
- data/doc/Users guide Apache.html +376 -193
- data/doc/Users guide Apache.idmap.txt +80 -62
- data/doc/Users guide Apache.txt +61 -35
- data/doc/Users guide Nginx.html +278 -83
- data/doc/Users guide Nginx.idmap.txt +26 -10
- data/doc/Users guide Nginx.txt +59 -31
- data/doc/Users guide Standalone.html +1 -1
- data/doc/users_guide_snippets/installation.txt +121 -11
- data/doc/users_guide_snippets/rvm_helper_tool.txt +56 -0
- data/ext/apache2/Bucket.cpp +1 -1
- data/ext/apache2/Configuration.cpp +7 -1
- data/ext/apache2/Configuration.hpp +4 -0
- data/ext/apache2/Hooks.cpp +2 -2
- data/ext/common/AgentsStarter.cpp +2 -2
- data/ext/common/AgentsStarter.h +1 -1
- data/ext/common/AgentsStarter.hpp +2 -2
- data/ext/common/ApplicationPool2/DirectSpawner.h +4 -8
- data/ext/common/ApplicationPool2/Group.h +17 -11
- data/ext/common/ApplicationPool2/Implementation.cpp +39 -11
- data/ext/common/ApplicationPool2/Pool.h +23 -4
- data/ext/common/ApplicationPool2/Process.h +30 -11
- data/ext/common/ApplicationPool2/SmartSpawner.h +3 -1
- data/ext/common/Constants.h +1 -1
- data/ext/common/EventedBufferedInput.h +4 -0
- data/ext/common/Utils.cpp +21 -3
- data/ext/common/Utils.h +8 -1
- data/ext/common/Utils/HttpHeaderBufferer.h +1 -1
- data/ext/common/Utils/IOUtils.cpp +5 -4
- data/ext/common/Utils/IOUtils.h +32 -14
- data/ext/common/Utils/MessagePassing.h +2 -2
- data/ext/common/Utils/ProcessMetricsCollector.h +47 -15
- data/ext/common/Utils/ScopeGuard.h +20 -3
- data/ext/common/Utils/StrIntUtils.h +14 -5
- data/ext/common/agents/Base.cpp +161 -50
- data/ext/common/agents/HelperAgent/AgentOptions.h +2 -2
- data/ext/common/agents/HelperAgent/Main.cpp +1 -0
- data/ext/common/agents/HelperAgent/RequestHandler.h +166 -52
- data/ext/common/agents/LoggingAgent/Main.cpp +1 -1
- data/ext/common/agents/Watchdog/Main.cpp +2 -2
- data/ext/nginx/Configuration.c +31 -4
- data/ext/nginx/Configuration.h +1 -0
- data/ext/nginx/ContentHandler.c +148 -34
- data/ext/nginx/ngx_http_passenger_module.c +4 -1
- data/ext/oxt/detail/spin_lock_pthreads.hpp +4 -4
- data/ext/oxt/macros.hpp +30 -8
- data/lib/phusion_passenger.rb +2 -2
- data/lib/phusion_passenger/classic_rails/thread_handler_extension.rb +1 -1
- data/lib/phusion_passenger/native_support.rb +19 -1
- data/lib/phusion_passenger/platform_info/compiler.rb +6 -0
- data/lib/phusion_passenger/platform_info/ruby.rb +54 -5
- data/lib/phusion_passenger/preloader_shared_helpers.rb +8 -1
- data/lib/phusion_passenger/rack/out_of_band_gc.rb +3 -1
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +32 -5
- data/lib/phusion_passenger/request_handler/thread_handler.rb +28 -8
- data/lib/phusion_passenger/ruby_core_enhancements.rb +9 -1
- data/lib/phusion_passenger/standalone/runtime_installer.rb +1 -0
- data/lib/phusion_passenger/utils/unseekable_socket.rb +50 -5
- data/passenger.gemspec +1 -1
- data/resources/templates/apache2/config_snippets.txt.erb +1 -1
- data/test/cxx/ApplicationPool2/PoolTest.cpp +4 -9
- data/test/cxx/RequestHandlerTest.cpp +5 -5
- data/test/ruby/classic_rails/loader_spec.rb +1 -1
- data/test/ruby/classic_rails/preloader_spec.rb +1 -1
- data/test/ruby/request_handler_spec.rb +207 -1
- data/test/ruby/shared/loader_sharedspec.rb +1 -0
- data/test/ruby/spec_helper.rb +11 -1
- data/test/stub/apache2/httpd.conf.erb +1 -1
- metadata +5 -3
- metadata.gz.asc +12 -0
data/ext/nginx/Configuration.h
CHANGED
data/ext/nginx/ContentHandler.c
CHANGED
@@ -53,10 +53,11 @@ static void abort_request(ngx_http_request_t *r);
|
|
53
53
|
static void finalize_request(ngx_http_request_t *r, ngx_int_t rc);
|
54
54
|
|
55
55
|
|
56
|
-
static
|
56
|
+
static unsigned int
|
57
57
|
uint_to_str(ngx_uint_t i, u_char *str, ngx_uint_t size) {
|
58
|
-
|
59
|
-
|
58
|
+
unsigned int len = ngx_snprintf(str, size - 1, "%ui", i) - str;
|
59
|
+
str[len] = '\0';
|
60
|
+
return len;
|
60
61
|
}
|
61
62
|
|
62
63
|
static FileType
|
@@ -222,6 +223,57 @@ set_upstream_server_address(ngx_http_upstream_t *upstream, ngx_http_upstream_con
|
|
222
223
|
}
|
223
224
|
}
|
224
225
|
|
226
|
+
/**
|
227
|
+
* If the helper agent socket cannot be connected to then we want Nginx to print
|
228
|
+
* the proper socket filename in the error message. The socket filename is stored
|
229
|
+
* in one of the upstream peer data structures. This name is initialized during
|
230
|
+
* the first ngx_http_read_client_request_body() call so there's no way to fix the
|
231
|
+
* name before the first request, which is why we do it after the fact.
|
232
|
+
*/
|
233
|
+
static void
|
234
|
+
fix_peer_address(ngx_http_request_t *r) {
|
235
|
+
ngx_http_upstream_rr_peer_data_t *rrp;
|
236
|
+
ngx_http_upstream_rr_peers_t *peers;
|
237
|
+
ngx_http_upstream_rr_peer_t *peer;
|
238
|
+
unsigned int peer_index;
|
239
|
+
const char *request_socket_filename;
|
240
|
+
unsigned int request_socket_filename_len;
|
241
|
+
|
242
|
+
if (r->upstream->peer.get != ngx_http_upstream_get_round_robin_peer) {
|
243
|
+
/* This function only supports the round-robin upstream method. */
|
244
|
+
return;
|
245
|
+
}
|
246
|
+
|
247
|
+
rrp = r->upstream->peer.data;
|
248
|
+
peers = rrp->peers;
|
249
|
+
request_socket_filename =
|
250
|
+
agents_starter_get_request_socket_filename(passenger_agents_starter,
|
251
|
+
&request_socket_filename_len);
|
252
|
+
|
253
|
+
while (peers != NULL) {
|
254
|
+
if (peers->name) {
|
255
|
+
if (peers->name->data == (u_char *) request_socket_filename) {
|
256
|
+
/* Peer names already fixed. */
|
257
|
+
return;
|
258
|
+
}
|
259
|
+
peers->name->data = (u_char *) request_socket_filename;
|
260
|
+
peers->name->len = request_socket_filename_len;
|
261
|
+
}
|
262
|
+
peer_index = 0;
|
263
|
+
while (1) {
|
264
|
+
peer = &peers->peer[peer_index];
|
265
|
+
peer->name.data = (u_char *) request_socket_filename;
|
266
|
+
peer->name.len = request_socket_filename_len;
|
267
|
+
if (peer->down) {
|
268
|
+
peer_index++;
|
269
|
+
} else {
|
270
|
+
break;
|
271
|
+
}
|
272
|
+
}
|
273
|
+
peers = peers->next;
|
274
|
+
}
|
275
|
+
}
|
276
|
+
|
225
277
|
|
226
278
|
/* Convenience macros for building the SCGI header in create_request(). */
|
227
279
|
|
@@ -311,8 +363,8 @@ create_request(ngx_http_request_t *r)
|
|
311
363
|
u_char ch;
|
312
364
|
const char * helper_agent_request_socket_password_data;
|
313
365
|
unsigned int helper_agent_request_socket_password_len;
|
314
|
-
u_char buf[sizeof("4294967296")];
|
315
|
-
size_t len, size, key_len, val_len
|
366
|
+
u_char buf[sizeof("4294967296") + 1];
|
367
|
+
size_t len, size, key_len, val_len;
|
316
368
|
const u_char *app_type_string;
|
317
369
|
size_t app_type_string_len;
|
318
370
|
int server_name_len;
|
@@ -366,15 +418,15 @@ create_request(ngx_http_request_t *r)
|
|
366
418
|
* Determine the request header length.
|
367
419
|
**************************************************/
|
368
420
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
421
|
+
len = 0;
|
422
|
+
|
423
|
+
/* Length of the Content-Length header. A value of -1 means that the content
|
424
|
+
* length is unspecified, which is the case for e.g. WebSocket requests. */
|
425
|
+
if (r->headers_in.content_length_n >= 0) {
|
426
|
+
len += sizeof("CONTENT_LENGTH") +
|
427
|
+
uint_to_str(r->headers_in.content_length_n, buf, sizeof(buf)) +
|
428
|
+
1; /* +1 for trailing null */
|
374
429
|
}
|
375
|
-
uint_to_str(content_length, buf, sizeof(buf));
|
376
|
-
/* +1 for trailing null */
|
377
|
-
len = sizeof("CONTENT_LENGTH") + ngx_strlen(buf) + 1;
|
378
430
|
|
379
431
|
/* DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT, PATH_INFO and REQUEST_URI. */
|
380
432
|
len += sizeof("DOCUMENT_ROOT") + context->public_dir.len + 1;
|
@@ -427,7 +479,11 @@ create_request(ngx_http_request_t *r)
|
|
427
479
|
slcf, debugger);
|
428
480
|
ANALYZE_BOOLEAN_CONFIG_LENGTH("PASSENGER_SHOW_VERSION_IN_HEADER",
|
429
481
|
slcf, show_version_in_header);
|
430
|
-
|
482
|
+
if (slcf->ruby.data != NULL) {
|
483
|
+
ANALYZE_STR_CONFIG_LENGTH("PASSENGER_RUBY", slcf, ruby);
|
484
|
+
} else {
|
485
|
+
len += sizeof("PASSENGER_RUBY") + passenger_main_conf.default_ruby.len + 1;
|
486
|
+
}
|
431
487
|
ANALYZE_STR_CONFIG_LENGTH("PASSENGER_PYTHON", slcf, python);
|
432
488
|
len += sizeof("PASSENGER_ENV") + slcf->environment.len + 1;
|
433
489
|
len += sizeof("PASSENGER_SPAWN_METHOD") + slcf->spawn_method.len + 1;
|
@@ -560,12 +616,13 @@ create_request(ngx_http_request_t *r)
|
|
560
616
|
b->last = ngx_snprintf(b->last, 10, "%ui", len);
|
561
617
|
*b->last++ = (u_char) ':';
|
562
618
|
|
563
|
-
|
564
|
-
|
565
|
-
|
619
|
+
if (r->headers_in.content_length_n >= 0) {
|
620
|
+
b->last = ngx_copy(b->last, "CONTENT_LENGTH",
|
621
|
+
sizeof("CONTENT_LENGTH"));
|
566
622
|
|
567
|
-
|
568
|
-
|
623
|
+
b->last = ngx_snprintf(b->last, 10, "%ui", r->headers_in.content_length_n);
|
624
|
+
*b->last++ = (u_char) 0;
|
625
|
+
}
|
569
626
|
|
570
627
|
/* Build DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT, PATH_INFO and REQUEST_URI. */
|
571
628
|
b->last = ngx_copy(b->last, "DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT"));
|
@@ -642,8 +699,15 @@ create_request(ngx_http_request_t *r)
|
|
642
699
|
SERIALIZE_BOOLEAN_CONFIG_DATA("PASSENGER_SHOW_VERSION_IN_HEADER",
|
643
700
|
slcf, show_version_in_header);
|
644
701
|
|
645
|
-
|
646
|
-
|
702
|
+
if (slcf->ruby.data != NULL) {
|
703
|
+
SERIALIZE_STR_CONFIG_DATA("PASSENGER_RUBY",
|
704
|
+
slcf, ruby);
|
705
|
+
} else {
|
706
|
+
b->last = ngx_copy(b->last, "PASSENGER_RUBY",
|
707
|
+
sizeof("PASSENGER_RUBY"));
|
708
|
+
b->last = ngx_copy(b->last, passenger_main_conf.default_ruby.data,
|
709
|
+
passenger_main_conf.default_ruby.len + 1);
|
710
|
+
}
|
647
711
|
SERIALIZE_STR_CONFIG_DATA("PASSENGER_PYTHON",
|
648
712
|
slcf, python);
|
649
713
|
|
@@ -833,6 +897,7 @@ reinit_request(ngx_http_request_t *r)
|
|
833
897
|
context->status_end = NULL;
|
834
898
|
|
835
899
|
r->upstream->process_header = process_status_line;
|
900
|
+
r->state = 0;
|
836
901
|
|
837
902
|
return NGX_OK;
|
838
903
|
}
|
@@ -1108,9 +1173,10 @@ done:
|
|
1108
1173
|
static ngx_int_t
|
1109
1174
|
process_header(ngx_http_request_t *r)
|
1110
1175
|
{
|
1111
|
-
|
1112
|
-
|
1176
|
+
ngx_str_t *status_line;
|
1177
|
+
ngx_int_t rc, status;
|
1113
1178
|
ngx_table_elt_t *h;
|
1179
|
+
ngx_http_upstream_t *u;
|
1114
1180
|
ngx_http_upstream_header_t *hh;
|
1115
1181
|
ngx_http_upstream_main_conf_t *umcf;
|
1116
1182
|
ngx_http_core_loc_conf_t *clcf;
|
@@ -1120,7 +1186,7 @@ process_header(ngx_http_request_t *r)
|
|
1120
1186
|
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
1121
1187
|
slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module);
|
1122
1188
|
|
1123
|
-
for ( ;;
|
1189
|
+
for ( ;; ) {
|
1124
1190
|
|
1125
1191
|
rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
|
1126
1192
|
|
@@ -1130,7 +1196,7 @@ process_header(ngx_http_request_t *r)
|
|
1130
1196
|
|
1131
1197
|
h = ngx_list_push(&r->upstream->headers_in.headers);
|
1132
1198
|
if (h == NULL) {
|
1133
|
-
return
|
1199
|
+
return NGX_ERROR;
|
1134
1200
|
}
|
1135
1201
|
|
1136
1202
|
h->hash = r->header_hash;
|
@@ -1138,10 +1204,11 @@ process_header(ngx_http_request_t *r)
|
|
1138
1204
|
h->key.len = r->header_name_end - r->header_name_start;
|
1139
1205
|
h->value.len = r->header_end - r->header_start;
|
1140
1206
|
|
1141
|
-
h->key.data =
|
1142
|
-
|
1207
|
+
h->key.data = ngx_pnalloc(r->pool,
|
1208
|
+
h->key.len + 1 + h->value.len + 1
|
1209
|
+
+ h->key.len);
|
1143
1210
|
if (h->key.data == NULL) {
|
1144
|
-
return
|
1211
|
+
return NGX_ERROR;
|
1145
1212
|
}
|
1146
1213
|
|
1147
1214
|
h->value.data = h->key.data + h->key.len + 1;
|
@@ -1156,21 +1223,18 @@ process_header(ngx_http_request_t *r)
|
|
1156
1223
|
ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
|
1157
1224
|
|
1158
1225
|
} else {
|
1159
|
-
|
1160
|
-
h->lowcase_key[i] = ngx_tolower(h->key.data[i]);
|
1161
|
-
}
|
1226
|
+
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
|
1162
1227
|
}
|
1163
1228
|
|
1164
1229
|
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
1165
1230
|
h->lowcase_key, h->key.len);
|
1166
1231
|
|
1167
1232
|
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
|
1168
|
-
return
|
1233
|
+
return NGX_ERROR;
|
1169
1234
|
}
|
1170
1235
|
|
1171
1236
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
1172
|
-
"http scgi header: \"%V: %V\"",
|
1173
|
-
&h->key, &h->value);
|
1237
|
+
"http scgi header: \"%V: %V\"", &h->key, &h->value);
|
1174
1238
|
|
1175
1239
|
continue;
|
1176
1240
|
}
|
@@ -1230,6 +1294,53 @@ process_header(ngx_http_request_t *r)
|
|
1230
1294
|
h->lowcase_key = (u_char *) "date";
|
1231
1295
|
}
|
1232
1296
|
|
1297
|
+
/* Process "Status" header. */
|
1298
|
+
|
1299
|
+
u = r->upstream;
|
1300
|
+
|
1301
|
+
if (u->headers_in.status_n) {
|
1302
|
+
goto done;
|
1303
|
+
}
|
1304
|
+
|
1305
|
+
if (u->headers_in.status) {
|
1306
|
+
status_line = &u->headers_in.status->value;
|
1307
|
+
|
1308
|
+
status = ngx_atoi(status_line->data, 3);
|
1309
|
+
if (status == NGX_ERROR) {
|
1310
|
+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
1311
|
+
"upstream sent invalid status \"%V\"",
|
1312
|
+
status_line);
|
1313
|
+
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
1314
|
+
}
|
1315
|
+
|
1316
|
+
u->headers_in.status_n = status;
|
1317
|
+
u->headers_in.status_line = *status_line;
|
1318
|
+
|
1319
|
+
} else if (u->headers_in.location) {
|
1320
|
+
u->headers_in.status_n = 302;
|
1321
|
+
ngx_str_set(&u->headers_in.status_line,
|
1322
|
+
"302 Moved Temporarily");
|
1323
|
+
|
1324
|
+
} else {
|
1325
|
+
u->headers_in.status_n = 200;
|
1326
|
+
ngx_str_set(&u->headers_in.status_line, "200 OK");
|
1327
|
+
}
|
1328
|
+
|
1329
|
+
if (u->state) {
|
1330
|
+
u->state->status = u->headers_in.status_n;
|
1331
|
+
}
|
1332
|
+
|
1333
|
+
done:
|
1334
|
+
|
1335
|
+
/* Supported since Nginx 1.3.15. */
|
1336
|
+
#ifdef NGX_HTTP_SWITCHING_PROTOCOLS
|
1337
|
+
if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS
|
1338
|
+
&& r->headers_in.upgrade)
|
1339
|
+
{
|
1340
|
+
u->upgrade = 1;
|
1341
|
+
}
|
1342
|
+
#endif
|
1343
|
+
|
1233
1344
|
return NGX_OK;
|
1234
1345
|
}
|
1235
1346
|
|
@@ -1390,6 +1501,7 @@ passenger_content_handler(ngx_http_request_t *r)
|
|
1390
1501
|
u->process_header = process_status_line;
|
1391
1502
|
u->abort_request = abort_request;
|
1392
1503
|
u->finalize_request = finalize_request;
|
1504
|
+
r->state = 0;
|
1393
1505
|
|
1394
1506
|
u->buffering = slcf->upstream_config.buffering;
|
1395
1507
|
|
@@ -1403,6 +1515,8 @@ passenger_content_handler(ngx_http_request_t *r)
|
|
1403
1515
|
|
1404
1516
|
rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
|
1405
1517
|
|
1518
|
+
fix_peer_address(r);
|
1519
|
+
|
1406
1520
|
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
|
1407
1521
|
return rc;
|
1408
1522
|
}
|
@@ -246,6 +246,7 @@ start_helper_server(ngx_cycle_t *cycle) {
|
|
246
246
|
char *default_user = NULL;
|
247
247
|
char *default_group = NULL;
|
248
248
|
char *passenger_root = NULL;
|
249
|
+
char *default_ruby = NULL;
|
249
250
|
char *temp_dir = NULL;
|
250
251
|
char *analytics_log_user;
|
251
252
|
char *analytics_log_group;
|
@@ -262,6 +263,7 @@ start_helper_server(ngx_cycle_t *cycle) {
|
|
262
263
|
default_user = ngx_str_null_terminate(&passenger_main_conf.default_user);
|
263
264
|
default_group = ngx_str_null_terminate(&passenger_main_conf.default_group);
|
264
265
|
passenger_root = ngx_str_null_terminate(&passenger_main_conf.root_dir);
|
266
|
+
default_ruby = ngx_str_null_terminate(&passenger_main_conf.default_ruby);
|
265
267
|
temp_dir = ngx_str_null_terminate(&passenger_main_conf.temp_dir);
|
266
268
|
analytics_log_user = ngx_str_null_terminate(&passenger_main_conf.analytics_log_user);
|
267
269
|
analytics_log_group = ngx_str_null_terminate(&passenger_main_conf.analytics_log_group);
|
@@ -287,7 +289,7 @@ start_helper_server(ngx_cycle_t *cycle) {
|
|
287
289
|
temp_dir, passenger_main_conf.user_switching,
|
288
290
|
default_user, default_group,
|
289
291
|
core_conf->user, core_conf->group,
|
290
|
-
passenger_root,
|
292
|
+
passenger_root, default_ruby, passenger_main_conf.max_pool_size,
|
291
293
|
passenger_main_conf.max_instances_per_app,
|
292
294
|
passenger_main_conf.pool_idle_time,
|
293
295
|
"",
|
@@ -350,6 +352,7 @@ cleanup:
|
|
350
352
|
free(default_user);
|
351
353
|
free(default_group);
|
352
354
|
free(passenger_root);
|
355
|
+
free(default_ruby);
|
353
356
|
free(temp_dir);
|
354
357
|
free(analytics_log_user);
|
355
358
|
free(analytics_log_group);
|
@@ -61,7 +61,7 @@ public:
|
|
61
61
|
ret = pthread_spin_init(&spin, PTHREAD_PROCESS_PRIVATE);
|
62
62
|
} while (ret == EINTR);
|
63
63
|
if (ret != 0) {
|
64
|
-
throw boost::thread_resource_error("Cannot initialize a spin lock"
|
64
|
+
throw boost::thread_resource_error(ret, "Cannot initialize a spin lock");
|
65
65
|
}
|
66
66
|
}
|
67
67
|
|
@@ -78,7 +78,7 @@ public:
|
|
78
78
|
ret = pthread_spin_lock(&spin);
|
79
79
|
} while (OXT_UNLIKELY(ret == EINTR));
|
80
80
|
if (OXT_UNLIKELY(ret != 0)) {
|
81
|
-
throw boost::thread_resource_error("Cannot lock spin lock"
|
81
|
+
throw boost::thread_resource_error(ret, "Cannot lock spin lock");
|
82
82
|
}
|
83
83
|
}
|
84
84
|
|
@@ -88,7 +88,7 @@ public:
|
|
88
88
|
ret = pthread_spin_unlock(&spin);
|
89
89
|
} while (OXT_UNLIKELY(ret == EINTR));
|
90
90
|
if (OXT_UNLIKELY(ret != 0)) {
|
91
|
-
throw boost::thread_resource_error("Cannot unlock spin lock"
|
91
|
+
throw boost::thread_resource_error(ret, "Cannot unlock spin lock");
|
92
92
|
}
|
93
93
|
}
|
94
94
|
|
@@ -102,7 +102,7 @@ public:
|
|
102
102
|
} else if (ret == EBUSY) {
|
103
103
|
return false;
|
104
104
|
} else {
|
105
|
-
throw boost::thread_resource_error("Cannot lock spin lock"
|
105
|
+
throw boost::thread_resource_error(ret, "Cannot lock spin lock");
|
106
106
|
}
|
107
107
|
}
|
108
108
|
};
|
data/ext/oxt/macros.hpp
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
* OXT - OS eXtensions for boosT
|
3
3
|
* Provides important functionality necessary for writing robust server software.
|
4
4
|
*
|
5
|
-
* Copyright (c) 2010
|
5
|
+
* Copyright (c) 2010-2013 Phusion
|
6
6
|
*
|
7
7
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
8
|
* of this software and associated documentation files (the "Software"), to deal
|
@@ -36,27 +36,49 @@
|
|
36
36
|
+ __GNUC_MINOR__ * 100 \
|
37
37
|
+ __GNUC_PATCHLEVEL__)
|
38
38
|
|
39
|
-
#if (defined(__GNUC__) && (__GNUC__ > 2)
|
39
|
+
#if (defined(__GNUC__) && (__GNUC__ > 2)) || defined(IN_DOXYGEN)
|
40
40
|
/**
|
41
41
|
* Indicate that the given expression is likely to be true.
|
42
42
|
* This allows the CPU to better perform branch prediction.
|
43
|
-
*
|
44
|
-
* Defining OXT_DEBUG will cause this macro to become an
|
45
|
-
* empty stub.
|
46
43
|
*/
|
47
44
|
#define OXT_LIKELY(expr) __builtin_expect((expr), 1)
|
48
45
|
|
49
46
|
/**
|
50
47
|
* Indicate that the given expression is likely to be false.
|
51
48
|
* This allows the CPU to better perform branch prediction.
|
52
|
-
*
|
53
|
-
* Defining OXT_DEBUG will cause this macro to become an
|
54
|
-
* empty stub.
|
55
49
|
*/
|
56
50
|
#define OXT_UNLIKELY(expr) __builtin_expect((expr), 0)
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Force inlining of the given function.
|
54
|
+
*/
|
55
|
+
#define OXT_FORCE_INLINE __attribute__((always_inline))
|
56
|
+
|
57
|
+
#if __GNUC__ >= 4
|
58
|
+
#define OXT_RESTRICT __restrict__
|
59
|
+
#else
|
60
|
+
#define OXT_RESTRICT
|
61
|
+
#endif
|
62
|
+
#ifndef restrict
|
63
|
+
/**
|
64
|
+
* The C99 'restrict' keyword, now usable in C++.
|
65
|
+
*/
|
66
|
+
#define restrict OXT_RESTRICT
|
67
|
+
#endif
|
68
|
+
#ifndef restrict_ref
|
69
|
+
/**
|
70
|
+
* The C99 'restrict' keyword, for use with C++ references.
|
71
|
+
* On compilers that support 'restrict' in C++ but not on
|
72
|
+
* references, this macro does nothing.
|
73
|
+
*/
|
74
|
+
#define restrict_ref OXT_RESTRICT
|
75
|
+
#endif
|
57
76
|
#else
|
58
77
|
#define OXT_LIKELY(expr) expr
|
59
78
|
#define OXT_UNLIKELY(expr) expr
|
79
|
+
#define OXT_FORCE_INLINE
|
80
|
+
#define restrict
|
81
|
+
#define restrict_ref
|
60
82
|
#endif
|
61
83
|
|
62
84
|
/*
|
data/lib/phusion_passenger.rb
CHANGED
@@ -31,10 +31,10 @@ module PhusionPassenger
|
|
31
31
|
PACKAGE_NAME = 'passenger'
|
32
32
|
|
33
33
|
# Phusion Passenger version number. Don't forget to edit ext/common/Constants.h too.
|
34
|
-
VERSION_STRING = '4.0.0.
|
34
|
+
VERSION_STRING = '4.0.0.rc6'
|
35
35
|
|
36
36
|
PREFERRED_NGINX_VERSION = '1.2.7'
|
37
|
-
PREFERRED_PCRE_VERSION = '8.
|
37
|
+
PREFERRED_PCRE_VERSION = '8.32'
|
38
38
|
STANDALONE_INTERFACE_VERSION = 1
|
39
39
|
|
40
40
|
|