mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66099275ca | ||
|
|
e7a40eb173 | ||
|
|
8342150b78 | ||
|
|
e2253f3693 | ||
|
|
d2f07c7583 | ||
|
|
1c87053a13 | ||
|
|
d69e23414f | ||
|
|
3d37d272ee | ||
|
|
9094a0f811 | ||
|
|
97efcca2b7 | ||
|
|
2445fd1f61 | ||
|
|
3234e0aae8 | ||
|
|
c5e7eb5d95 | ||
|
|
e051e4fe1c | ||
|
|
5f691ec987 | ||
|
|
a8e0aac9b0 | ||
|
|
bcdbab247c | ||
|
|
2e378dfc29 | ||
|
|
acc270ad81 | ||
|
|
b0c3ee02f9 | ||
|
|
06ab5eaee5 | ||
|
|
46de2ae0cb | ||
|
|
65fe93ac14 | ||
|
|
f7cdd22f9a | ||
|
|
3d553d2ae0 | ||
|
|
582d5828aa | ||
|
|
245a66b0e5 | ||
|
|
596c81124e | ||
|
|
a86a1fcc40 | ||
|
|
34036ac8b4 | ||
|
|
11cd6c34a5 | ||
|
|
aaea6ff2e2 | ||
|
|
38c30bc257 | ||
|
|
2f3e83b78e | ||
|
|
43e8c65841 | ||
|
|
555902a0ee | ||
|
|
9d4f4eb3c3 | ||
|
|
5d338cfb3a | ||
|
|
3406441d95 | ||
|
|
df08c7bfb5 | ||
|
|
75b4a3cb28 | ||
|
|
c356c01f12 | ||
|
|
ba8aa44baa | ||
|
|
a1dc7a660c | ||
|
|
3a4663844b | ||
|
|
309f449a43 | ||
|
|
f059a69312 | ||
|
|
93116a1239 | ||
|
|
5e4440443a | ||
|
|
373481b888 | ||
|
|
105b9c69cf | ||
|
|
9012ead72c | ||
|
|
6c1d2625a8 | ||
|
|
c0733b5771 | ||
|
|
f4759d7acd | ||
|
|
7082188a06 | ||
|
|
bcd9ed011d | ||
|
|
25c6d7a3a1 | ||
|
|
675c02c7fa | ||
|
|
32896a1418 | ||
|
|
548e736d84 | ||
|
|
87575b1a22 | ||
|
|
1aa6eeca1b | ||
|
|
f778e30d48 | ||
|
|
e071184d53 | ||
|
|
1d09cde778 | ||
|
|
70ee29becb | ||
|
|
60e26333bf | ||
|
|
865b9c199d | ||
|
|
833193a1ba | ||
|
|
4eab050634 | ||
|
|
688d1d3b75 | ||
|
|
349daee614 | ||
|
|
0d272cf747 | ||
|
|
46ac28efae | ||
|
|
31b3bcc83d | ||
|
|
f364d676fa | ||
|
|
c72fde1eed | ||
|
|
a5cacfbba6 | ||
|
|
921cfa5d79 | ||
|
|
9c676c62f5 | ||
|
|
2917de3e76 | ||
|
|
e836272c07 | ||
|
|
7e25452242 | ||
|
|
42d42d9e4c | ||
|
|
73c3e971e6 | ||
|
|
b627edf1b8 | ||
|
|
7fbc46750b | ||
|
|
1a63634359 | ||
|
|
c30e99a0df | ||
|
|
3c53f26cbd | ||
|
|
a5c74293d8 | ||
|
|
e5da0fc28c | ||
|
|
8e9bcc4758 | ||
|
|
bcf1f46d33 | ||
|
|
8cd13f2ad9 | ||
|
|
13df278cc4 | ||
|
|
56fedbd80c | ||
|
|
c4b563f260 | ||
|
|
39706c5899 | ||
|
|
e45f710694 | ||
|
|
0c86212aa2 | ||
|
|
3cfa743cb5 | ||
|
|
f14cb7e02a | ||
|
|
7fbc4013ca | ||
|
|
0324e5965c | ||
|
|
2050d38f96 | ||
|
|
fadce6cfe5 | ||
|
|
0ac4f8f1e4 | ||
|
|
51e81eff31 | ||
|
|
4818a5d386 | ||
|
|
4457fbefd6 | ||
|
|
9780e5fc5e | ||
|
|
9c18e0e12a | ||
|
|
c4c146dca4 | ||
|
|
08e1cf211c | ||
|
|
a52a6fc1e1 | ||
|
|
6e1c468eed | ||
|
|
1c186db72a | ||
|
|
92a8d6f2c5 | ||
|
|
144ffbaa25 | ||
|
|
3e910aaca2 | ||
|
|
5b2a3c28d0 | ||
|
|
01a5611159 | ||
|
|
bf692c4d18 | ||
|
|
a09ee5153d | ||
|
|
bc9f5d6f88 | ||
|
|
ec25be94ba | ||
|
|
7e8e113921 | ||
|
|
0575859f2d | ||
|
|
e9c0bf91ad | ||
|
|
53fb764830 | ||
|
|
76393e36be | ||
|
|
94a39e1755 | ||
|
|
e675b49ef8 | ||
|
|
78b330dd96 | ||
|
|
293ee92791 | ||
|
|
dac7457927 | ||
|
|
e1b3d8fd1a |
+10
@@ -4,6 +4,12 @@
|
||||
*.jar
|
||||
*~
|
||||
*.so
|
||||
*.gox
|
||||
*.a
|
||||
*.dll
|
||||
*.key
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
/uwsgi
|
||||
/uwsgibuild.*
|
||||
@@ -12,3 +18,7 @@
|
||||
/t/ring/target
|
||||
|
||||
core/dot_h.c
|
||||
|
||||
+# coverity
|
||||
+/cov-int/
|
||||
+uwsgi.tar.xz
|
||||
|
||||
+3
-1
@@ -1,7 +1,7 @@
|
||||
- this is a incomplete list of all the contributors of the project -
|
||||
|
||||
Roberto De Ioris, Unbit, <roberto@unbit.it>
|
||||
Riccardo Magliocchetti, Unbit, <riccardo@unbit.it>
|
||||
Riccardo Magliocchetti
|
||||
Yann Malet, Lincoln Loop
|
||||
Simon Litchfield
|
||||
Masahiro Honma, <hiratara@cpan.org>
|
||||
@@ -28,3 +28,5 @@ Ryan Petrello
|
||||
Danila Shtan <danila@shtan.ru>
|
||||
Ævar Arnfjörð Bjarmason
|
||||
Yu Zhao (getcwd)
|
||||
Mathieu Dupuy
|
||||
Adriano Di Luzio (adriano@unbit.it)
|
||||
|
||||
@@ -365,12 +365,13 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
ap_set_content_type(r, apr_pstrdup(r->pool, buf));
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int finish = 0;
|
||||
while(!finish) {
|
||||
rv = ap_get_brigade(rp->input_filters, bb,
|
||||
AP_MODE_READBYTES, mode,
|
||||
conf->io_buffer_size);
|
||||
if (mode == APR_NONBLOCK_READ && (APR_STATUS_IS_EAGAIN(rv)
|
||||
|| (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)))) {
|
||||
if (APR_STATUS_IS_EAGAIN(rv)
|
||||
|| (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) ) {
|
||||
e = apr_bucket_flush_create(c->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, e);
|
||||
if (ap_pass_brigade(r->output_filters, bb) || c->aborted) {
|
||||
@@ -401,7 +402,16 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
|
||||
ap_proxy_buckets_lifetime_transform(r, bb, pass_bb);
|
||||
|
||||
ap_pass_brigade(r->output_filters, pass_bb);
|
||||
// found the last brigade?
|
||||
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) finish = 1;
|
||||
|
||||
// do not pass chunk if it is zero_sized
|
||||
apr_brigade_length(pass_bb, 0, &readbytes);
|
||||
|
||||
if ((readbytes > 0 && ap_pass_brigade(r->output_filters, pass_bb) != APR_SUCCESS) || c->aborted) {
|
||||
finish = 1;
|
||||
}
|
||||
|
||||
apr_brigade_cleanup(bb);
|
||||
apr_brigade_cleanup(pass_bb);
|
||||
}
|
||||
|
||||
Binary file not shown.
+2
-1
@@ -369,7 +369,8 @@ void async_schedule_to_req_green(void) {
|
||||
uwsgi.schedule_fix(wsgi_req);
|
||||
}
|
||||
// switch after each yield
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
if (uwsgi.schedule_to_main)
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
|
||||
+106
-30
@@ -24,6 +24,49 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
*/
|
||||
|
||||
static void cache_full(struct uwsgi_cache *uc) {
|
||||
uint64_t i;
|
||||
int force_clear = 0;
|
||||
|
||||
if (!uc->ignore_full) {
|
||||
if (uc->purge_lru)
|
||||
uwsgi_log("LRU item will be purged from cache \"%s\"\n", uc->name);
|
||||
else
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
}
|
||||
|
||||
uc->full++;
|
||||
|
||||
if (uc->purge_lru && uc->lru_head)
|
||||
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
|
||||
|
||||
// we do not need locking here !
|
||||
if (uc->sweep_on_full) {
|
||||
uint64_t removed = 0;
|
||||
uint64_t now = (uint64_t) uwsgi_now();
|
||||
if (uc->next_scan <= now) {
|
||||
uc->next_scan = now + uc->sweep_on_full;
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
struct uwsgi_cache_item *uci = cache_item(i);
|
||||
if (uci->expires > 0 && uci->expires <= now) {
|
||||
if (!uwsgi_cache_del2(uc, NULL, 0, i, 0)) {
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removed == 0) {
|
||||
force_clear = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uc->clear_on_full || force_clear) {
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
uwsgi_cache_del2(uc, NULL, 0, i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_cache_find_free_blocks(struct uwsgi_cache *uc, uint64_t need) {
|
||||
// how many blocks we need ?
|
||||
uint64_t needed_blocks = need/uc->blocksize;
|
||||
@@ -331,6 +374,14 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
int cache_fd;
|
||||
struct stat cst;
|
||||
|
||||
if (uc->store_delete && !stat(uc->store, &cst) && ((size_t) cst.st_size != uc->filesize || !S_ISREG(cst.st_mode))) {
|
||||
uwsgi_log("Removing invalid cache store file: %s\n", uc->store);
|
||||
if (unlink(uc->store) != 0) {
|
||||
uwsgi_log("Cannot remove invalid cache store file: %s\n", uc->store);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (stat(uc->store, &cst)) {
|
||||
uwsgi_log("creating a new cache store file: %s\n", uc->store);
|
||||
cache_fd = open(uc->store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
@@ -412,6 +463,17 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
|
||||
}
|
||||
|
||||
static uint64_t check_lazy(struct uwsgi_cache *uc, struct uwsgi_cache_item *uci, uint64_t slot) {
|
||||
if (!uci->expires || !uc->lazy_expire) return slot;
|
||||
uint64_t now = (uint64_t) uwsgi_now();
|
||||
// expired ?
|
||||
if (uci->expires <= now) {
|
||||
uwsgi_cache_del2(uc, NULL, 0, slot, UWSGI_CACHE_FLAG_LOCAL);
|
||||
return 0;
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
|
||||
|
||||
uint32_t hash = uc->hash->func(key, keylen);
|
||||
@@ -437,7 +499,7 @@ static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_
|
||||
if (memcmp(uci->key, key, keylen))
|
||||
goto cycle;
|
||||
|
||||
return slot;
|
||||
return check_lazy(uc, uci, slot);
|
||||
|
||||
cycle:
|
||||
while (uci->next) {
|
||||
@@ -460,8 +522,9 @@ cycle:
|
||||
continue;
|
||||
if (uci->keysize != keylen)
|
||||
continue;
|
||||
if (!memcmp(uci->key, key, keylen))
|
||||
return slot;
|
||||
if (!memcmp(uci->key, key, keylen)) {
|
||||
return check_lazy(uc, uci, slot);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -710,15 +773,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
if (!index) {
|
||||
if (!uc->unused_blocks_stack_ptr) {
|
||||
if (!uc->ignore_full) {
|
||||
if (uc->purge_lru)
|
||||
uwsgi_log("LRU item will be purged from cache \"%s\"\n", uc->name);
|
||||
else
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
}
|
||||
uc->full++;
|
||||
if (uc->purge_lru && uc->lru_head)
|
||||
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
|
||||
cache_full(uc);
|
||||
if (!uc->unused_blocks_stack_ptr)
|
||||
goto end;
|
||||
}
|
||||
@@ -733,16 +788,14 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
else {
|
||||
uci->first_block = uwsgi_cache_find_free_blocks(uc, vallen);
|
||||
if (uci->first_block == 0xffffffffffffffffLLU) {
|
||||
if (!uc->ignore_full)
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
uc->full++;
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
cache_full(uc);
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + needed_blocks > uc->blocks) {
|
||||
if (uci->first_block + needed_blocks >= uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
else {
|
||||
@@ -837,16 +890,14 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uint64_t old_first_block = uci->first_block;
|
||||
uci->first_block = uwsgi_cache_find_free_blocks(uc, vallen);
|
||||
if (uci->first_block == 0xffffffffffffffffLLU) {
|
||||
if (!uc->ignore_full)
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
uc->full++;
|
||||
uci->first_block = old_first_block;
|
||||
cache_full(uc);
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + needed_blocks > uc->blocks) {
|
||||
if (uci->first_block + needed_blocks >= uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
else {
|
||||
@@ -1052,7 +1103,7 @@ static uint64_t cache_sweeper_free_items(struct uwsgi_cache *uc) {
|
||||
uint64_t i;
|
||||
uint64_t freed_items = 0;
|
||||
|
||||
if (uc->no_expire || uc->purge_lru)
|
||||
if (uc->no_expire || uc->purge_lru || uc->lazy_expire)
|
||||
return 0;
|
||||
|
||||
uwsgi_rlock(uc->lock);
|
||||
@@ -1131,20 +1182,24 @@ void uwsgi_cache_start_sweepers() {
|
||||
if (uwsgi.cache_no_expire)
|
||||
return;
|
||||
|
||||
int need_to_run = 0;
|
||||
while(uc) {
|
||||
pthread_t cache_sweeper;
|
||||
if (!uc->no_expire && !uc->purge_lru) {
|
||||
if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, uwsgi.caches)) {
|
||||
uwsgi_error("pthread_create()");
|
||||
uwsgi_log("unable to run the sweeper!!!\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("sweeper thread enabled\n");
|
||||
}
|
||||
if (!uc->no_expire && !uc->purge_lru && !uc->lazy_expire) {
|
||||
need_to_run = 1;
|
||||
break;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
if (!need_to_run) return;
|
||||
|
||||
pthread_t cache_sweeper;
|
||||
if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, uwsgi.caches)) {
|
||||
uwsgi_error("uwsgi_cache_start_sweepers()/pthread_create()");
|
||||
uwsgi_log("unable to run the cache sweeper!!!\n");
|
||||
return;
|
||||
}
|
||||
uwsgi_log("cache sweeper thread enabled\n");
|
||||
}
|
||||
|
||||
void uwsgi_cache_start_sync_servers() {
|
||||
@@ -1212,6 +1267,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
char *c_keysize = NULL;
|
||||
char *c_store = NULL;
|
||||
char *c_store_sync = NULL;
|
||||
char *c_store_delete = NULL;
|
||||
char *c_nodes = NULL;
|
||||
char *c_sync = NULL;
|
||||
char *c_udp_servers = NULL;
|
||||
@@ -1220,6 +1276,10 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
char *c_math_initial = NULL;
|
||||
char *c_ignore_full = NULL;
|
||||
char *c_purge_lru = NULL;
|
||||
char *c_lazy_expire = NULL;
|
||||
char *c_sweep_on_full = NULL;
|
||||
char *c_clear_on_full = NULL;
|
||||
char *c_no_expire = NULL;
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"name", &c_name,
|
||||
@@ -1236,6 +1296,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
"store", &c_store,
|
||||
"store_sync", &c_store_sync,
|
||||
"storesync", &c_store_sync,
|
||||
"store_delete", &c_store_delete,
|
||||
"storedelete", &c_store_delete,
|
||||
"node", &c_nodes,
|
||||
"nodes", &c_nodes,
|
||||
"sync", &c_sync,
|
||||
@@ -1250,6 +1312,11 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
"ignore_full", &c_ignore_full,
|
||||
"purge_lru", &c_purge_lru,
|
||||
"lru", &c_purge_lru,
|
||||
"lazy_expire", &c_lazy_expire,
|
||||
"lazy", &c_lazy_expire,
|
||||
"sweep_on_full", &c_sweep_on_full,
|
||||
"clear_on_full", &c_clear_on_full,
|
||||
"no_expire", &c_no_expire,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse cache definition\n");
|
||||
exit(1);
|
||||
@@ -1299,8 +1366,17 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
if (c_use_last_modified) uc->use_last_modified = 1;
|
||||
if (c_ignore_full) uc->ignore_full = 1;
|
||||
|
||||
if (c_store_delete) uc->store_delete = 1;
|
||||
|
||||
if (c_math_initial) uc->math_initial = strtol(c_math_initial, NULL, 10);
|
||||
|
||||
if (c_lazy_expire) uc->lazy_expire = 1;
|
||||
if (c_sweep_on_full) {
|
||||
uc->sweep_on_full = uwsgi_n64(c_sweep_on_full);
|
||||
}
|
||||
if (c_clear_on_full) uc->clear_on_full = 1;
|
||||
if (c_no_expire) uc->no_expire = 1;
|
||||
|
||||
uc->store_sync = uwsgi.cache_store_sync;
|
||||
if (c_store_sync) { uc->store_sync = uwsgi_n64(c_store_sync); }
|
||||
|
||||
|
||||
+6
-1
@@ -237,7 +237,12 @@ void uwsgi_detach_daemons() {
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
int waitpid_status;
|
||||
while (!kill(ud->pid, 0)) {
|
||||
kill(-(ud->pid), ud->stop_signal);
|
||||
if (uwsgi_instance_is_reloading && ud->reload_signal > 0) {
|
||||
kill(-(ud->pid), ud->reload_signal);
|
||||
}
|
||||
else {
|
||||
kill(-(ud->pid), ud->stop_signal);
|
||||
}
|
||||
sleep(1);
|
||||
waitpid(ud->pid, &waitpid_status, WNOHANG);
|
||||
if (uwsgi_now() >= timeout) {
|
||||
|
||||
+59
-4
@@ -13,6 +13,7 @@ void emperor_send_stats(int);
|
||||
|
||||
time_t emperor_throttle;
|
||||
int emperor_throttle_level;
|
||||
int emperor_warming_up = 1;
|
||||
|
||||
struct uwsgi_instance *ui;
|
||||
|
||||
@@ -867,7 +868,16 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("emperor throttle = %d\n", emperor_throttle_level);
|
||||
#endif
|
||||
usleep(emperor_throttle_level);
|
||||
if (emperor_warming_up) {
|
||||
if (emperor_throttle_level > 0) {
|
||||
// wait 10 milliseconds in case of fork-bombing
|
||||
// pretty random value, but should avoid the load average to increase
|
||||
usleep(10);
|
||||
}
|
||||
}
|
||||
else {
|
||||
usleep(emperor_throttle_level);
|
||||
}
|
||||
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (uid == 0 || gid == 0) {
|
||||
@@ -1015,14 +1025,14 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_emperor) {
|
||||
uwsgi_log("mounting \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
uwsgi_log("unable to mount %s\n", usl->value);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_as_emperor) {
|
||||
uwsgi_log("un-mounting \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
uwsgi_log("unable to umount %s\n", usl->value);
|
||||
}
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.exec_as_emperor) {
|
||||
@@ -1093,7 +1103,20 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
|
||||
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
int i;
|
||||
|
||||
// run plugin hooks for the vassal
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->vassal) {
|
||||
uwsgi.p[i]->vassal(n_ui);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->vassal) {
|
||||
uwsgi.gp[i]->vassal(n_ui);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
@@ -1350,7 +1373,6 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
int i;
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
if (uwsgi_fd_is_safe(i))
|
||||
continue;
|
||||
@@ -1429,10 +1451,24 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
func(n_ui->name, n_ui->uid, n_ui->gid);
|
||||
}
|
||||
|
||||
// ->vassal_before_exec
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->vassal_before_exec) {
|
||||
uwsgi.p[i]->vassal_before_exec(n_ui);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->vassal) {
|
||||
uwsgi.gp[i]->vassal_before_exec(n_ui);
|
||||
}
|
||||
}
|
||||
|
||||
// start !!!
|
||||
if (execvp(vassal_argv[0], vassal_argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
}
|
||||
uwsgi_log("[emperor] binary path: %s\n", vassal_argv[0]);
|
||||
uwsgi_log("[emperor] is the uwsgi binary in your system PATH ?\n");
|
||||
// never here
|
||||
exit(UWSGI_EXILE_CODE);
|
||||
@@ -1528,6 +1564,7 @@ void uwsgi_emperor_run_scanners(void) {
|
||||
ues->monitor->func(ues);
|
||||
ues = ues->next;
|
||||
}
|
||||
emperor_warming_up = 0;
|
||||
}
|
||||
|
||||
void emperor_build_scanners() {
|
||||
@@ -1738,6 +1775,8 @@ void emperor_loop() {
|
||||
if (ui_current) {
|
||||
char byte;
|
||||
ssize_t rlen = read(interesting_fd, &byte, 1);
|
||||
// retry if needed
|
||||
if (rlen < 0 && uwsgi_is_again()) continue;
|
||||
if (rlen <= 0) {
|
||||
// SAFE
|
||||
event_queue_del_fd(uwsgi.emperor_queue, interesting_fd, event_queue_read());
|
||||
@@ -2322,7 +2361,17 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
|
||||
|
||||
void uwsgi_master_manage_emperor() {
|
||||
char byte;
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
// special cose for port event system
|
||||
// place the socket in non-blocking mode
|
||||
uwsgi_socket_nb(uwsgi.emperor_fd);
|
||||
#endif
|
||||
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
// special cose for port event system
|
||||
// and place back in blocking mode
|
||||
uwsgi_socket_b(uwsgi.emperor_fd);
|
||||
#endif
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("received message %d from emperor\n", byte);
|
||||
// remove me
|
||||
@@ -2342,6 +2391,12 @@ void uwsgi_master_manage_emperor() {
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
// special cose for port event system
|
||||
else if (rlen < 0 && uwsgi_is_again()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
uwsgi_error("uwsgi_master_manage_emperor()/read()");
|
||||
uwsgi_log("lost connection with my emperor !!!\n");
|
||||
|
||||
+7
-6
@@ -414,11 +414,11 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno != ETIME) {
|
||||
uwsgi_error("port_getn()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
uwsgi_error("port_getn()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint_t i;
|
||||
@@ -452,6 +452,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
else {
|
||||
ret = port_get(eq, &pe, NULL);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
@@ -947,7 +948,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
struct timespec ts;
|
||||
struct kevent ev;
|
||||
|
||||
if (timeout <= 0) {
|
||||
if (timeout < 0) {
|
||||
ret = kevent(eq, NULL, 0, &ev, 1, NULL);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -80,6 +80,7 @@ void uwsgi_master_fifo_prepare() {
|
||||
|
||||
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
|
||||
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
|
||||
uwsgi_fifo_table['B'] = vassal_sos;
|
||||
uwsgi_fifo_table['c'] = uwsgi_chain_reload;
|
||||
uwsgi_fifo_table['C'] = uwsgi_go_cheap;
|
||||
uwsgi_fifo_table['E'] = emperor_rescan;
|
||||
|
||||
+15
-6
@@ -233,17 +233,26 @@ static int uwsgi_hook_writen(char *arg) {
|
||||
|
||||
static int uwsgi_hook_appendn(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook appendn syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
if (space)
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
if (space)
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
if (!space) {
|
||||
// simple newline
|
||||
if (write(fd, "\n", 1) != 1) {
|
||||
uwsgi_error("uwsgi_hook_appendn()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
char *buf = uwsgi_malloc(l + 1);
|
||||
|
||||
@@ -1212,6 +1212,9 @@ next:
|
||||
legion = legion->next;
|
||||
}
|
||||
|
||||
// this must be called only by the master !!!
|
||||
if (!uwsgi.workers) return;
|
||||
if (uwsgi.workers[0].pid != getpid()) return;
|
||||
uwsgi_legion_announce_death();
|
||||
}
|
||||
|
||||
|
||||
+79
-73
@@ -354,51 +354,51 @@ void uwsgi_setup_log() {
|
||||
|
||||
static struct uwsgi_logger *setup_choosen_logger(struct uwsgi_string_list *usl) {
|
||||
char *id = NULL;
|
||||
char *name = usl->value;
|
||||
char *name = usl->value;
|
||||
|
||||
char *space = strchr(name, ' ');
|
||||
if (space) {
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for (i = 0; i < (space - name); i++) {
|
||||
if (!isalnum((int)name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_id) {
|
||||
id = uwsgi_concat2n(name, space - name, "", 0);
|
||||
name = space + 1;
|
||||
}
|
||||
}
|
||||
char *space = strchr(name, ' ');
|
||||
if (space) {
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for (i = 0; i < (space - name); i++) {
|
||||
if (!isalnum((int)name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_id) {
|
||||
id = uwsgi_concat2n(name, space - name, "", 0);
|
||||
name = space + 1;
|
||||
}
|
||||
}
|
||||
|
||||
char *colon = strchr(name, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
char *colon = strchr(name, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
|
||||
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
|
||||
if (!choosen_logger) {
|
||||
uwsgi_log("unable to find logger %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
|
||||
if (!choosen_logger) {
|
||||
uwsgi_log("unable to find logger %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// make a copy of the logger
|
||||
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
|
||||
choosen_logger = copy_of_choosen_logger;
|
||||
choosen_logger->id = id;
|
||||
choosen_logger->next = NULL;
|
||||
// make a copy of the logger
|
||||
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
|
||||
choosen_logger = copy_of_choosen_logger;
|
||||
choosen_logger->id = id;
|
||||
choosen_logger->next = NULL;
|
||||
|
||||
if (colon) {
|
||||
choosen_logger->arg = colon + 1;
|
||||
// check for empty string
|
||||
if (*choosen_logger->arg == 0) {
|
||||
choosen_logger->arg = NULL;
|
||||
}
|
||||
*colon = ':';
|
||||
}
|
||||
return choosen_logger;
|
||||
if (colon) {
|
||||
choosen_logger->arg = colon + 1;
|
||||
// check for empty string
|
||||
if (*choosen_logger->arg == 0) {
|
||||
choosen_logger->arg = NULL;
|
||||
}
|
||||
*colon = ':';
|
||||
}
|
||||
return choosen_logger;
|
||||
}
|
||||
|
||||
void uwsgi_setup_log_master(void) {
|
||||
@@ -519,40 +519,46 @@ void uwsgi_check_logrotate(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_log_rotate() {
|
||||
if (!uwsgi.logfile) return;
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) uwsgi_now());
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
// this will be rawly written to the logfile
|
||||
uwsgi_logfile_write("logsize: %llu, triggering rotation to %s...\n", (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// reopen logfile and dup'it, on dup2 error, exit(1)
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
// this will be written to the original file
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
void uwsgi_log_do_rotate(char *logfile, char *rotatedfile, off_t logsize, int log_fd) {
|
||||
int need_free = 0;
|
||||
char *rot_name = rotatedfile;
|
||||
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) uwsgi_now());
|
||||
rot_name = uwsgi_concat3(logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
// this will be rawly written to the logfile
|
||||
uwsgi_logfile_write("logsize: %llu, triggering rotation to %s...\n", (unsigned long long) logsize, rot_name);
|
||||
if (rename(logfile, rot_name) == 0) {
|
||||
// reopen logfile and dup'it, on dup2 error, exit(1)
|
||||
int fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
// this will be written to the original file
|
||||
uwsgi_error_open(logfile);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, log_fd) < 0) {
|
||||
// this could be lost :(
|
||||
uwsgi_error("uwsgi_log_do_rotate()/dup2()");
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
// this could be lost :(
|
||||
uwsgi_error("uwsgi_log_rotate()/dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
|
||||
void uwsgi_log_rotate() {
|
||||
if (!uwsgi.logfile)
|
||||
return;
|
||||
uwsgi_log_do_rotate(uwsgi.logfile, uwsgi.log_backupname, uwsgi.shared->logsize, uwsgi.original_log_fd);
|
||||
}
|
||||
|
||||
void uwsgi_log_reopen() {
|
||||
|
||||
+27
-8
@@ -7,6 +7,7 @@ void uwsgi_update_load_counters() {
|
||||
int i;
|
||||
uint64_t busy_workers = 0;
|
||||
uint64_t idle_workers = 0;
|
||||
static time_t last_sos = 0;
|
||||
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
@@ -21,6 +22,15 @@ void uwsgi_update_load_counters() {
|
||||
|
||||
if (busy_workers >= (uint64_t) uwsgi.numproc) {
|
||||
ushared->overloaded++;
|
||||
|
||||
if (uwsgi.vassal_sos) {
|
||||
if (uwsgi.current_time - last_sos > uwsgi.vassal_sos) {
|
||||
uwsgi_log_verbose("asking Emperor for reinforcements (overload: %llu)...\n", (unsigned long long) ushared->overloaded);
|
||||
vassal_sos();
|
||||
last_sos = uwsgi.current_time;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ushared->busy_workers = busy_workers;
|
||||
@@ -273,17 +283,23 @@ static void master_check_listen_queue() {
|
||||
if (uwsgi.vassal_sos_backlog > 0 && uwsgi.has_emperor) {
|
||||
if (uwsgi.shared->backlog >= (uint64_t) uwsgi.vassal_sos_backlog) {
|
||||
// ask emperor for help
|
||||
char byte = 30;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("asking Emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->backlog);
|
||||
}
|
||||
uwsgi_log_verbose("asking Emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->backlog);
|
||||
vassal_sos();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vassal_sos() {
|
||||
if (!uwsgi.has_emperor) {
|
||||
uwsgi_log("[broodlord] instance not governed by an Emperor !!!\n");
|
||||
return;
|
||||
}
|
||||
char byte = 30;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("vassal_sos()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
int master_loop(char **argv, char **environ) {
|
||||
|
||||
struct timeval last_respawn;
|
||||
@@ -845,7 +861,10 @@ int master_loop(char **argv, char **environ) {
|
||||
if (touched) {
|
||||
uwsgi_log_verbose("*** %s has been touched... reloading daemon \"%s\" (pid: %d) !!! ***\n", touched, ud->command, (int) ud->pid);
|
||||
if (kill(-ud->pid, ud->stop_signal)) {
|
||||
uwsgi_error("[uwsgi-daemon/touch] kill()");
|
||||
// killing process group failed, try to kill by process id
|
||||
if (kill(ud->pid, ud->stop_signal)) {
|
||||
uwsgi_error("[uwsgi-daemon/touch] kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,12 +138,25 @@ void uwsgi_master_check_idle() {
|
||||
uwsgi.workers[i].cheaped = 1;
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
// first send SIGINT
|
||||
kill(uwsgi.workers[i].pid, SIGINT);
|
||||
// and start waiting upto 3 seconds
|
||||
int j;
|
||||
for(j=0;j<3;j++) {
|
||||
sleep(1);
|
||||
int ret = waitpid(uwsgi.workers[i].pid, &waitpid_status, WNOHANG);
|
||||
if (ret == 0) continue;
|
||||
if (ret == (int) uwsgi.workers[i].pid) goto done;
|
||||
// on error, directly send SIGKILL
|
||||
break;
|
||||
}
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
if (errno != ECHILD)
|
||||
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
|
||||
}
|
||||
else {
|
||||
done:
|
||||
uwsgi.workers[i].pid = 0;
|
||||
uwsgi.workers[i].rss_size = 0;
|
||||
uwsgi.workers[i].vsz_size = 0;
|
||||
@@ -335,6 +348,7 @@ int uwsgi_master_check_daemons_death(int diedpid) {
|
||||
|
||||
int uwsgi_worker_is_busy(int wid) {
|
||||
int i;
|
||||
if (uwsgi.workers[uwsgi.mywid].sig) return 1;
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
if (uwsgi.workers[wid].cores[i].in_request) {
|
||||
return 1;
|
||||
|
||||
@@ -162,6 +162,7 @@ int uwsgi_calc_cheaper(void) {
|
||||
ignore_algo = 1;
|
||||
}
|
||||
uwsgi.cheaper_fifo_delta = 0;
|
||||
goto safe;
|
||||
}
|
||||
|
||||
// if cheaper limits wants to change worker count, then skip cheaper algo
|
||||
@@ -172,6 +173,7 @@ int uwsgi_calc_cheaper(void) {
|
||||
needed_workers = 0;
|
||||
}
|
||||
|
||||
safe:
|
||||
if (needed_workers > 0) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
@@ -1719,6 +1721,7 @@ void uwsgi_setns_preopen() {
|
||||
}
|
||||
while ((de = readdir(ns)) != NULL) {
|
||||
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
|
||||
if (!strcmp(de->d_name, "user")) continue;
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
int found = 0;
|
||||
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
|
||||
@@ -1777,6 +1780,7 @@ void uwsgi_master_manage_setns(int fd) {
|
||||
}
|
||||
while ((de = readdir(ns)) != NULL) {
|
||||
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
|
||||
if (!strcmp(de->d_name, "user")) continue;
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
int found = 0;
|
||||
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
|
||||
|
||||
@@ -55,6 +55,9 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[offload] created session %p\n", uor);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -159,6 +162,12 @@ static int u_offload_sendfile_prepare(struct wsgi_request *wsgi_req, struct uwsg
|
||||
}
|
||||
|
||||
static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
|
||||
|
||||
// call the free function asap
|
||||
if (uor->free) {
|
||||
uor->free(uor);
|
||||
}
|
||||
|
||||
// close the socket and the file descriptor
|
||||
if (uor->takeover && uor->s > -1) {
|
||||
close(uor->s);
|
||||
@@ -197,12 +206,41 @@ static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_re
|
||||
uwsgi_buffer_destroy(uor->ubuf);
|
||||
}
|
||||
|
||||
if (uor->ubuf1) {
|
||||
uwsgi_buffer_destroy(uor->ubuf1);
|
||||
}
|
||||
if (uor->ubuf2) {
|
||||
uwsgi_buffer_destroy(uor->ubuf2);
|
||||
}
|
||||
if (uor->ubuf3) {
|
||||
uwsgi_buffer_destroy(uor->ubuf3);
|
||||
}
|
||||
if (uor->ubuf4) {
|
||||
uwsgi_buffer_destroy(uor->ubuf4);
|
||||
}
|
||||
if (uor->ubuf5) {
|
||||
uwsgi_buffer_destroy(uor->ubuf5);
|
||||
}
|
||||
if (uor->ubuf6) {
|
||||
uwsgi_buffer_destroy(uor->ubuf6);
|
||||
}
|
||||
if (uor->ubuf7) {
|
||||
uwsgi_buffer_destroy(uor->ubuf7);
|
||||
}
|
||||
if (uor->ubuf8) {
|
||||
uwsgi_buffer_destroy(uor->ubuf8);
|
||||
}
|
||||
|
||||
if (uor->pipe[0] != -1) {
|
||||
close(uor->pipe[1]);
|
||||
close(uor->pipe[0]);
|
||||
}
|
||||
|
||||
free(uor);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[offload] destroyed session %p\n", uor);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void uwsgi_offload_append(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
|
||||
|
||||
+40
-20
@@ -527,6 +527,11 @@ static int uwsgi_proto_check_22(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_X_FORWARDED_PROTO", 22)) {
|
||||
wsgi_req->scheme = buf;
|
||||
wsgi_req->scheme_len = len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -731,25 +736,40 @@ next:
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi_apps_cnt; i++) {
|
||||
//uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
|
||||
if (orig_path_info_len >= uwsgi_apps[i].mountpoint_len) {
|
||||
if (!uwsgi_startswith(orig_path_info, uwsgi_apps[i].mountpoint, uwsgi_apps[i].mountpoint_len) && uwsgi_apps[i].mountpoint_len > best_found) {
|
||||
best_found = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
|
||||
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len;
|
||||
wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len;
|
||||
char* mountpoint = uwsgi_apps[i].mountpoint;
|
||||
int mountpoint_len = uwsgi_apps[i].mountpoint_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name;
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
#endif
|
||||
}
|
||||
// Ignore trailing mountpoint slashes
|
||||
if (mountpoint_len > 0 && mountpoint[mountpoint_len - 1] == '/') {
|
||||
mountpoint_len -= 1;
|
||||
}
|
||||
|
||||
//uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
|
||||
|
||||
// Check if mountpoint could be a possible candidate
|
||||
if (orig_path_info_len < mountpoint_len || // it should be shorter than or equal to path_info
|
||||
mountpoint_len <= best_found || // it should be better than the previous found
|
||||
// should have the same prefix of path_info
|
||||
uwsgi_startswith(orig_path_info, mountpoint, mountpoint_len) ||
|
||||
// and should not be "misleading"
|
||||
(orig_path_info_len > mountpoint_len && orig_path_info[mountpoint_len] != '/' )) {
|
||||
continue;
|
||||
}
|
||||
|
||||
best_found = mountpoint_len;
|
||||
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
|
||||
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len;
|
||||
wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name;
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1051,7 +1071,7 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
|
||||
wsgi_req->var_cnt++;
|
||||
ptr += keylen;
|
||||
|
||||
|
||||
|
||||
|
||||
*ptr++ = (uint8_t) (vallen & 0xff);
|
||||
*ptr++ = (uint8_t) ((vallen >> 8) & 0xff);
|
||||
@@ -1118,13 +1138,13 @@ int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *i
|
||||
*ptr ++= '/';
|
||||
}
|
||||
memcpy(ptr, index, index_len);
|
||||
|
||||
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = new_path_info;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = wsgi_req->path_info_len;
|
||||
wsgi_req->var_cnt++;
|
||||
|
||||
wsgi_req->uh->pktsize += 13 + wsgi_req->path_info_len;
|
||||
wsgi_req->path_info = new_path_info;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
|
||||
// allocate more memory if needed
|
||||
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark == 0) {
|
||||
memcpy(wsgi_req->post_readline_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos);
|
||||
memmove(wsgi_req->post_readline_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos);
|
||||
wsgi_req->post_readline_watermark -= wsgi_req->post_readline_pos;
|
||||
wsgi_req->post_readline_pos = 0;
|
||||
// still something to use ?
|
||||
|
||||
@@ -2045,5 +2045,19 @@ next4:
|
||||
usl->custom2 = strlen(space+1);
|
||||
uwsgi_log("collecting header %.*s to var %s\n", usl->custom, usl->value, usl->custom_ptr);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.pull_headers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid pull header syntax, must be <header> <var>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
usl->custom = strlen(usl->value);
|
||||
*space = ' ';
|
||||
usl->custom_ptr = space+1;
|
||||
usl->custom2 = strlen(space+1);
|
||||
uwsgi_log("pulling header %.*s to var %s\n", usl->custom, usl->value, usl->custom_ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+2
-1
@@ -193,12 +193,13 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
close(fd);
|
||||
*len = rlen;
|
||||
if (*len == 0) {
|
||||
goto error;
|
||||
goto error2;
|
||||
}
|
||||
return buffer;
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
error2:
|
||||
free(buffer);
|
||||
return NULL;
|
||||
|
||||
|
||||
+10
-1
@@ -20,9 +20,18 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
|
||||
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
|
||||
return -1;
|
||||
#elif defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
|
||||
#elif defined(__linux__) || defined(__GNU_kFreeBSD__)
|
||||
off_t off = pos;
|
||||
return sendfile(sockfd, filefd, &off, len);
|
||||
#elif defined(__sun__)
|
||||
off_t off = pos;
|
||||
ssize_t wlen = sendfile(sockfd, filefd, &off, len);
|
||||
if (wlen < 0 && uwsgi_is_again()) {
|
||||
if (off - pos > 0) {
|
||||
return off-pos;
|
||||
}
|
||||
}
|
||||
return wlen;
|
||||
#endif
|
||||
|
||||
no_sendfile:
|
||||
|
||||
@@ -331,6 +331,16 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// send to al lactive workers
|
||||
else if (!strcmp(use->receiver, "active-workers")) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0 && !uwsgi.workers[i].cheaped && !uwsgi.workers[i].suspended) {
|
||||
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// route to specific worker
|
||||
else if (!strncmp(use->receiver, "worker", 6)) {
|
||||
i = atoi(use->receiver + 6);
|
||||
|
||||
+6
-1
@@ -189,7 +189,10 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_un));
|
||||
serverfd = create_server_socket(AF_UNIX, SOCK_STREAM);
|
||||
if (serverfd < 0) return -1;
|
||||
if (serverfd < 0) {
|
||||
free(uws_addr);
|
||||
return -1;
|
||||
}
|
||||
if (abstract_socket == 0) {
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
uwsgi_error("error removing unix socket, unlink()");
|
||||
@@ -563,6 +566,7 @@ char *generate_socket_name(char *socket_name) {
|
||||
ifa = ifap;
|
||||
while (ifa) {
|
||||
memset(new_addr, 0, 16);
|
||||
if (!ifa->ifa_addr) goto next;
|
||||
sin = (struct sockaddr_in *) ifa->ifa_addr;
|
||||
if (inet_ntop(AF_INET, (void *) &sin->sin_addr.s_addr, new_addr, 16)) {
|
||||
if (!strncmp(socket_name, new_addr, strlen(socket_name))) {
|
||||
@@ -575,6 +579,7 @@ char *generate_socket_name(char *socket_name) {
|
||||
|
||||
}
|
||||
|
||||
next:
|
||||
ifaf = ifa;
|
||||
ifa = ifaf->ifa_next;
|
||||
|
||||
|
||||
+6
-8
@@ -200,11 +200,13 @@ static void spooler_req_parser_hook(char *key, uint16_t key_len, char *value, ui
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CHANGED in 2.0.7: wsgi_req is useless !
|
||||
*/
|
||||
char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len, char *body, size_t body_len) {
|
||||
|
||||
struct timeval tv;
|
||||
static uint64_t internal_counter = 0;
|
||||
int core_id = 0;
|
||||
int fd = -1;
|
||||
struct spooler_req sr;
|
||||
|
||||
@@ -232,10 +234,6 @@ char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len,
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req) {
|
||||
core_id = wsgi_req->async_id;
|
||||
}
|
||||
|
||||
// this lock is for threads, the pid value in filename will avoid multiprocess races
|
||||
uwsgi_lock(uspool->lock);
|
||||
|
||||
@@ -260,7 +258,7 @@ char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len,
|
||||
// no need to check for errors...
|
||||
(void) mkdir(filename, 0777);
|
||||
|
||||
ret = snprintf(filename, filename_len, "%s/%.*s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, (int)sr.priority_len, sr.priority, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, core_id,
|
||||
ret = snprintf(filename, filename_len, "%s/%.*s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, (int)sr.priority_len, sr.priority, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, rand(),
|
||||
(unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
|
||||
if (ret <= 0 || ret >=(int) filename_len) {
|
||||
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
|
||||
@@ -272,8 +270,8 @@ char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len,
|
||||
else {
|
||||
filename_len = strlen(uspool->dir) + strlen(uwsgi.hostname) + 256;
|
||||
filename = uwsgi_malloc(filename_len);
|
||||
int ret = snprintf(filename, filename_len, "%s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, core_id,
|
||||
(unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
|
||||
int ret = snprintf(filename, filename_len, "%s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter,
|
||||
rand(), (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
|
||||
if (ret <= 0 || ret >= (int) filename_len) {
|
||||
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
|
||||
free(filename);
|
||||
|
||||
@@ -210,6 +210,10 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
ssloptions |= SSL_OP_NO_COMPRESSION;
|
||||
#endif
|
||||
|
||||
if (!uwsgi.sslv3) {
|
||||
ssloptions |= SSL_OP_NO_SSLv3;
|
||||
}
|
||||
|
||||
// release/reuse buffers as soon as possibile
|
||||
#ifdef SSL_MODE_RELEASE_BUFFERS
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
@@ -396,6 +400,11 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
|
||||
SSL_CTX_set_timeout(ctx, uwsgi.ssl_sessions_timeout);
|
||||
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.ssl_options) {
|
||||
ssloptions |= atoi(usl->value);
|
||||
}
|
||||
|
||||
SSL_CTX_set_options(ctx, ssloptions);
|
||||
|
||||
|
||||
|
||||
@@ -679,6 +679,10 @@ static struct uwsgi_buffer *uwsgi_subscription_ub(char *key, size_t keysize, uin
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keyval(ub, "address", 7, socket_name, strlen(socket_name)))
|
||||
goto end;
|
||||
|
||||
if (uwsgi.subscribe_with_modifier1) {
|
||||
modifier1 = atoi(uwsgi.subscribe_with_modifier1);
|
||||
}
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier1", 9, modifier1))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier2", 9, modifier2))
|
||||
|
||||
+81
-3
@@ -699,6 +699,22 @@ void uwsgi_as_root() {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.wait_for_fs) {
|
||||
if (uwsgi_wait_for_fs(usl->value, 0)) exit(1);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.wait_for_file) {
|
||||
if (uwsgi_wait_for_fs(usl->value, 1)) exit(1);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.wait_for_dir) {
|
||||
if (uwsgi_wait_for_fs(usl->value, 2)) exit(1);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.wait_for_mountpoint) {
|
||||
if (uwsgi_wait_for_mountpoint(usl->value)) exit(1);
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_root, "as root", 1);
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_root) {
|
||||
@@ -1019,8 +1035,14 @@ void uwsgi_destroy_request(struct wsgi_request *wsgi_req) {
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &foo);
|
||||
}
|
||||
|
||||
memset(wsgi_req, 0, sizeof(struct wsgi_request));
|
||||
// reset for avoiding following requests to fail on non-uwsgi protocols
|
||||
// thanks Marko Tiikkaja for catching it
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
|
||||
// some plugins expected async_id to be defined before setup
|
||||
int tmp_id = wsgi_req->async_id;
|
||||
memset(wsgi_req, 0, sizeof(struct wsgi_request));
|
||||
wsgi_req->async_id = tmp_id;
|
||||
}
|
||||
|
||||
// finalize/close/free a request
|
||||
@@ -1166,8 +1188,8 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
tmp_id = wsgi_req->async_id;
|
||||
memset(wsgi_req, 0, sizeof(struct wsgi_request));
|
||||
// some plugins expected async_id to be defined before setup
|
||||
wsgi_req->async_id = tmp_id;
|
||||
|
||||
// yes, this is pretty useless but we cannot ensure all of the plugin have the same behaviour
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
|
||||
|
||||
@@ -3393,7 +3415,7 @@ struct uwsgi_app *uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int
|
||||
}
|
||||
|
||||
if (!uwsgi.no_default_app) {
|
||||
if ((mountpoint_len == 0 || (mountpoint_len = -1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
|
||||
if ((mountpoint_len == 0 || (mountpoint_len == 1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
|
||||
uwsgi.default_app = id;
|
||||
}
|
||||
}
|
||||
@@ -4457,3 +4479,59 @@ mode_t uwsgi_mode_t(char *value, int *error) {
|
||||
return mode;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_wait_for_mountpoint(char *mountpoint) {
|
||||
if (!uwsgi.wait_for_fs_timeout) {
|
||||
uwsgi.wait_for_fs_timeout = 60;
|
||||
}
|
||||
uwsgi_log("waiting for %s (max %d seconds) ...\n", mountpoint, uwsgi.wait_for_fs_timeout);
|
||||
int counter = 0;
|
||||
for (;;) {
|
||||
if (counter > uwsgi.wait_for_fs_timeout) {
|
||||
uwsgi_log("%s unavailable after %d seconds\n", mountpoint, counter);
|
||||
return -1;
|
||||
}
|
||||
struct stat st0;
|
||||
struct stat st1;
|
||||
if (stat(mountpoint, &st0)) goto retry;
|
||||
if (!S_ISDIR(st0.st_mode)) goto retry;
|
||||
char *relative = uwsgi_concat2(mountpoint, "/../");
|
||||
if (stat(relative, &st1)) {
|
||||
free(relative);
|
||||
goto retry;
|
||||
}
|
||||
free(relative);
|
||||
// useless :P
|
||||
if (!S_ISDIR(st1.st_mode)) goto retry;
|
||||
if (st0.st_dev == st1.st_dev) goto retry;
|
||||
uwsgi_log_verbose("%s mounted\n", mountpoint);
|
||||
return 0;
|
||||
retry:
|
||||
sleep(1);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
// type -> 1 file, 2 dir, 0 both
|
||||
int uwsgi_wait_for_fs(char *filename, int type) {
|
||||
if (!uwsgi.wait_for_fs_timeout) {
|
||||
uwsgi.wait_for_fs_timeout = 60;
|
||||
}
|
||||
uwsgi_log("waiting for %s (max %d seconds) ...\n", filename, uwsgi.wait_for_fs_timeout);
|
||||
int counter = 0;
|
||||
for (;;) {
|
||||
if (counter > uwsgi.wait_for_fs_timeout) {
|
||||
uwsgi_log("%s unavailable after %d seconds\n", filename, counter);
|
||||
return -1;
|
||||
}
|
||||
struct stat st;
|
||||
if (stat(filename, &st)) goto retry;
|
||||
if (type == 1 && !S_ISREG(st.st_mode)) goto retry;
|
||||
if (type == 2 && !S_ISDIR(st.st_mode)) goto retry;
|
||||
uwsgi_log_verbose("%s found\n", filename);
|
||||
return 0;
|
||||
retry:
|
||||
sleep(1);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
+50
-13
@@ -71,8 +71,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
|
||||
{"socket-protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
|
||||
{"shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"undeferred-shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc (undeferred mode)", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"shared-socket", required_argument, 0, "create a shared socket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"undeferred-shared-socket", required_argument, 0, "create a shared socket for advanced jailing or ipc (undeferred mode)", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"processes", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
|
||||
{"workers", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
|
||||
{"thunder-lock", no_argument, 0, "serialize accept() usage (if possible)", uwsgi_opt_true, &uwsgi.use_thunder_lock, 0},
|
||||
@@ -241,6 +241,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"vassals-include-before", required_argument, 0, "include config templates to vassals config (uses --include instead of --inherit, parses before the vassal file)", uwsgi_opt_add_string_list, &uwsgi.vassals_includes_before, 0},
|
||||
{"vassals-start-hook", required_argument, 0, "run the specified command before each vassal starts", uwsgi_opt_set_str, &uwsgi.vassals_start_hook, 0},
|
||||
{"vassals-stop-hook", required_argument, 0, "run the specified command after vassal's death", uwsgi_opt_set_str, &uwsgi.vassals_stop_hook, 0},
|
||||
{"vassal-sos", required_argument, 0, "ask emperor for reinforcement when overloaded", uwsgi_opt_set_int, &uwsgi.vassal_sos, 0},
|
||||
{"vassal-sos-backlog", required_argument, 0, "ask emperor for sos if backlog queue has more items than the value specified", uwsgi_opt_set_int, &uwsgi.vassal_sos_backlog, 0},
|
||||
{"vassals-set", required_argument, 0, "automatically set the specified option (via --set) for every vassal", uwsgi_opt_add_string_list, &uwsgi.vassals_set, 0},
|
||||
{"vassal-set", required_argument, 0, "automatically set the specified option (via --set) for every vassal", uwsgi_opt_add_string_list, &uwsgi.vassals_set, 0},
|
||||
@@ -392,6 +393,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"hook-as-user-atexit", required_argument, 0, "run the specified hook before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.hook_as_user_atexit, 0},
|
||||
{"hook-pre-app", required_argument, 0, "run the specified hook before app loading", uwsgi_opt_add_string_list, &uwsgi.hook_pre_app, 0},
|
||||
{"hook-post-app", required_argument, 0, "run the specified hook after app loading", uwsgi_opt_add_string_list, &uwsgi.hook_post_app, 0},
|
||||
{"hook-post-fork", required_argument, 0, "run the specified hook after each fork", uwsgi_opt_add_string_list, &uwsgi.hook_post_fork, 0},
|
||||
{"hook-accepting", required_argument, 0, "run the specified hook after each worker enter the accepting phase", uwsgi_opt_add_string_list, &uwsgi.hook_accepting, 0},
|
||||
{"hook-accepting1", required_argument, 0, "run the specified hook after the first worker enters the accepting phase", uwsgi_opt_add_string_list, &uwsgi.hook_accepting1, 0},
|
||||
{"hook-accepting-once", required_argument, 0, "run the specified hook after each worker enter the accepting phase (once per-instance)", uwsgi_opt_add_string_list, &uwsgi.hook_accepting_once, 0},
|
||||
@@ -459,6 +461,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"wait-iface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
|
||||
{"wait-iface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
|
||||
|
||||
{"wait-for-fs", required_argument, 0, "wait for the specified filesystem item to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_fs, 0},
|
||||
{"wait-for-file", required_argument, 0, "wait for the specified file to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_fs, 0},
|
||||
{"wait-for-dir", required_argument, 0, "wait for the specified directory to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_fs, 0},
|
||||
{"wait-for-mountpoint", required_argument, 0, "wait for the specified mountpoint to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_mountpoint, 0},
|
||||
{"wait-for-fs-timeout", required_argument, 0, "set the timeout for wait-for-fs/file/dir", uwsgi_opt_set_int, &uwsgi.wait_for_fs_timeout, 0},
|
||||
|
||||
{"call-asap", required_argument, 0, "call the specified function as soon as possible", uwsgi_opt_add_string_list, &uwsgi.call_asap, 0},
|
||||
{"call-pre-jail", required_argument, 0, "call the specified function before jailing", uwsgi_opt_add_string_list, &uwsgi.call_pre_jail, 0},
|
||||
{"call-post-jail", required_argument, 0, "call the specified function after jailing", uwsgi_opt_add_string_list, &uwsgi.call_post_jail, 0},
|
||||
@@ -624,6 +632,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"subscription-tolerance", required_argument, 0, "set tolerance for subscription servers", uwsgi_opt_set_int, &uwsgi.subscription_tolerance, 0},
|
||||
{"unsubscribe-on-graceful-reload", no_argument, 0, "force unsubscribe request even during graceful reload", uwsgi_opt_true, &uwsgi.unsubscribe_on_graceful_reload, 0},
|
||||
{"start-unsubscribed", no_argument, 0, "configure subscriptions but do not send them (useful with master fifo)", uwsgi_opt_true, &uwsgi.subscriptions_blocked, 0},
|
||||
|
||||
{"subscribe-with-modifier1", required_argument, 0, "force the specififed modifier1 when subscribing", uwsgi_opt_set_str, &uwsgi.subscribe_with_modifier1, UWSGI_OPT_MASTER},
|
||||
|
||||
{"snmp", optional_argument, 0, "enable the embedded snmp server", uwsgi_opt_snmp, NULL, 0},
|
||||
{"snmp-community", required_argument, 0, "set the snmp community string", uwsgi_opt_snmp_community, NULL, 0},
|
||||
#ifdef UWSGI_SSL
|
||||
@@ -636,6 +647,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"sni", required_argument, 0, "add an SNI-governed SSL context", uwsgi_opt_sni, NULL, 0},
|
||||
{"sni-dir", required_argument, 0, "check for cert/key/client_ca file in the specified directory and create a sni/ssl context on demand", uwsgi_opt_set_str, &uwsgi.sni_dir, 0},
|
||||
{"sni-dir-ciphers", required_argument, 0, "set ssl ciphers for sni-dir option", uwsgi_opt_set_str, &uwsgi.sni_dir_ciphers, 0},
|
||||
{"ssl-enable3", no_argument, 0, "enable SSLv3 (insecure)", uwsgi_opt_true, &uwsgi.sslv3, 0},
|
||||
{"ssl-option", no_argument, 0, "set a raw ssl option (numeric value)", uwsgi_opt_add_string_list, &uwsgi.ssl_options, 0},
|
||||
#ifdef UWSGI_PCRE
|
||||
{"sni-regexp", required_argument, 0, "add an SNI-governed SSL context (the key is a regexp)", uwsgi_opt_sni, NULL, 0},
|
||||
#endif
|
||||
@@ -849,6 +862,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"collect-header", required_argument, 0, "store the specified response header in a request var (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.collect_headers, 0},
|
||||
{"response-header-collect", required_argument, 0, "store the specified response header in a request var (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.collect_headers, 0},
|
||||
|
||||
{"pull-header", required_argument, 0, "store the specified response header in a request var and remove it from the response (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.pull_headers, 0},
|
||||
|
||||
{"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
|
||||
{"check-static-docroot", no_argument, 0, "check for static files in the requested DOCUMENT_ROOT", uwsgi_opt_true, &uwsgi.check_static_docroot, UWSGI_OPT_MIME},
|
||||
{"static-check", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
|
||||
@@ -1533,8 +1548,10 @@ static void vacuum(void) {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
if (uwsgi.restore_tc) {
|
||||
if (tcsetattr(0, TCSANOW, &uwsgi.termios)) {
|
||||
uwsgi_error("tcsetattr()");
|
||||
if (getpid() == masterpid) {
|
||||
if (tcsetattr(0, TCSANOW, &uwsgi.termios)) {
|
||||
uwsgi_error("vacuum()/tcsetattr()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1583,6 +1600,17 @@ static void vacuum(void) {
|
||||
next:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
if (uwsgi.stats) {
|
||||
// is a unix socket ?
|
||||
if (!strchr(uwsgi.stats, ':') && uwsgi.stats[0] != '@') {
|
||||
if (unlink(uwsgi.stats)) {
|
||||
uwsgi_error("unlink()");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("VACUUM: unix socket %s (stats) removed.\n", uwsgi.stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2521,6 +2549,7 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
|
||||
if (uwsgi.chdir) {
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.chdir);
|
||||
if (chdir(uwsgi.chdir)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
@@ -3269,6 +3298,8 @@ int uwsgi_run() {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_post_fork, "post-fork", 1);
|
||||
|
||||
if (uwsgi.worker_exec2) {
|
||||
char *w_argv[2];
|
||||
w_argv[0] = uwsgi.worker_exec2;
|
||||
@@ -3345,6 +3376,7 @@ void uwsgi_worker_run() {
|
||||
}
|
||||
|
||||
if (uwsgi.chdir2) {
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.chdir2);
|
||||
if (chdir(uwsgi.chdir2)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
@@ -3418,7 +3450,10 @@ void uwsgi_ignition() {
|
||||
if (uwsgi.has_emperor && uwsgi.mywid == 1) {
|
||||
char byte = 5;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("emperor-i-am-ready-to-accept/write()");
|
||||
uwsgi_log_verbose("lost communication with the Emperor, goodbye...\n");
|
||||
gracefully_kill_them_all(0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3786,7 +3821,8 @@ void uwsgi_opt_false(char *opt, char *value, void *key) {
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
|
||||
gid_t gid = atoi(value);
|
||||
gid_t gid = 0;
|
||||
if (is_a_number(value)) gid = atoi(value);
|
||||
if (gid == 0) {
|
||||
struct group *ugroup = getgrnam(value);
|
||||
if (ugroup)
|
||||
@@ -3815,7 +3851,8 @@ void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
|
||||
|
||||
|
||||
void uwsgi_opt_set_immediate_uid(char *opt, char *value, void *none) {
|
||||
uid_t uid = atoi(value);
|
||||
uid_t uid = 0;
|
||||
if (is_a_number(value)) uid = atoi(value);
|
||||
if (uid == 0) {
|
||||
struct passwd *upasswd = getpwnam(value);
|
||||
if (upasswd)
|
||||
@@ -3862,7 +3899,8 @@ void uwsgi_opt_set_int(char *opt, char *value, void *key) {
|
||||
}
|
||||
|
||||
void uwsgi_opt_uid(char *opt, char *value, void *key) {
|
||||
uid_t uid = atoi(value);
|
||||
uid_t uid = 0;
|
||||
if (is_a_number(value)) uid = atoi(value);
|
||||
if (!uid) {
|
||||
struct passwd *p = getpwnam(value);
|
||||
if (p) {
|
||||
@@ -3880,7 +3918,8 @@ void uwsgi_opt_uid(char *opt, char *value, void *key) {
|
||||
}
|
||||
|
||||
void uwsgi_opt_gid(char *opt, char *value, void *key) {
|
||||
gid_t gid = atoi(value);
|
||||
gid_t gid = 0;
|
||||
if (is_a_number(value)) gid = atoi(value);
|
||||
if (!gid) {
|
||||
struct group *g = getgrnam(value);
|
||||
if (g) {
|
||||
@@ -4181,15 +4220,13 @@ void uwsgi_opt_print(char *opt, char *value, void *str) {
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_uid(char *opt, char *value, void *none) {
|
||||
|
||||
uwsgi.uid = atoi(value);
|
||||
if (is_a_number(value)) uwsgi.uid = atoi(value);
|
||||
if (!uwsgi.uid)
|
||||
uwsgi.uidname = value;
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_gid(char *opt, char *value, void *none) {
|
||||
|
||||
uwsgi.gid = atoi(value);
|
||||
if (is_a_number(value)) uwsgi.gid = atoi(value);
|
||||
if (!uwsgi.gid)
|
||||
uwsgi.gidname = value;
|
||||
}
|
||||
|
||||
@@ -273,6 +273,7 @@ static struct uwsgi_buffer *uwsgi_websocket_recv_do(struct wsgi_request *wsgi_re
|
||||
}
|
||||
else {
|
||||
wsgi_req->websocket_need += wsgi_req->websocket_size;
|
||||
wsgi_req->websocket_pktsize += wsgi_req->websocket_size;
|
||||
wsgi_req->websocket_phase = 4;
|
||||
}
|
||||
break;
|
||||
|
||||
+10
-1
@@ -124,9 +124,18 @@ error:
|
||||
static int uwsgi_response_add_header_do(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
|
||||
|
||||
|
||||
// collect the header ?
|
||||
// pull/collect the header ?
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.pull_headers) {
|
||||
if (!uwsgi_strnicmp(key, key_len, usl->value, usl->custom)) {
|
||||
if (!uwsgi_req_append(wsgi_req, usl->custom_ptr, usl->custom2, value, value_len)) {
|
||||
wsgi_req->write_errors++ ; return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.collect_headers) {
|
||||
if (!uwsgi_strnicmp(key, key_len, usl->value, usl->custom)) {
|
||||
if (!uwsgi_req_append(wsgi_req, usl->custom_ptr, usl->custom2, value, value_len)) {
|
||||
|
||||
@@ -312,8 +312,6 @@ static void asyncio_loop() {
|
||||
uwsgi.wait_write_hook = uwsgi_asyncio_wait_write_hook;
|
||||
uwsgi.wait_read_hook = uwsgi_asyncio_wait_read_hook;
|
||||
|
||||
uwsgi.schedule_fix = uwsgi_asyncio_schedule_fix;
|
||||
|
||||
if (uwsgi.async < 2) {
|
||||
uwsgi_log("the asyncio loop engine requires async mode (--async <n>)\n");
|
||||
exit(1);
|
||||
@@ -323,9 +321,20 @@ static void asyncio_loop() {
|
||||
uwsgi_log("*** DANGER *** asyncio mode without coroutine/greenthread engine loaded !!!\n");
|
||||
}
|
||||
|
||||
if (!uwsgi.schedule_to_req) {
|
||||
uwsgi.schedule_to_req = async_schedule_to_req_green;
|
||||
}
|
||||
else {
|
||||
uwsgi.schedule_fix = uwsgi_asyncio_schedule_fix;
|
||||
}
|
||||
|
||||
#ifndef PYTHREE
|
||||
PyObject *asyncio = PyImport_ImportModule("trollius");
|
||||
#else
|
||||
PyObject *asyncio = PyImport_ImportModule("asyncio");
|
||||
#endif
|
||||
if (!asyncio) uwsgi_pyexit;
|
||||
|
||||
|
||||
uasyncio.mod = asyncio;
|
||||
|
||||
uasyncio.loop = PyObject_CallMethod(asyncio, "get_event_loop", NULL);
|
||||
|
||||
@@ -71,7 +71,9 @@ static void carbon_post_init() {
|
||||
u_server->errors = 0;
|
||||
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(usl->value, ":", p, ctx) {
|
||||
// make a copy to not clobber argv
|
||||
char *tmp = uwsgi_str(usl->value);
|
||||
uwsgi_foreach_token(tmp, ":", p, ctx) {
|
||||
if (!u_server->hostname) {
|
||||
u_server->hostname = uwsgi_str(p);
|
||||
}
|
||||
@@ -81,6 +83,7 @@ static void carbon_post_init() {
|
||||
else
|
||||
break;
|
||||
}
|
||||
free(tmp);
|
||||
if (!u_server->hostname || !u_server->port) {
|
||||
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
|
||||
usl = usl->next;
|
||||
@@ -196,7 +199,7 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
|
||||
u_carbon.last_busyness_values[i] = uwsgi.workers[i+1].running_time;
|
||||
u_carbon.was_busy[i-1] += uwsgi_worker_is_busy(i+1);
|
||||
u_carbon.was_busy[i] += uwsgi_worker_is_busy(i+1);
|
||||
}
|
||||
|
||||
needs_retry = 0;
|
||||
|
||||
@@ -75,6 +75,12 @@ void uwsgi_cr_peer_reset(struct corerouter_peer *peer) {
|
||||
peer->hook_write = NULL;
|
||||
}
|
||||
|
||||
if (peer->is_buffering) {
|
||||
if (peer->buffering_fd != -1) {
|
||||
close(peer->buffering_fd);
|
||||
}
|
||||
}
|
||||
|
||||
peer->failed = 0;
|
||||
peer->soopt = 0;
|
||||
peer->timed_out = 0;
|
||||
@@ -84,7 +90,13 @@ void uwsgi_cr_peer_reset(struct corerouter_peer *peer) {
|
||||
}
|
||||
|
||||
// destroy a peer
|
||||
void uwsgi_cr_peer_del(struct corerouter_peer *peer) {
|
||||
int uwsgi_cr_peer_del(struct corerouter_peer *peer) {
|
||||
// first of all check if we need to run a flush procedure
|
||||
if (peer->flush && !peer->is_flushing) {
|
||||
peer->is_flushing = 1;
|
||||
// on success, suspend the execution
|
||||
if (peer->flush(peer) >= 0) return -1;
|
||||
}
|
||||
struct corerouter_peer *prev = peer->prev;
|
||||
struct corerouter_peer *next = peer->next;
|
||||
|
||||
@@ -111,6 +123,7 @@ void uwsgi_cr_peer_del(struct corerouter_peer *peer) {
|
||||
uwsgi_buffer_destroy(peer->out);
|
||||
}
|
||||
free(peer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_opt_corerouter(char *opt, char *value, void *cr) {
|
||||
@@ -383,7 +396,7 @@ void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer
|
||||
}
|
||||
|
||||
end:
|
||||
uwsgi_cr_peer_del(peer);
|
||||
if (uwsgi_cr_peer_del(peer) < 0) return;
|
||||
|
||||
if (peer == cs->main_peer) {
|
||||
cs->main_peer = NULL;
|
||||
@@ -401,7 +414,7 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
|
||||
|
||||
struct corerouter_peer *main_peer = cr_session->main_peer;
|
||||
if (main_peer) {
|
||||
uwsgi_cr_peer_del(main_peer);
|
||||
if (uwsgi_cr_peer_del(main_peer) < 0) return;
|
||||
}
|
||||
|
||||
// free peers
|
||||
@@ -413,7 +426,7 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
|
||||
if (ucr->subscriptions && tmp_peer->un && tmp_peer->un->len) {
|
||||
tmp_peer->un->reference--;
|
||||
}
|
||||
uwsgi_cr_peer_del(tmp_peer);
|
||||
if (uwsgi_cr_peer_del(tmp_peer) < 0) return;
|
||||
}
|
||||
|
||||
// could be used to free additional resources
|
||||
|
||||
@@ -180,8 +180,8 @@ struct corerouter_peer {
|
||||
uint16_t retries;
|
||||
|
||||
// parsed key
|
||||
char *key;
|
||||
uint16_t key_len;
|
||||
char key[0xff];
|
||||
uint8_t key_len;
|
||||
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
@@ -190,6 +190,12 @@ struct corerouter_peer {
|
||||
struct corerouter_peer *next;
|
||||
|
||||
int current_timeout;
|
||||
|
||||
ssize_t (*flush)(struct corerouter_peer *);
|
||||
|
||||
int is_flushing;
|
||||
int is_buffering;
|
||||
int buffering_fd;
|
||||
};
|
||||
|
||||
struct uwsgi_corerouter {
|
||||
|
||||
@@ -53,6 +53,7 @@ int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *ucr, struct coreroute
|
||||
peer->instance_address = peer->un->name;
|
||||
peer->instance_address_len = peer->un->len;
|
||||
peer->modifier1 = peer->un->modifier1;
|
||||
peer->modifier2 = peer->un->modifier2;
|
||||
}
|
||||
else if (ucr->cheap && !ucr->i_am_cheap && uwsgi_no_subscriptions(ucr->subscriptions)) {
|
||||
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
|
||||
@@ -88,6 +89,7 @@ split:
|
||||
peer->instance_address = peer->un->name;
|
||||
peer->instance_address_len = peer->un->len;
|
||||
peer->modifier1 = peer->un->modifier1;
|
||||
peer->modifier2 = peer->un->modifier2;
|
||||
}
|
||||
else if (ucr->cheap && !ucr->i_am_cheap && uwsgi_no_subscriptions(ucr->subscriptions)) {
|
||||
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
|
||||
|
||||
+17
-26
@@ -2,13 +2,6 @@
|
||||
|
||||
#define AMQP_CONNECTION_HEADER "AMQP\0\0\x09\x01"
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#define ntohll(x) x
|
||||
#else
|
||||
#define ntohll(x) ( ( (uint64_t)(ntohl( (uint32_t)((x << 32) >> 32) )) << 32) | ntohl( ((uint32_t)(x >> 32)) ) )
|
||||
#endif
|
||||
#define htonll(x) ntohll(x)
|
||||
|
||||
#define amqp_send(a, b, c) if (send(a, b, c, 0) < 0) { uwsgi_error("send()"); return -1; }
|
||||
|
||||
struct amqp_frame_header {
|
||||
@@ -69,13 +62,8 @@ static char *amqp_get_long(char *ptr, char *watermark, uint32_t *lv) {
|
||||
|
||||
static char *amqp_get_longlong(char *ptr, char *watermark, uint64_t *llv) {
|
||||
|
||||
uint64_t tmp_longlong;
|
||||
|
||||
if (ptr+8 > watermark) return NULL;
|
||||
|
||||
memcpy(&tmp_longlong, ptr, 8);
|
||||
|
||||
*llv = ntohll(tmp_longlong);
|
||||
*llv = uwsgi_be64(ptr);
|
||||
return ptr+8;
|
||||
}
|
||||
|
||||
@@ -85,26 +73,29 @@ static int amqp_send_ack(int fd, uint64_t delivery_tag) {
|
||||
|
||||
uint32_t size = 4 + 8 + 1;
|
||||
|
||||
size = htonl(size);
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(64);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
if (uwsgi_buffer_append(ub, "\1\0\1", 3)) goto end;
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 60 method 80
|
||||
amqp_send(fd, "\x00\x3C\x00\x50", 4);
|
||||
|
||||
if (uwsgi_buffer_u32be(ub, size)) goto end;
|
||||
// send class 60 method 80
|
||||
if (uwsgi_buffer_append(ub, "\x00\x3C\x00\x50", 4)) goto end;
|
||||
// set delivery_tag
|
||||
delivery_tag = htonll(delivery_tag);
|
||||
amqp_send(fd, &delivery_tag, 8);
|
||||
if (uwsgi_buffer_u64be(ub, delivery_tag)) goto end;
|
||||
if (uwsgi_buffer_append(ub, "\0\xCE", 2)) goto end;
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
// send buffer to socket
|
||||
if (write(fd, ub->buf, ub->pos) < 0) {
|
||||
uwsgi_error("amqp_send_ack()/write()");
|
||||
goto end;
|
||||
}
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
NAME='emperor_zeromq'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
LIBS = ['-lzmq']
|
||||
|
||||
GCC_LIST = ['emperor_zeromq']
|
||||
|
||||
+118
-15
@@ -16,6 +16,8 @@ extern struct uwsgi_server uwsgi;
|
||||
struct fastrouter_session {
|
||||
struct corerouter_session session;
|
||||
int has_key;
|
||||
uint64_t content_length;
|
||||
uint64_t buffered;
|
||||
};
|
||||
|
||||
static struct uwsgi_option fastrouter_options[] = {
|
||||
@@ -42,7 +44,7 @@ static struct uwsgi_option fastrouter_options[] = {
|
||||
|
||||
{"fastrouter-timeout", required_argument, 0, "set fastrouter timeout", uwsgi_opt_set_int, &ufr.cr.socket_timeout, 0},
|
||||
{"fastrouter-post-buffering", required_argument, 0, "enable fastrouter post buffering", uwsgi_opt_set_64bit, &ufr.cr.post_buffering, 0},
|
||||
{"fastrouter-post-buffering-dir", required_argument, 0, "put fastrouter buffered files to the specified directory", uwsgi_opt_set_str, &ufr.cr.pb_base_dir, 0},
|
||||
{"fastrouter-post-buffering-dir", required_argument, 0, "put fastrouter buffered files to the specified directory (noop, use TMPDIR env)", uwsgi_opt_set_str, &ufr.cr.pb_base_dir, 0},
|
||||
|
||||
{"fastrouter-stats", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
{"fastrouter-stats-server", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
@@ -66,21 +68,27 @@ static void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vall
|
||||
|
||||
//uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
|
||||
if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !peer->key_len) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
if (vallen <= 0xff) {
|
||||
memcpy(peer->key, val, vallen);
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !fr->has_key) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
if (vallen <= 0xff) {
|
||||
memcpy(peer->key, val, vallen);
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) {
|
||||
fr->has_key = 1;
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
if (vallen <= 0xff) {
|
||||
fr->has_key = 1;
|
||||
memcpy(peer->key, val, vallen);
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -97,6 +105,12 @@ static void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vall
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ufr.cr.post_buffering > 0) {
|
||||
if (!uwsgi_strncmp("CONTENT_LENGTH", 14, key, keylen)) {
|
||||
fr->content_length = uwsgi_str_num(val, vallen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// writing client body to the instance
|
||||
@@ -157,6 +171,23 @@ static ssize_t fr_instance_read(struct corerouter_peer *peer) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t fr_instance_sendfile(struct corerouter_peer *peer) {
|
||||
struct fastrouter_session *fr = (struct fastrouter_session *) peer->session;
|
||||
ssize_t len = uwsgi_sendfile_do(peer->fd, peer->session->main_peer->buffering_fd, fr->buffered, fr->content_length - fr->buffered);
|
||||
if (len < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_cr_error(peer, "fr_instance_sendfile()/sendfile()");
|
||||
return -1;
|
||||
}
|
||||
if (len == 0) return 0;
|
||||
fr->buffered += len;
|
||||
if (peer != peer->session->main_peer && peer->un) peer->un->rx+=len;
|
||||
if (fr->buffered >= fr->content_length) {
|
||||
cr_reset_hooks(peer);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
// send the uwsgi request header and vars
|
||||
static ssize_t fr_instance_send_request(struct corerouter_peer *peer) {
|
||||
ssize_t len = cr_write(peer, "fr_instance_send_request()");
|
||||
@@ -167,9 +198,16 @@ static ssize_t fr_instance_send_request(struct corerouter_peer *peer) {
|
||||
if (cr_write_complete(peer)) {
|
||||
// reset the original read buffer
|
||||
peer->out->pos = 0;
|
||||
// start waiting for body
|
||||
peer->session->main_peer->last_hook_read = fr_read_body;
|
||||
cr_reset_hooks(peer);
|
||||
if (!peer->session->main_peer->is_buffering) {
|
||||
// start waiting for body
|
||||
peer->session->main_peer->last_hook_read = fr_read_body;
|
||||
cr_reset_hooks(peer);
|
||||
}
|
||||
else {
|
||||
peer->hook_write = fr_instance_sendfile;
|
||||
// stop reading from the client
|
||||
peer->session->main_peer->last_hook_read = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
@@ -184,8 +222,8 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
|
||||
peer->can_retry = 0;
|
||||
|
||||
// fix modifiers
|
||||
peer->in->buf[0] = peer->session->main_peer->modifier1;
|
||||
peer->in->buf[3] = peer->session->main_peer->modifier2;
|
||||
peer->in->buf[0] = peer->modifier1;
|
||||
peer->in->buf[3] = peer->modifier2;
|
||||
|
||||
// prepare to write the uwsgi packet
|
||||
peer->out = peer->session->main_peer->in;
|
||||
@@ -197,20 +235,73 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
|
||||
|
||||
// called after receaving the uwsgi header (read vars)
|
||||
static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
|
||||
struct fastrouter_session *fr = (struct fastrouter_session *) main_peer->session;
|
||||
|
||||
struct corerouter_peer *new_peer = NULL;
|
||||
ssize_t len = 0;
|
||||
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) main_peer->in->buf;
|
||||
// better to store it as the original buf address could change
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
|
||||
// are we buffering ?
|
||||
if (main_peer->is_buffering) {
|
||||
// memory or disk ?
|
||||
if (fr->content_length <= ufr.cr.post_buffering) {
|
||||
// increase buffer if needed
|
||||
if (uwsgi_buffer_fix(main_peer->in, pktsize+4+fr->content_length))
|
||||
return -1;
|
||||
len = cr_read_exact(main_peer, pktsize+4+fr->content_length, "fr_recv_uwsgi_vars()");
|
||||
if (!len) return 0;
|
||||
// whole body read ?
|
||||
if (main_peer->in->pos == (size_t)(pktsize+4+fr->content_length)) {
|
||||
main_peer->is_buffering = 0;
|
||||
goto done;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
// first round ?
|
||||
if (main_peer->buffering_fd == -1) {
|
||||
main_peer->buffering_fd = uwsgi_tmpfd();
|
||||
if (main_peer->buffering_fd < 0) return -1;
|
||||
}
|
||||
char buf[32768];
|
||||
size_t remains = fr->content_length - fr->buffered;
|
||||
ssize_t rlen = read(main_peer->fd, buf, UMIN(32768, remains));
|
||||
if (rlen < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_cr_error(main_peer, "fr_recv_uwsgi_vars()/read()");
|
||||
return -1;
|
||||
}
|
||||
if (rlen == 0) return 0;
|
||||
fr->buffered += rlen;
|
||||
if (write(main_peer->buffering_fd, buf, rlen) != rlen) {
|
||||
uwsgi_cr_error(main_peer, "fr_recv_uwsgi_vars()/write()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// have we done ?
|
||||
if (fr->buffered >= fr->content_length) {
|
||||
fr->buffered = 0;
|
||||
len = rlen;
|
||||
goto done;
|
||||
}
|
||||
|
||||
return rlen;
|
||||
}
|
||||
|
||||
// increase buffer if needed
|
||||
if (uwsgi_buffer_fix(main_peer->in, pktsize+4))
|
||||
return -1;
|
||||
ssize_t len = cr_read_exact(main_peer, pktsize+4, "fr_recv_uwsgi_vars()");
|
||||
len = cr_read_exact(main_peer, pktsize+4, "fr_recv_uwsgi_vars()");
|
||||
if (!len) return 0;
|
||||
|
||||
// headers received, ready to choose the instance
|
||||
if (main_peer->in->pos == (size_t)(pktsize+4)) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = main_peer->session->corerouter;
|
||||
|
||||
struct corerouter_peer *new_peer = uwsgi_cr_peer_add(main_peer->session);
|
||||
new_peer = uwsgi_cr_peer_add(main_peer->session);
|
||||
new_peer->last_hook_read = fr_instance_read;
|
||||
|
||||
// find the hostname
|
||||
@@ -237,6 +328,18 @@ static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// buffering ?
|
||||
if (ufr.cr.post_buffering > 0 && fr->content_length > 0) {
|
||||
main_peer->is_buffering = 1;
|
||||
main_peer->buffering_fd = -1;
|
||||
return len;
|
||||
}
|
||||
|
||||
done:
|
||||
if (!new_peer) {
|
||||
new_peer = main_peer->session->peers;
|
||||
}
|
||||
|
||||
new_peer->can_retry = 1;
|
||||
|
||||
cr_connect(new_peer, fr_instance_connected);
|
||||
|
||||
@@ -100,6 +100,31 @@ retry:
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_gevent_int(PyObject *self, PyObject *args) {
|
||||
|
||||
uwsgi_log("Brutally killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
|
||||
|
||||
uwsgi_log_verbose("stopping gevent signals watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
PyObject_CallMethod(ugevent.my_signal_watcher, "stop", NULL);
|
||||
PyObject_CallMethod(ugevent.signal_watcher, "stop", NULL);
|
||||
|
||||
uwsgi_log_verbose("stopping gevent sockets watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
int i,count = uwsgi_count_sockets(uwsgi.sockets);
|
||||
for(i=0;i<count;i++) {
|
||||
PyObject_CallMethod(ugevent.watchers[i], "stop", NULL);
|
||||
}
|
||||
uwsgi_log_verbose("main gevent watchers stopped for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
|
||||
if (!ugevent.wait_for_hub) {
|
||||
PyObject_CallMethod(ugevent.ctrl_gl, "kill", NULL);
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_gevent_gbcw() {
|
||||
|
||||
// already running
|
||||
@@ -333,6 +358,7 @@ PyMethodDef uwsgi_gevent_signal_def[] = { {"uwsgi_gevent_signal", py_uwsgi_geven
|
||||
PyMethodDef uwsgi_gevent_my_signal_def[] = { {"uwsgi_gevent_my_signal", py_uwsgi_gevent_my_signal, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler", py_uwsgi_gevent_signal_handler, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_unix_signal_handler_def[] = { {"uwsgi_gevent_unix_signal_handler", py_uwsgi_gevent_graceful, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_unix_signal_int_handler_def[] = { {"uwsgi_gevent_unix_signal_int_handler", py_uwsgi_gevent_int, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_ctrl_gl_def[] = { {"uwsgi_gevent_ctrl_gl_handler", py_uwsgi_gevent_ctrl_gl, METH_VARARGS, ""} };
|
||||
|
||||
static void gil_gevent_get() {
|
||||
@@ -488,6 +514,22 @@ static void gevent_loop() {
|
||||
|
||||
python_call(ugevent.signal, ge_signal_tuple, 0, NULL);
|
||||
|
||||
// map SIGINT/SIGTERM with gevent.signal
|
||||
ge_signal_tuple = PyTuple_New(2);
|
||||
PyTuple_SetItem(ge_signal_tuple, 0, PyInt_FromLong(SIGINT));
|
||||
PyObject *uwsgi_gevent_unix_signal_int_handler = PyCFunction_New(uwsgi_gevent_unix_signal_int_handler_def, NULL);
|
||||
Py_INCREF(uwsgi_gevent_unix_signal_int_handler);
|
||||
PyTuple_SetItem(ge_signal_tuple, 1, uwsgi_gevent_unix_signal_int_handler);
|
||||
python_call(ugevent.signal, ge_signal_tuple, 0, NULL);
|
||||
|
||||
ge_signal_tuple = PyTuple_New(2);
|
||||
PyTuple_SetItem(ge_signal_tuple, 0, PyInt_FromLong(SIGTERM));
|
||||
PyTuple_SetItem(ge_signal_tuple, 1, uwsgi_gevent_unix_signal_int_handler);
|
||||
python_call(ugevent.signal, ge_signal_tuple, 0, NULL);
|
||||
|
||||
|
||||
|
||||
|
||||
PyObject *wait_for_me = ugevent.hub;
|
||||
|
||||
if (!ugevent.wait_for_hub) {
|
||||
|
||||
@@ -46,6 +46,8 @@ struct uwsgi_http {
|
||||
int connect_timeout;
|
||||
int manage_source;
|
||||
int enable_proxy_protocol;
|
||||
int chunked_input;
|
||||
int manage_rtsp;
|
||||
};
|
||||
|
||||
struct http_session {
|
||||
@@ -134,6 +136,8 @@ struct http_session {
|
||||
|
||||
ssize_t (*func_write)(struct corerouter_peer *);
|
||||
|
||||
int is_rtsp;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
+52
-11
@@ -42,6 +42,8 @@ struct uwsgi_option http_options[] = {
|
||||
{"http-raw-body", no_argument, 0, "blindly send HTTP body to backends (required for WebSockets and Icecast support in backends)", uwsgi_opt_true, &uhttp.raw_body, 0},
|
||||
{"http-websockets", no_argument, 0, "automatically detect websockets connections and put the session in raw mode", uwsgi_opt_true, &uhttp.websockets, 0},
|
||||
|
||||
{"http-chunked-input", no_argument, 0, "automatically detect chunked input requests and put the session in raw mode", uwsgi_opt_true, &uhttp.chunked_input, 0},
|
||||
|
||||
{"http-use-code-string", required_argument, 0, "use code string as hostname->server mapper for the http router", uwsgi_opt_corerouter_cs, &uhttp, 0},
|
||||
{"http-use-socket", optional_argument, 0, "forward request to the specified uwsgi socket", uwsgi_opt_corerouter_use_socket, &uhttp, 0},
|
||||
{"http-gracetime", required_argument, 0, "retry connections to dead static nodes after the specified amount of seconds", uwsgi_opt_set_int, &uhttp.cr.static_node_gracetime, 0},
|
||||
@@ -64,6 +66,7 @@ struct uwsgi_option http_options[] = {
|
||||
{"http-connect-timeout", required_argument, 0, "set internal http socket timeout for backend connections", uwsgi_opt_set_int, &uhttp.connect_timeout, 0},
|
||||
|
||||
{"http-manage-source", no_argument, 0, "manage the SOURCE HTTP method placing the session in raw mode", uwsgi_opt_true, &uhttp.manage_source, 0},
|
||||
{"http-manage-rtsp", no_argument, 0, "manage RTSP sessions", uwsgi_opt_true, &uhttp.manage_rtsp, 0},
|
||||
{"http-enable-proxy-protocol", optional_argument, 0, "manage PROXY protocol requests", uwsgi_opt_true, &uhttp.enable_proxy_protocol, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
@@ -138,9 +141,14 @@ static int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, size_t
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("HOST", 4, hh, keylen)) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
if (uhttp.server_name_as_http_host && uwsgi_buffer_append_keyval(out, "SERVER_NAME", 11, peer->key, peer->key_len)) return -1;
|
||||
if (vallen <= 0xff) {
|
||||
memcpy(peer->key, val, vallen);
|
||||
peer->key_len = vallen;
|
||||
if (uhttp.server_name_as_http_host && uwsgi_buffer_append_keyval(out, "SERVER_NAME", 11, peer->key, peer->key_len)) return -1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
|
||||
@@ -150,6 +158,11 @@ static int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, size_t
|
||||
// in the future we could support chunked requests...
|
||||
else if (!uwsgi_strncmp("TRANSFER_ENCODING", 17, hh, keylen)) {
|
||||
hr->session.can_keepalive = 0;
|
||||
if (uhttp.chunked_input) {
|
||||
if (!uwsgi_strnicmp(val, vallen, "chunked", 7)) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp("CONNECTION", 10, hh, keylen)) {
|
||||
@@ -158,8 +171,10 @@ static int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, size_t
|
||||
}
|
||||
}
|
||||
else if (peer->key == uwsgi.hostname && hr->raw_body && !uwsgi_strncmp("ICE_URL", 7, hh, keylen)) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
if (vallen <= 0xff) {
|
||||
memcpy(peer->key, val, vallen);
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZLIB
|
||||
@@ -316,6 +331,10 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
if (uhttp.keepalive && !uwsgi_strncmp("HTTP/1.1", 8, base, ptr-base)) {
|
||||
hr->session.can_keepalive = 1;
|
||||
}
|
||||
if (uhttp.manage_rtsp && !uwsgi_strncmp("RTSP/1.0", 8, base, ptr-base)) {
|
||||
hr->raw_body = 1;
|
||||
hr->is_rtsp = 1;
|
||||
}
|
||||
ptr += 2;
|
||||
found = 1;
|
||||
break;
|
||||
@@ -333,7 +352,7 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
|
||||
// SERVER_NAME
|
||||
if (!uhttp.server_name_as_http_host && uwsgi_buffer_append_keyval(out, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len)) return -1;
|
||||
peer->key = uwsgi.hostname;
|
||||
memcpy(peer->key, uwsgi.hostname, uwsgi.hostname_len);
|
||||
peer->key_len = uwsgi.hostname_len;
|
||||
|
||||
// SERVER_PORT
|
||||
@@ -445,6 +464,19 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
hv = hv->next;
|
||||
}
|
||||
|
||||
if (hr->is_rtsp) {
|
||||
if (uwsgi_starts_with("rtsp://", 7, hr->path_info, hr->path_info_len)) {
|
||||
char *slash = memchr(hr->path_info + 7, '/', hr->path_info_len - 7);
|
||||
if (!slash) return -1;
|
||||
if (slash - (hr->path_info + 7) <= 0xff) {
|
||||
peer->key_len = slash - (hr->path_info + 7);
|
||||
memcpy(peer->key, hr->path_info + 7, peer->key_len);
|
||||
// override PATH_INFO
|
||||
if (uwsgi_buffer_append_keyval(out, "PATH_INFO", 9, slash, hr->path_info_len - (7 + peer->key_len))) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
clear:
|
||||
@@ -808,10 +840,16 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
if (new_peer->instance_address_len == 0)
|
||||
return -1;
|
||||
|
||||
// fix modifiers
|
||||
if (uhttp.modifier1)
|
||||
new_peer->modifier1 = uhttp.modifier1;
|
||||
if (uhttp.modifier2)
|
||||
new_peer->modifier2 = uhttp.modifier2;
|
||||
|
||||
uint16_t pktsize = new_peer->out->pos-4;
|
||||
// fix modifiers
|
||||
new_peer->out->buf[0] = new_peer->session->main_peer->modifier1;
|
||||
new_peer->out->buf[3] = new_peer->session->main_peer->modifier2;
|
||||
new_peer->out->buf[0] = new_peer->modifier1;
|
||||
new_peer->out->buf[3] = new_peer->modifier2;
|
||||
// fix pktsize
|
||||
new_peer->out->buf[1] = (uint8_t) (pktsize & 0xff);
|
||||
new_peer->out->buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
|
||||
@@ -829,6 +867,12 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
if (uwsgi_buffer_append(new_peer->out, main_peer->in->buf + hr->headers_size + 1, hr->remains)) return -1;
|
||||
}
|
||||
|
||||
if (new_peer->modifier1 == 123) {
|
||||
// reset modifier1 to 0
|
||||
new_peer->out->buf[0] = 0;
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
|
||||
if (hr->websockets > 2 && hr->websocket_key_len > 0) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
@@ -953,9 +997,6 @@ int http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket
|
||||
// set the retry hook
|
||||
cs->retry = hr_retry;
|
||||
struct http_session *hr = (struct http_session *) cs;
|
||||
// set the modifier1
|
||||
cs->main_peer->modifier1 = uhttp.modifier1;
|
||||
cs->main_peer->modifier2 = uhttp.modifier2;
|
||||
// default hook
|
||||
cs->main_peer->last_hook_read = hr_read;
|
||||
|
||||
|
||||
+63
-6
@@ -10,6 +10,14 @@
|
||||
|
||||
extern struct uwsgi_http uhttp;
|
||||
|
||||
// taken from nginx
|
||||
static void hr_ssl_clear_errors() {
|
||||
while (ERR_peek_error()) {
|
||||
(void) ERR_get_error();
|
||||
}
|
||||
ERR_clear_error();
|
||||
}
|
||||
|
||||
void uwsgi_opt_https(char *opt, char *value, void *cr) {
|
||||
struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr;
|
||||
char *client_ca = NULL;
|
||||
@@ -172,9 +180,9 @@ int hr_https_add_vars(struct http_session *hr, struct corerouter_peer *peer, str
|
||||
if (uwsgi_buffer_append_keyval(out, "HTTPS", 5, "on", 2)) return -1;
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
const char *servername = SSL_get_servername(hr->ssl, TLSEXT_NAMETYPE_host_name);
|
||||
if (servername) {
|
||||
peer->key = (char *) servername;
|
||||
peer->key_len = strlen(servername);
|
||||
if (servername && strlen(servername) <= 0xff) {
|
||||
peer->key_len = strlen(servername);
|
||||
memcpy(peer->key, servername, peer->key_len) ;
|
||||
}
|
||||
#endif
|
||||
hr->ssl_client_cert = SSL_get_peer_certificate(hr->ssl);
|
||||
@@ -234,7 +242,7 @@ void hr_session_ssl_close(struct corerouter_session *cs) {
|
||||
#endif
|
||||
|
||||
// clear the errors (otherwise they could be propagated)
|
||||
ERR_clear_error();
|
||||
hr_ssl_clear_errors();
|
||||
SSL_free(hr->ssl);
|
||||
}
|
||||
|
||||
@@ -270,6 +278,8 @@ ssize_t hr_ssl_write(struct corerouter_peer *main_peer) {
|
||||
struct corerouter_session *cs = main_peer->session;
|
||||
struct http_session *hr = (struct http_session *) cs;
|
||||
|
||||
hr_ssl_clear_errors();
|
||||
|
||||
int ret = SSL_write(hr->ssl, main_peer->out->buf + main_peer->out_pos, main_peer->out->pos - main_peer->out_pos);
|
||||
if (ret > 0) {
|
||||
main_peer->out_pos += ret;
|
||||
@@ -294,9 +304,11 @@ ssize_t hr_ssl_write(struct corerouter_peer *main_peer) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (ret == 0) return 0;
|
||||
|
||||
int err = SSL_get_error(hr->ssl, ret);
|
||||
|
||||
if (err == SSL_ERROR_ZERO_RETURN || err == 0) return 0;
|
||||
|
||||
if (err == SSL_ERROR_WANT_READ) {
|
||||
cr_reset_hooks_and_read(main_peer, hr_ssl_write);
|
||||
return 1;
|
||||
@@ -322,6 +334,8 @@ ssize_t hr_ssl_read(struct corerouter_peer *main_peer) {
|
||||
struct corerouter_session *cs = main_peer->session;
|
||||
struct http_session *hr = (struct http_session *) cs;
|
||||
|
||||
hr_ssl_clear_errors();
|
||||
|
||||
// try to always leave 4k available
|
||||
if (uwsgi_buffer_ensure(main_peer->in, uwsgi.page_size)) return -1;
|
||||
int ret = SSL_read(hr->ssl, main_peer->in->buf + main_peer->in->pos, main_peer->in->len - main_peer->in->pos);
|
||||
@@ -350,9 +364,11 @@ ssize_t hr_ssl_read(struct corerouter_peer *main_peer) {
|
||||
#endif
|
||||
return http_parse(main_peer);
|
||||
}
|
||||
if (ret == 0) return 0;
|
||||
|
||||
int err = SSL_get_error(hr->ssl, ret);
|
||||
|
||||
if (err == SSL_ERROR_ZERO_RETURN || err == 0) return 0;
|
||||
|
||||
if (err == SSL_ERROR_WANT_READ) {
|
||||
cr_reset_hooks_and_read(main_peer, hr_ssl_read);
|
||||
return 1;
|
||||
@@ -374,6 +390,46 @@ ssize_t hr_ssl_read(struct corerouter_peer *main_peer) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t hr_ssl_shutdown(struct corerouter_peer *peer) {
|
||||
// ensure no hooks are set
|
||||
if (uwsgi_cr_set_hooks(peer, NULL, NULL)) return -1;
|
||||
|
||||
struct corerouter_session *cs = peer->session;
|
||||
struct http_session *hr = (struct http_session *) cs;
|
||||
|
||||
hr_ssl_clear_errors();
|
||||
|
||||
int ret = SSL_shutdown(hr->ssl);
|
||||
int err = 0;
|
||||
|
||||
if (ret != 1 && ERR_peek_error()) {
|
||||
err = SSL_get_error(hr->ssl, ret);
|
||||
}
|
||||
|
||||
// no error, close the connection
|
||||
if (ret == 1 || err == 0 || err == SSL_ERROR_ZERO_RETURN) return 0;
|
||||
|
||||
if (err == SSL_ERROR_WANT_READ) {
|
||||
if (uwsgi_cr_set_hooks(peer, hr_ssl_shutdown, NULL)) return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
else if (err == SSL_ERROR_WANT_WRITE) {
|
||||
if (uwsgi_cr_set_hooks(peer, NULL, hr_ssl_shutdown)) return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
else if (err == SSL_ERROR_SYSCALL) {
|
||||
uwsgi_cr_error(peer, "hr_ssl_shutdown()");
|
||||
}
|
||||
|
||||
else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void hr_setup_ssl(struct http_session *hr, struct uwsgi_gateway_socket *ugs) {
|
||||
hr->ssl = SSL_new(ugs->ctx);
|
||||
SSL_set_fd(hr->ssl, hr->session.main_peer->fd);
|
||||
@@ -382,6 +438,7 @@ void hr_setup_ssl(struct http_session *hr, struct uwsgi_gateway_socket *ugs) {
|
||||
SSL_set_ex_data(hr->ssl, uhttp.spdy_index, hr);
|
||||
#endif
|
||||
uwsgi_cr_set_hooks(hr->session.main_peer, hr_ssl_read, NULL);
|
||||
hr->session.main_peer->flush = hr_ssl_shutdown;
|
||||
hr->session.close = hr_session_ssl_close;
|
||||
hr->func_write = hr_ssl_write;
|
||||
}
|
||||
|
||||
@@ -556,8 +556,10 @@ static ssize_t spdy_inflate_http_headers(struct http_session *hr) {
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp(cgi_name, nk_len, "HTTP_HOST", 9)) {
|
||||
new_peer->key = new_peer->out->buf + (new_peer->out->pos - v_len);
|
||||
new_peer->key_len = v_len;
|
||||
if (v_len <= 0xff) {
|
||||
memcpy(new_peer->key, new_peer->out->buf + (new_peer->out->pos - v_len), v_len);
|
||||
new_peer->key_len = v_len;
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_strncmp(cgi_name, nk_len, "REQUEST_URI", 11)) {
|
||||
char *path_info = new_peer->out->buf + (new_peer->out->pos - v_len);
|
||||
|
||||
@@ -1,10 +1,49 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
struct logfile_data {
|
||||
char *logfile;
|
||||
char *backupname;
|
||||
uint64_t maxsize;
|
||||
};
|
||||
|
||||
static ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
if (!ul->configured) {
|
||||
if (ul->arg) {
|
||||
ul->fd = open(ul->arg, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
int is_keyval = 0;
|
||||
char *backupname = NULL;
|
||||
char *maxsize = NULL;
|
||||
char *logfile = NULL;
|
||||
|
||||
if (strchr(ul->arg, '=')) {
|
||||
if (uwsgi_kvlist_parse(ul->arg, strlen(ul->arg), ',', '=',
|
||||
"logfile", &logfile, "backupname", &backupname, "maxsize", &maxsize, NULL)) {
|
||||
uwsgi_log("[uwsgi-logfile] invalid keyval syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
is_keyval = 1;
|
||||
}
|
||||
if (is_keyval) {
|
||||
if (!logfile) {
|
||||
uwsgi_log("[uwsgi-logfile] missing logfile key\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxsize) {
|
||||
struct logfile_data *data = uwsgi_malloc(sizeof(struct logfile_data));
|
||||
data->logfile = logfile;
|
||||
data->backupname = backupname;
|
||||
data->maxsize = (uint64_t)strtoull(maxsize, NULL, 10);
|
||||
ul->data = data;
|
||||
|
||||
free(maxsize);
|
||||
maxsize = NULL;
|
||||
}
|
||||
} else {
|
||||
logfile = ul->arg;
|
||||
}
|
||||
|
||||
ul->fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (ul->fd >= 0) {
|
||||
ul->configured = 1;
|
||||
}
|
||||
@@ -12,10 +51,21 @@ static ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t
|
||||
}
|
||||
|
||||
if (ul->fd >= 0) {
|
||||
return write(ul->fd, message, len);
|
||||
}
|
||||
return 0;
|
||||
ssize_t written = write(ul->fd, message, len);
|
||||
|
||||
if (ul->data) {
|
||||
struct logfile_data *data = ul->data;
|
||||
off_t logsize = lseek(ul->fd, 0, SEEK_CUR);
|
||||
|
||||
if (data->maxsize > 0 && (uint64_t) logsize > data->maxsize) {
|
||||
uwsgi_log_do_rotate(data->logfile, data->backupname, logsize, ul->fd);
|
||||
}
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_fd_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
@@ -543,7 +543,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
|
||||
// if it is -1, try to load a dynamic app
|
||||
if (wsgi_req->app_id == -1) {
|
||||
if (wsgi_req->app_id == -1 && key_len > 0) {
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_lock(&umono.lock_loader);
|
||||
}
|
||||
@@ -562,10 +562,15 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
uwsgi_500(wsgi_req);
|
||||
uwsgi_log("--- unable to find Mono/ASP.NET application ---\n");
|
||||
// nothing to clear/free
|
||||
return UWSGI_OK;
|
||||
if (!uwsgi.no_default_app && uwsgi.default_app > -1 && uwsgi_apps[uwsgi.default_app].modifier1 == mono_plugin.modifier1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
}
|
||||
else {
|
||||
uwsgi_500(wsgi_req);
|
||||
uwsgi_log("--- unable to find Mono/ASP.NET application ---\n");
|
||||
// nothing to clear/free
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_app *app = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
@@ -6,6 +6,9 @@ LDFLAGS = []
|
||||
LIBS = os.popen('pkg-config --libs mono-2').read().rstrip().split()
|
||||
GCC_LIST = ['mono_plugin']
|
||||
|
||||
if os.uname()[0] == 'Darwin':
|
||||
LIBS.append('-framework Foundation')
|
||||
|
||||
def post_build(config):
|
||||
if os.system("sn -k plugins/mono/uwsgi.key") != 0:
|
||||
os._exit(1)
|
||||
|
||||
@@ -121,7 +121,7 @@ int uwsgi_buffer_msgpack_int(struct uwsgi_buffer *ub, int64_t num) {
|
||||
if (num > 0 && num <= 127) {
|
||||
return uwsgi_buffer_byte(ub, (uint8_t) num);
|
||||
}
|
||||
else if (num < 0 && num >= 31) {
|
||||
else if (num < 0 && num >= -31) {
|
||||
return uwsgi_buffer_byte(ub, 224 | (int8_t) num);
|
||||
}
|
||||
else if (num <= 127 && num >= -127) {
|
||||
|
||||
+36
-14
@@ -77,7 +77,7 @@ static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC)
|
||||
return str_length;
|
||||
}
|
||||
|
||||
static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
|
||||
{
|
||||
sapi_header_struct *h;
|
||||
zend_llist_position pos;
|
||||
@@ -135,7 +135,7 @@ static int sapi_uwsgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
|
||||
}
|
||||
|
||||
|
||||
static char *sapi_uwsgi_read_cookies(void)
|
||||
static char *sapi_uwsgi_read_cookies(TSRMLS_D)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
@@ -254,8 +254,9 @@ PHP_FUNCTION(uwsgi_cache_exists) {
|
||||
char *key = NULL;
|
||||
int keylen = 0;
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -269,8 +270,9 @@ PHP_FUNCTION(uwsgi_cache_exists) {
|
||||
PHP_FUNCTION(uwsgi_cache_clear) {
|
||||
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -287,8 +289,9 @@ PHP_FUNCTION(uwsgi_cache_del) {
|
||||
char *key = NULL;
|
||||
int keylen = 0;
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -304,12 +307,13 @@ PHP_FUNCTION(uwsgi_cache_get) {
|
||||
char *key = NULL;
|
||||
int keylen = 0;
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
uint64_t valsize;
|
||||
|
||||
if (!uwsgi.caches)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -329,11 +333,12 @@ PHP_FUNCTION(uwsgi_cache_set) {
|
||||
int vallen;
|
||||
uint64_t expires = 0;
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
|
||||
if (!uwsgi.caches)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", &key, &keylen, &value, &vallen, &expires, &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", &key, &keylen, &value, &vallen, &expires, &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -351,11 +356,12 @@ PHP_FUNCTION(uwsgi_cache_update) {
|
||||
int vallen;
|
||||
uint64_t expires = 0;
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
|
||||
if (!uwsgi.caches)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", &key, &keylen, &value, &vallen, &expires, &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", &key, &keylen, &value, &vallen, &expires, &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -512,7 +518,7 @@ static int php_uwsgi_startup(sapi_module_struct *sapi_module)
|
||||
}
|
||||
}
|
||||
|
||||
static void sapi_uwsgi_log_message(char *message) {
|
||||
static void sapi_uwsgi_log_message(char *message TSRMLS_DC) {
|
||||
|
||||
uwsgi_log("%s\n", message);
|
||||
}
|
||||
@@ -553,6 +559,10 @@ int uwsgi_php_init(void) {
|
||||
struct uwsgi_string_list *pset = uphp.set;
|
||||
struct uwsgi_string_list *append_config = uphp.append_config;
|
||||
|
||||
#ifdef ZTS
|
||||
tsrm_startup(1, 1, 0, NULL);
|
||||
#endif
|
||||
|
||||
sapi_startup(&uwsgi_sapi_module);
|
||||
|
||||
// applying custom options
|
||||
@@ -653,9 +663,14 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
size_t real_filename_len = 0;
|
||||
struct stat php_stat;
|
||||
char *filename = NULL;
|
||||
int force_empty_script_name = 0;
|
||||
|
||||
zend_file_handle file_handle;
|
||||
|
||||
#ifdef ZTS
|
||||
TSRMLS_FETCH();
|
||||
#endif
|
||||
|
||||
SG(server_context) = (void *) wsgi_req;
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
@@ -721,6 +736,7 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
appready:
|
||||
wsgi_req->path_info = "";
|
||||
wsgi_req->path_info_len = 0;
|
||||
force_empty_script_name = 1;
|
||||
goto secure2;
|
||||
}
|
||||
|
||||
@@ -850,13 +866,19 @@ secure2:
|
||||
}
|
||||
|
||||
secure3:
|
||||
wsgi_req->script_name = orig_path_info;
|
||||
if (path_info) {
|
||||
wsgi_req->script_name_len = path_info - orig_path_info;
|
||||
if (force_empty_script_name) {
|
||||
wsgi_req->script_name = "";
|
||||
wsgi_req->script_name_len = 0;
|
||||
}
|
||||
else {
|
||||
wsgi_req->script_name_len = orig_path_info_len;
|
||||
}
|
||||
wsgi_req->script_name = orig_path_info;
|
||||
if (path_info) {
|
||||
wsgi_req->script_name_len = path_info - orig_path_info;
|
||||
}
|
||||
else {
|
||||
wsgi_req->script_name_len = orig_path_info_len;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("php filename = %s script_name = %.*s (%d) document_root = %.*s (%d)\n", real_filename, wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->script_name_len,
|
||||
|
||||
@@ -25,11 +25,12 @@ XS(XS_error) {
|
||||
psgi_check_args(0);
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[wsgi_req->async_id]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->error)[wsgi_req->async_id]);
|
||||
}
|
||||
else {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[0]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->error)[0]);
|
||||
}
|
||||
sv_2mortal(ST(0));
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
@@ -41,11 +42,12 @@ XS(XS_input) {
|
||||
psgi_check_args(0);
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[wsgi_req->async_id]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->input)[wsgi_req->async_id]);
|
||||
}
|
||||
else {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[0]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->input)[0]);
|
||||
}
|
||||
sv_2mortal(ST(0));
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
@@ -80,11 +82,12 @@ XS(XS_stream)
|
||||
|
||||
SvREFCNT_dec(response);
|
||||
if (uwsgi.threads > 1) {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[wsgi_req->async_id]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->stream)[wsgi_req->async_id]);
|
||||
}
|
||||
else {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[0]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->stream)[0]);
|
||||
}
|
||||
sv_2mortal(ST(0));
|
||||
XSRETURN(1);
|
||||
}
|
||||
else {
|
||||
@@ -271,6 +274,51 @@ nonworker:
|
||||
newCONSTSUB(stash, "SPOOL_RETRY", newSViv(-1));
|
||||
newCONSTSUB(stash, "SPOOL_IGNORE", newSViv(0));
|
||||
|
||||
HV *_opts = newHV();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
if (hv_exists(_opts, uwsgi.exported_opts[i]->key, strlen(uwsgi.exported_opts[i]->key))) {
|
||||
SV **value = hv_fetch(_opts, uwsgi.exported_opts[i]->key, strlen(uwsgi.exported_opts[i]->key), 0);
|
||||
// last resort !!!
|
||||
if (!value) {
|
||||
uwsgi_log("[perl] WARNING !!! unable to build uwsgi::opt hash !!!\n");
|
||||
goto end;
|
||||
}
|
||||
if (SvTYPE(SvRV(*value)) == SVt_PVAV) {
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
av_push((AV *)SvRV(*value), newSViv(1));
|
||||
}
|
||||
else {
|
||||
av_push((AV *)SvRV(*value), newSVpv(uwsgi.exported_opts[i]->value, 0));
|
||||
}
|
||||
}
|
||||
else {
|
||||
AV *_opt_a = newAV();
|
||||
av_push(_opt_a, SvREFCNT_inc(*value));
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
av_push(_opt_a, newSViv(1));
|
||||
}
|
||||
else {
|
||||
av_push(_opt_a, newSVpv(uwsgi.exported_opts[i]->value, 0));
|
||||
}
|
||||
hv_store(_opts, uwsgi.exported_opts[i]->key, strlen(uwsgi.exported_opts[i]->key), newRV_inc((SV *) _opt_a), 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
hv_store(_opts, uwsgi.exported_opts[i]->key, strlen(uwsgi.exported_opts[i]->key), newSViv(1), 0);
|
||||
}
|
||||
else {
|
||||
hv_store(_opts, uwsgi.exported_opts[i]->key, strlen(uwsgi.exported_opts[i]->key), newSVpv(uwsgi.exported_opts[i]->value, 0), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newCONSTSUB(stash, "opt", newRV_inc((SV *) _opts));
|
||||
|
||||
end:
|
||||
|
||||
init_perl_embedded_module();
|
||||
|
||||
}
|
||||
|
||||
+31
-10
@@ -114,7 +114,7 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
|
||||
|
||||
SPAGAIN;
|
||||
|
||||
newobj = POPs;
|
||||
newobj = SvREFCNT_inc(POPs);
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
@@ -661,15 +661,21 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
if (SvTRUE(*harakiri)) wsgi_req->async_plagued = 1;
|
||||
}
|
||||
|
||||
// Free the $env hash
|
||||
SvREFCNT_dec(wsgi_req->async_environ);
|
||||
|
||||
// async plagued could be defined in other areas...
|
||||
if (wsgi_req->async_plagued) {
|
||||
uwsgi_log("*** psgix.harakiri.commit requested ***\n");
|
||||
// Before we call exit(0) we'll run the
|
||||
// uwsgi_perl_atexit() hook which'll properly tear
|
||||
// down the interpreter.
|
||||
|
||||
// mark the request as ended (otherwise the atexit hook will be skipped)
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
|
||||
goodbye_cruel_world();
|
||||
}
|
||||
|
||||
// clear the env
|
||||
SvREFCNT_dec(wsgi_req->async_environ);
|
||||
|
||||
// now we can check for changed files
|
||||
if (uperl.auto_reload) {
|
||||
time_t now = uwsgi_now();
|
||||
@@ -803,24 +809,39 @@ void uwsgi_perl_run_hook(SV *hook) {
|
||||
}
|
||||
|
||||
static void uwsgi_perl_atexit() {
|
||||
int i;
|
||||
|
||||
if (uwsgi.mywid == 0) goto realstuff;
|
||||
|
||||
// if hijacked do not run atexit hooks
|
||||
// if hijacked do not run atexit hooks -- TODO: explain why
|
||||
// not.
|
||||
if (uwsgi.workers[uwsgi.mywid].hijacked)
|
||||
return;
|
||||
goto destroyperl;
|
||||
|
||||
// if busy do not run atexit hooks
|
||||
// if busy do not run atexit hooks (as this part could be called in a signal handler
|
||||
// while a subroutine is running)
|
||||
if (uwsgi_worker_is_busy(uwsgi.mywid))
|
||||
return;
|
||||
|
||||
// managing atexit in async mode is a real pain...skip it for now
|
||||
if (uwsgi.async > 1)
|
||||
return;
|
||||
realstuff:
|
||||
|
||||
if (uperl.atexit) {
|
||||
uwsgi_perl_run_hook(uperl.atexit);
|
||||
}
|
||||
|
||||
destroyperl:
|
||||
|
||||
// We must free our perl context(s) so any DESTROY hooks
|
||||
// etc. will run.
|
||||
for(i=0;i<uwsgi.threads;i++) {
|
||||
PERL_SET_CONTEXT(uperl.main[i]);
|
||||
|
||||
// Destroy the PerlInterpreter, see "perldoc perlembed"
|
||||
perl_destruct(uperl.main[i]);
|
||||
perl_free(uperl.main[i]);
|
||||
}
|
||||
PERL_SYS_TERM();
|
||||
free(uperl.main);
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
|
||||
|
||||
@@ -68,7 +68,7 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
|
||||
|
||||
hitem = av_fetch(response, 1, 0);
|
||||
if (!hitem) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
|
||||
if (!hitem || !SvRV(*hitem) || SvTYPE(SvRV(*hitem)) != SVt_PVAV) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
|
||||
|
||||
headers = (AV *) SvRV(*hitem);
|
||||
if (!headers) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
|
||||
|
||||
@@ -318,6 +318,13 @@ XS(XS_alarm) {
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_worker_id) {
|
||||
dXSARGS;
|
||||
psgi_check_args(0);
|
||||
ST(0) = newSViv(uwsgi.mywid);
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_async_connect) {
|
||||
|
||||
dXSARGS;
|
||||
@@ -946,7 +953,7 @@ XS(XS_spool) {
|
||||
}
|
||||
}
|
||||
|
||||
char *filename = uwsgi_spool_request(current_wsgi_req(), ub->buf, ub->pos, body, body_len);
|
||||
char *filename = uwsgi_spool_request(NULL, ub->buf, ub->pos, body, body_len);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
if (filename) {
|
||||
ST(0) = newSVpv(filename, strlen(filename));
|
||||
@@ -1042,5 +1049,6 @@ void init_perl_embedded_module() {
|
||||
psgi_xs(spool);
|
||||
|
||||
psgi_xs(add_var);
|
||||
psgi_xs(worker_id);
|
||||
|
||||
}
|
||||
|
||||
@@ -66,17 +66,34 @@ static int uwsgi_pypy_init() {
|
||||
}
|
||||
else {
|
||||
if (upypy.home) {
|
||||
// first try with /bin way:
|
||||
#ifdef __CYGWIN__
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dll");
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/bin/libpypy-c.dll");
|
||||
#elif defined(__APPLE__)
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dylib");
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/bin/libpypy-c.dylib");
|
||||
#else
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.so");
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/bin/libpypy-c.so");
|
||||
#endif
|
||||
if (uwsgi_file_exists(libpath)) {
|
||||
upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
free(libpath);
|
||||
|
||||
// fallback to old-style way
|
||||
if (!upypy.handler) {
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dll");
|
||||
#elif defined(__APPLE__)
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dylib");
|
||||
#else
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.so");
|
||||
#endif
|
||||
if (uwsgi_file_exists(libpath)) {
|
||||
upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
free(libpath);
|
||||
}
|
||||
free(libpath);
|
||||
}
|
||||
// fallback to standard library search path
|
||||
if (!upypy.handler) {
|
||||
|
||||
@@ -325,12 +325,19 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
if (uwsgi.threads > 1 && id) {
|
||||
// if we have multiple threads we need to initialize a PyThreadState for each one
|
||||
for(i=0;i<uwsgi.threads;i++) {
|
||||
//uwsgi_log("%p\n", uwsgi.core[i]->ts[id]);
|
||||
uwsgi.workers[uwsgi.mywid].cores[i].ts[id] = PyThreadState_New( ((PyThreadState *)wi->interpreter)->interp);
|
||||
//uwsgi_log("%p\n", uwsgi.workers[uwsgi.mywid].cores[i].ts[id]);
|
||||
if (!uwsgi.workers[uwsgi.mywid].cores[i].ts[id]) {
|
||||
uwsgi_log("unable to allocate new PyThreadState structure for app %s", wi->mountpoint);
|
||||
goto doh;
|
||||
}
|
||||
// cow ?
|
||||
if (uwsgi.mywid == 0) {
|
||||
int j;
|
||||
for(j=1;j<=uwsgi.numproc;j++) {
|
||||
uwsgi.workers[j].cores[i].ts[id] = uwsgi.workers[0].cores[i].ts[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key) );
|
||||
}
|
||||
|
||||
@@ -397,6 +397,7 @@ void uwsgi_python_post_fork() {
|
||||
PyErr_Clear();
|
||||
|
||||
if (uwsgi.mywid > 0) {
|
||||
uwsgi_python_set_thread_name(0);
|
||||
if (up.auto_reload) {
|
||||
// spawn the reloader thread
|
||||
pthread_t par_tid;
|
||||
@@ -920,12 +921,16 @@ int uwsgi_python_mount_app(char *mountpoint, char *app) {
|
||||
if (strchr(app, ':') || uwsgi_endswith(app, ".py") || uwsgi_endswith(app, ".wsgi")) {
|
||||
uwsgi.wsgi_req->appid = mountpoint;
|
||||
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
|
||||
// lazy ?
|
||||
if (uwsgi.mywid > 0) UWSGI_GET_GIL
|
||||
if (uwsgi.single_interpreter) {
|
||||
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else {
|
||||
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
// lazy ?
|
||||
if (uwsgi.mywid > 0) UWSGI_RELEASE_GIL
|
||||
return id;
|
||||
}
|
||||
return -1;
|
||||
@@ -1266,11 +1271,39 @@ void uwsgi_python_enable_threads() {
|
||||
up.reset_ts = threaded_reset_ts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uwsgi_log("python threads support enabled\n");
|
||||
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_python_set_thread_name(int core_id) {
|
||||
// call threading.currentThread (taken from mod_wsgi, but removes DECREFs as thread in uWSGI are fixed)
|
||||
PyObject *threading_module = PyImport_ImportModule("threading");
|
||||
if (threading_module) {
|
||||
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
|
||||
if (threading_module_dict) {
|
||||
#ifdef PYTHREE
|
||||
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
|
||||
#else
|
||||
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
|
||||
#endif
|
||||
if (threading_current) {
|
||||
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
|
||||
if (!current_thread) {
|
||||
// ignore the error
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
PyObject_SetAttrString(current_thread, "name", PyString_FromFormat("uWSGIWorker%dCore%d", uwsgi.mywid, core_id));
|
||||
Py_INCREF(current_thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_python_init_thread(int core_id) {
|
||||
|
||||
// set a new ThreadState for each thread
|
||||
@@ -1282,29 +1315,7 @@ void uwsgi_python_init_thread(int core_id) {
|
||||
uwsgi_log("python ThreadState %d = %p\n", core_id, pts);
|
||||
#endif
|
||||
UWSGI_GET_GIL;
|
||||
// call threading.currentThread (taken from mod_wsgi, but removes DECREFs as thread in uWSGI are fixed)
|
||||
PyObject *threading_module = PyImport_ImportModule("threading");
|
||||
if (threading_module) {
|
||||
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
|
||||
if (threading_module_dict) {
|
||||
#ifdef PYTHREE
|
||||
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
|
||||
#else
|
||||
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
|
||||
#endif
|
||||
if (threading_current) {
|
||||
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
|
||||
if (!current_thread) {
|
||||
// ignore the error
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
PyObject_SetAttrString(current_thread, "name", PyString_FromFormat("uWSGIWorker%dCore%d", uwsgi.mywid, core_id));
|
||||
Py_INCREF(current_thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi_python_set_thread_name(core_id);
|
||||
UWSGI_RELEASE_GIL;
|
||||
|
||||
|
||||
@@ -1414,7 +1425,15 @@ void *uwsgi_python_autoreloader_thread(void *foobar) {
|
||||
int found = 0;
|
||||
struct uwsgi_string_list *usl = up.auto_reload_ignore;
|
||||
while(usl) {
|
||||
#ifdef PYTHREE
|
||||
PyObject *zero = PyUnicode_AsUTF8String(mod_name);
|
||||
char *str_mod_name = PyString_AsString(zero);
|
||||
int ret_cmp = strcmp(usl->value, str_mod_name);
|
||||
Py_DECREF(zero);
|
||||
if (!ret_cmp) {
|
||||
#else
|
||||
if (!strcmp(usl->value, PyString_AsString(mod_name))) {
|
||||
#endif
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,18 @@ char *uwsgi_python_get_thread_name(PyObject *thread_id) {
|
||||
if (PyInt_AsLong(thread_ident) == PyInt_AsLong(thread_id)) {
|
||||
PyObject *thread_name = PyObject_GetAttrString(threads_list_next, "name");
|
||||
if (!thread_name) goto clear2;
|
||||
#ifdef PYTHREE
|
||||
PyObject *thread_name_utf8 = PyUnicode_AsUTF8String(thread_name);
|
||||
if (!thread_name_utf8) goto clear2;
|
||||
char *name = NULL;
|
||||
char *tmp_name = PyString_AsString(thread_name_utf8);
|
||||
if (tmp_name) {
|
||||
name = uwsgi_str(tmp_name);
|
||||
Py_DECREF(thread_name_utf8);
|
||||
}
|
||||
#else
|
||||
char *name = PyString_AsString(thread_name);
|
||||
#endif
|
||||
Py_DECREF(threads_list_next);
|
||||
Py_DECREF(threads_list_iter);
|
||||
Py_DECREF(threads_list);
|
||||
@@ -133,6 +144,9 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
PyObject *st_items = PyIter_Next(stacktrace_iter);
|
||||
// we have the first traceback item
|
||||
while(st_items) {
|
||||
#ifdef PYTHREE
|
||||
int thread_name_need_free = 0;
|
||||
#endif
|
||||
PyObject *st_filename = PyTuple_GetItem(st_items, 0);
|
||||
if (!st_filename) { Py_DECREF(st_items); goto next; }
|
||||
PyObject *st_lineno = PyTuple_GetItem(st_items, 1);
|
||||
@@ -149,12 +163,26 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
if (!iov[1].iov_base) {
|
||||
iov[1].iov_base = "<UnnamedPythonThread>";
|
||||
}
|
||||
#ifdef PYTHREE
|
||||
else {
|
||||
thread_name_need_free = 1;
|
||||
}
|
||||
#endif
|
||||
iov[1].iov_len = strlen(iov[1].iov_base);
|
||||
|
||||
iov[2].iov_base = " filename = ";
|
||||
iov[2].iov_len = 12;
|
||||
|
||||
#ifdef PYTHREE
|
||||
PyObject *st_filename_utf8 = PyUnicode_AsUTF8String(st_filename);
|
||||
if (!st_filename_utf8) {
|
||||
if (thread_name_need_free) free(iov[1].iov_base);
|
||||
goto next;
|
||||
}
|
||||
iov[3].iov_base = PyString_AsString(st_filename_utf8);
|
||||
#else
|
||||
iov[3].iov_base = PyString_AsString(st_filename);
|
||||
#endif
|
||||
iov[3].iov_len = strlen(iov[3].iov_base);
|
||||
|
||||
iov[4].iov_base = " lineno = ";
|
||||
@@ -166,7 +194,17 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
iov[6].iov_base = " function = ";
|
||||
iov[6].iov_len = 12 ;
|
||||
|
||||
#ifdef PYTHREE
|
||||
PyObject *st_name_utf8 = PyUnicode_AsUTF8String(st_name);
|
||||
if (!st_name_utf8) {
|
||||
if (thread_name_need_free) free(iov[1].iov_base);
|
||||
Py_DECREF(st_filename_utf8);
|
||||
goto next;
|
||||
}
|
||||
iov[7].iov_base = PyString_AsString(st_name_utf8);
|
||||
#else
|
||||
iov[7].iov_base = PyString_AsString(st_name);
|
||||
#endif
|
||||
iov[7].iov_len = strlen(iov[7].iov_base);
|
||||
|
||||
iov[8].iov_base = "";
|
||||
@@ -178,10 +216,24 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
iov[10].iov_base = "\n";
|
||||
iov[10].iov_len = 1;
|
||||
|
||||
#ifdef PYTHREE
|
||||
PyObject *st_line_utf8 = NULL;
|
||||
#endif
|
||||
if (st_line) {
|
||||
iov[8].iov_base = " line = ";
|
||||
iov[8].iov_len = 8;
|
||||
#ifdef PYTHREE
|
||||
PyObject *st_line_utf8 = PyUnicode_AsUTF8String(st_line);
|
||||
if (!st_line_utf8) {
|
||||
if (thread_name_need_free) free(iov[1].iov_base);
|
||||
Py_DECREF(st_filename_utf8);
|
||||
Py_DECREF(st_name_utf8);
|
||||
goto next;
|
||||
}
|
||||
iov[9].iov_base = PyString_AsString(st_line_utf8);
|
||||
#else
|
||||
iov[9].iov_base = PyString_AsString(st_line);
|
||||
#endif
|
||||
iov[9].iov_len = strlen(iov[9].iov_base);
|
||||
}
|
||||
|
||||
@@ -192,6 +244,15 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
// free the line_no
|
||||
free(iov[5].iov_base);
|
||||
Py_DECREF(st_items);
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(st_filename_utf8);
|
||||
Py_DECREF(st_name_utf8);
|
||||
if (st_line_utf8) {
|
||||
Py_DECREF(st_line_utf8);
|
||||
}
|
||||
if (thread_name_need_free)
|
||||
free(iov[1].iov_base);
|
||||
#endif
|
||||
st_items = PyIter_Next(stacktrace_iter);
|
||||
}
|
||||
if (write(client_fd, "\n", 1) < 0) {
|
||||
|
||||
@@ -382,6 +382,11 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
|
||||
if (PyString_Check(py_node)) {
|
||||
node = PyString_AsString(py_node);
|
||||
}
|
||||
#ifdef PYTHREE
|
||||
else if (PyUnicode_Check(py_node)) {
|
||||
node = PyBytes_AsString(PyUnicode_AsLatin1String(py_node));
|
||||
}
|
||||
#endif
|
||||
|
||||
py_func = PyTuple_GetItem(args, 1);
|
||||
|
||||
@@ -1855,7 +1860,6 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
PyObject *spool_dict, *spool_vars;
|
||||
PyObject *zero, *key, *val;
|
||||
uint16_t keysize, valsize;
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
char *body = NULL;
|
||||
size_t body_len= 0;
|
||||
|
||||
@@ -1956,7 +1960,8 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
char *filename = uwsgi_spool_request(wsgi_req, ub->buf, ub->pos, body, body_len);
|
||||
// current_wsgi_req can be NULL, in such a case a non-thread-safe counter will be used
|
||||
char *filename = uwsgi_spool_request(NULL, ub->buf, ub->pos, body, body_len);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
@@ -1988,6 +1993,16 @@ PyObject *py_uwsgi_spooler_pid(PyObject * self, PyObject * args) {
|
||||
return PyInt_FromLong(uspool->pid);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_spooler_pids(PyObject * self, PyObject * args) {
|
||||
PyObject *ret = PyList_New(0);
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
PyList_Append(ret, PyInt_FromLong(uspool->pid));
|
||||
uspool = uspool->next;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_connect(PyObject * self, PyObject * args) {
|
||||
|
||||
@@ -2240,7 +2255,8 @@ PyObject *py_uwsgi_stop(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_request_id(PyObject * self, PyObject * args) {
|
||||
return PyLong_FromUnsignedLongLong(uwsgi.workers[uwsgi.mywid].requests);
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
return PyLong_FromUnsignedLongLong(uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_worker_id(PyObject * self, PyObject * args) {
|
||||
@@ -2419,6 +2435,7 @@ static PyMethodDef uwsgi_spooler_methods[] = {
|
||||
{"set_spooler_frequency", py_uwsgi_spooler_freq, METH_VARARGS, ""},
|
||||
{"spooler_jobs", py_uwsgi_spooler_jobs, METH_VARARGS, ""},
|
||||
{"spooler_pid", py_uwsgi_spooler_pid, METH_VARARGS, ""},
|
||||
{"spooler_pids", py_uwsgi_spooler_pids, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -299,6 +299,8 @@ int uwsgi_python_send_body(struct wsgi_request *, PyObject *);
|
||||
|
||||
int uwsgi_request_python_raw(struct wsgi_request *);
|
||||
|
||||
void uwsgi_python_set_thread_name(int);
|
||||
|
||||
#define py_current_wsgi_req() current_wsgi_req();\
|
||||
if (!wsgi_req) {\
|
||||
return PyErr_Format(PyExc_SystemError, "you can call uwsgi api function only from the main callable");\
|
||||
|
||||
@@ -969,7 +969,6 @@ static int rack_uwsgi_build_spool(VALUE rbkey, VALUE rbval, VALUE argv) {
|
||||
|
||||
static VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
char *body = NULL;
|
||||
size_t body_len= 0;
|
||||
|
||||
@@ -991,7 +990,7 @@ static VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
|
||||
rb_hash_foreach(args, rack_uwsgi_build_spool, (VALUE) ub);
|
||||
|
||||
char *filename = uwsgi_spool_request(wsgi_req, ub->buf, ub->pos, body, body_len);
|
||||
char *filename = uwsgi_spool_request(NULL, ub->buf, ub->pos, body, body_len);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ static int uwsgi_rados_put(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, cha
|
||||
char *body = uwsgi_request_body_read(wsgi_req, UMIN(remains, 32768) , &body_len);
|
||||
if (!body || body == uwsgi.empty) goto error;
|
||||
if (uwsgi.async <= 1) {
|
||||
if (rados_write(ctx, key, body, body_len, off) <= 0) {
|
||||
if (rados_write_full(ctx, key, body, body_len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,7 @@ static int uwsgi_rados_put(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, cha
|
||||
free(urcb);
|
||||
goto error;
|
||||
}
|
||||
if (rados_aio_write(ctx, key, comp, body, body_len, off) < 0) {
|
||||
if (rados_aio_write_full(ctx, key, comp, body, body_len) < 0) {
|
||||
free(urcb);
|
||||
rados_aio_release(comp);
|
||||
goto error;
|
||||
|
||||
@@ -245,7 +245,7 @@ static int rawrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_ga
|
||||
peer->last_hook_read = rr_instance_read;
|
||||
|
||||
// use the address as hostname
|
||||
peer->key = cs->ugs->name;
|
||||
memcpy(peer->key, cs->ugs->name, cs->ugs->name_len);
|
||||
peer->key_len = cs->ugs->name_len;
|
||||
|
||||
// the mapper hook
|
||||
|
||||
@@ -30,6 +30,9 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
|
||||
if (ur->custom & 0x02) {
|
||||
ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
}
|
||||
else if (ur->custom & 0x04) {
|
||||
ub = uwsgi_to_http_dumb(wsgi_req, ur->data2, ur->data2_len, ub_url ? ub_url->buf : NULL, ub_url ? ub_url->pos : 0);
|
||||
}
|
||||
else {
|
||||
ub = uwsgi_to_http(wsgi_req, ur->data2, ur->data2_len, ub_url ? ub_url->buf : NULL, ub_url ? ub_url->pos : 0);
|
||||
}
|
||||
@@ -133,10 +136,16 @@ static int uwsgi_router_http_connect(struct uwsgi_route *ur, char *args) {
|
||||
return uwsgi_router_http(ur, args);
|
||||
}
|
||||
|
||||
static int uwsgi_router_httpdumb(struct uwsgi_route *ur, char *args) {
|
||||
ur->custom = 0x04;
|
||||
return uwsgi_router_http(ur, args);
|
||||
}
|
||||
|
||||
|
||||
static void router_http_register(void) {
|
||||
|
||||
uwsgi_register_router("http", uwsgi_router_http);
|
||||
uwsgi_register_router("httpdumb", uwsgi_router_httpdumb);
|
||||
uwsgi_register_router("proxyhttp", uwsgi_router_proxyhttp);
|
||||
uwsgi_register_router("httpconnect", uwsgi_router_http_connect);
|
||||
uwsgi_register_router("proxyhttpconnect", uwsgi_router_proxyhttp_connect);
|
||||
|
||||
@@ -387,6 +387,7 @@ end:
|
||||
}
|
||||
|
||||
static int uwsgi_routing_func_rpc_raw(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *response = NULL;
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
@@ -418,7 +419,7 @@ static int uwsgi_routing_func_rpc_raw(struct wsgi_request *wsgi_req, struct uwsg
|
||||
remote = at+1;
|
||||
}
|
||||
uint64_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
@@ -426,12 +427,13 @@ static int uwsgi_routing_func_rpc_raw(struct wsgi_request *wsgi_req, struct uwsg
|
||||
if (size == 0) goto end;
|
||||
|
||||
ret = uwsgi_blob_to_response(wsgi_req, response, size);
|
||||
free(response);
|
||||
if (ret == 0) {
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
end:
|
||||
free(response);
|
||||
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
@@ -441,6 +443,7 @@ end:
|
||||
}
|
||||
|
||||
static int uwsgi_routing_func_rpc_var(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *response = NULL;
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
@@ -472,7 +475,7 @@ static int uwsgi_routing_func_rpc_var(struct wsgi_request *wsgi_req, struct uwsg
|
||||
remote = at+1;
|
||||
}
|
||||
uint64_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
@@ -483,9 +486,9 @@ static int uwsgi_routing_func_rpc_var(struct wsgi_request *wsgi_req, struct uwsg
|
||||
free(response);
|
||||
goto end;
|
||||
}
|
||||
free(response);
|
||||
ret = UWSGI_ROUTE_NEXT;
|
||||
end:
|
||||
free(response);
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
|
||||
@@ -23,7 +23,7 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *filename = uwsgi_spool_request(wsgi_req, wsgi_req->buffer, wsgi_req->uh->pktsize, NULL, 0);
|
||||
char *filename = uwsgi_spool_request(NULL, wsgi_req->buffer, wsgi_req->uh->pktsize, NULL, 0);
|
||||
uh.modifier1 = 255;
|
||||
uh.pktsize = 0;
|
||||
if (filename) {
|
||||
|
||||
@@ -288,15 +288,15 @@ static ssize_t sr_read(struct corerouter_peer *main_peer) {
|
||||
// set default peer hook
|
||||
peer->last_hook_read = sr_instance_read;
|
||||
// use the address as hostname
|
||||
peer->key = cs->ugs->name;
|
||||
memcpy(peer->key, cs->ugs->name, cs->ugs->name_len);
|
||||
peer->key_len = cs->ugs->name_len;
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
if (usr.sni) {
|
||||
const char *servername = SSL_get_servername(sr->ssl, TLSEXT_NAMETYPE_host_name);
|
||||
if (servername) {
|
||||
peer->key = (char *) servername;
|
||||
if (servername && strlen(servername) <= 0xff) {
|
||||
peer->key_len = strlen(servername);
|
||||
memcpy(peer->key, servername, peer->key_len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -92,7 +92,7 @@ static void stats_pusher_statsd(struct uwsgi_stats_pusher_instance *uspi, time_t
|
||||
statsd_send_metric(ub, uspi, um->name, um->name_len, *um->value, "|g");
|
||||
}
|
||||
else {
|
||||
statsd_send_metric(ub, uspi, um->name, um->name_len, *um->value, "|m");
|
||||
statsd_send_metric(ub, uspi, um->name, um->name_len, *um->value, "|c");
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (um->reset_after_push){
|
||||
|
||||
@@ -10,7 +10,7 @@ ssize_t uwsgi_systemd_logger(struct uwsgi_logger *ul, char *message, size_t len)
|
||||
for(i=0;i<len;i++) {
|
||||
if (message[i] == '\n') {
|
||||
message[i] = 0;
|
||||
sd_journal_print(LOG_INFO, base);
|
||||
sd_journal_print(LOG_INFO, "%s", base);
|
||||
base = message+i+1;
|
||||
}
|
||||
}
|
||||
|
||||
+91
-7
@@ -49,7 +49,7 @@ static uint16_t http_add_uwsgi_header(struct wsgi_request *wsgi_req, char *hh, s
|
||||
|
||||
if (buffer + keylen + hvlen + 2 + 2 >= watermark) {
|
||||
if (has_prefix) {
|
||||
uwsgi_log("[WARNING] unable to add HTTP_%.*s=%.*s to uwsgi packet, consider increasing buffer size\n", keylen, hh, hvlen, hv);
|
||||
uwsgi_log("[WARNING] unable to add HTTP_%.*s=%.*s to uwsgi packet, consider increasing buffer size\n", keylen-5, hh, hvlen, hv);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[WARNING] unable to add %.*s=%.*s to uwsgi packet, consider increasing buffer size\n", keylen, hh, hvlen, hv);
|
||||
@@ -480,6 +480,96 @@ static void uwsgi_httpize_var(char *buf, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_to_http_dumb(struct wsgi_request *wsgi_req, char *host, uint16_t host_len, char *uri, uint16_t uri_len) {
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->method, wsgi_req->method_len)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, " ", 1)) goto clear;
|
||||
|
||||
if (uri_len && uri) {
|
||||
if (uwsgi_buffer_append(ub, uri, uri_len)) goto clear;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->uri, wsgi_req->uri_len)) goto clear;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append(ub, " ", 1)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->protocol, wsgi_req->protocol_len)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto clear;
|
||||
|
||||
int i;
|
||||
char *x_forwarded_for = NULL;
|
||||
size_t x_forwarded_for_len = 0;
|
||||
|
||||
// start adding headers
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
if (!uwsgi_starts_with(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, "HTTP_", 5)) {
|
||||
|
||||
char *header = wsgi_req->hvec[i].iov_base+5;
|
||||
size_t header_len = wsgi_req->hvec[i].iov_len-5;
|
||||
|
||||
if (host && !uwsgi_strncmp(header, header_len, "HOST", 4)) goto next;
|
||||
|
||||
if (!uwsgi_strncmp(header, header_len, "X_FORWARDED_FOR", 15)) {
|
||||
x_forwarded_for = wsgi_req->hvec[i+1].iov_base;
|
||||
x_forwarded_for_len = wsgi_req->hvec[i+1].iov_len;
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append(ub, header, header_len)) goto clear;
|
||||
|
||||
// transofmr uwsgi var to http header
|
||||
uwsgi_httpize_var((ub->buf+ub->pos) - header_len, header_len);
|
||||
|
||||
if (uwsgi_buffer_append(ub, ": ", 2)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto clear;
|
||||
|
||||
}
|
||||
next:
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
// append custom Host (if needed)
|
||||
if (host) {
|
||||
if (uwsgi_buffer_append(ub, "Host: ", 6)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, host, host_len)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto clear;
|
||||
}
|
||||
|
||||
if (wsgi_req->content_type_len > 0) {
|
||||
if (uwsgi_buffer_append(ub, "Content-Type: ", 14)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->content_type, wsgi_req->content_type_len)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto clear;
|
||||
}
|
||||
|
||||
if (wsgi_req->post_cl > 0) {
|
||||
if (uwsgi_buffer_append(ub, "Content-Length: ", 16)) goto clear;
|
||||
if (uwsgi_buffer_num64(ub, (int64_t) wsgi_req->post_cl)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto clear;
|
||||
}
|
||||
|
||||
// append required headers
|
||||
if (uwsgi_buffer_append(ub, "X-Forwarded-For: ", 17)) goto clear;
|
||||
|
||||
if (x_forwarded_for_len > 0) {
|
||||
if (uwsgi_buffer_append(ub, x_forwarded_for, x_forwarded_for_len)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, ", ", 2)) goto clear;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->remote_addr, wsgi_req->remote_addr_len)) goto clear;
|
||||
|
||||
if (uwsgi_buffer_append(ub, "\r\n\r\n", 4)) goto clear;
|
||||
|
||||
return ub;
|
||||
clear:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *wsgi_req, char *host, uint16_t host_len, char *uri, uint16_t uri_len) {
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
@@ -513,14 +603,8 @@ struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *wsgi_req, char *host, ui
|
||||
// remove dangerous headers
|
||||
if (!uwsgi_strncmp(header, header_len, "CONNECTION", 10)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "KEEP_ALIVE", 10)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "ACCEPT_ENCODING", 15)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "TE", 2)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "TRAILER", 7)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "IF_MATCH", 8)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "IF_MODIFIED_SINCE", 17)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "IF_RANGE", 8)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "IF_UNMODIFIED_SINCE", 19)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "IF_NONE_MATCH", 13)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "X_FORWARDED_FOR", 15)) {
|
||||
x_forwarded_for = wsgi_req->hvec[i+1].iov_base;
|
||||
x_forwarded_for_len = wsgi_req->hvec[i+1].iov_len;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#uwsgi --psgi t/perl/active_workers_signal.pl -s :3031 --perl-no-plack --timer "17 3" -p 8 --cheap --idle 10
|
||||
my $handler = sub {
|
||||
print "hello i am the signal handler on worker ".uwsgi::worker_id()."\n";
|
||||
};
|
||||
|
||||
uwsgi::register_signal(17, 'active-workers', $handler);
|
||||
|
||||
my $app = sub {
|
||||
};
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
{
|
||||
package psgix::harakiri::tester;
|
||||
sub DESTROY { print STDERR "$$: Calling DESTROY\n" }
|
||||
}
|
||||
|
||||
sub {
|
||||
my $env = shift;
|
||||
|
||||
die "PANIC: We should support psgix.harakiri here" unless $env->{'psgix.harakiri'};
|
||||
|
||||
$env->{'psgix.harakiri.tester'} = bless {} => 'psgix::harakiri::tester';
|
||||
my $harakiri = $env->{QUERY_STRING};
|
||||
$env->{'psgix.harakiri.commit'} = $harakiri ? 1 : 0;
|
||||
|
||||
return [200, [], [ $harakiri ? "We are about to destroy ourselves\n" : "We will live for another request\n" ]];
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
[uwsgi]
|
||||
http-socket = :8080
|
||||
|
||||
master = 1
|
||||
|
||||
; Three apps on three mountpoints
|
||||
wsgi-file = %d/useless_app.py
|
||||
|
||||
mount = /foo=%d/useless_app.py
|
||||
mount = /foobis/=%d/useless_app.py
|
||||
mount = /footris/=%d/useless_app.py
|
||||
|
||||
manage-script-name = 1
|
||||
@@ -0,0 +1,59 @@
|
||||
#! /usr/bin/env python3
|
||||
# coding = utf-8
|
||||
# author = Adriano Di Luzio
|
||||
|
||||
# I require requests!
|
||||
|
||||
"""
|
||||
First run:
|
||||
$ ./uwsgi t/python/manage_script_name/manage_script_name_test.ini
|
||||
|
||||
Then run me!
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
HOST = "http://127.0.0.1:8080"
|
||||
|
||||
|
||||
class ManageScriptNameTest(unittest.TestCase):
|
||||
|
||||
def test_classic_mountpoints(self):
|
||||
mps = {
|
||||
"/foo",
|
||||
"/foobis/",
|
||||
"/footris/"
|
||||
}
|
||||
|
||||
for mp in mps:
|
||||
# Requests to /foo should kick-in the managed script name.
|
||||
r = requests.get(HOST + mp)
|
||||
self.assertEqual(r.text, mp)
|
||||
|
||||
ends = mp.endswith("/")
|
||||
|
||||
# And equally requests to /foo/
|
||||
r = requests.get(
|
||||
HOST + mp + "/") if not ends else requests.get(HOST + mp[:-1])
|
||||
self.assertEqual(r.text, mp)
|
||||
|
||||
# Or correct requests (/foo/resource)
|
||||
r = requests.get(
|
||||
HOST + mp + "/" + "resource") if not ends else requests.get(HOST + mp + "resource")
|
||||
self.assertEqual(r.text, mp)
|
||||
|
||||
def test_intriguing_mountpoints(self):
|
||||
mps = {
|
||||
"/fooanything",
|
||||
"/foobisis/",
|
||||
"/foofighters",
|
||||
}
|
||||
|
||||
for mp in mps:
|
||||
r = requests.get(HOST + mp)
|
||||
self.assertEqual(r.text, "")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
@@ -0,0 +1,3 @@
|
||||
def application(env, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
return env['SCRIPT_NAME']
|
||||
+1
-1
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
|
||||
s.name = 'uwsgi'
|
||||
s.license = 'GPL-2'
|
||||
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
|
||||
s.date = '2014-07-01'
|
||||
s.date = '2014-12-30'
|
||||
s.summary = "uWSGI"
|
||||
s.description = "The uWSGI server for Ruby/Rack"
|
||||
s.authors = ["Unbit"]
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define UWSGI_PLUGIN_API 1
|
||||
|
||||
#define UWSGI_HAS_OFFLOAD_UBUFS 1
|
||||
|
||||
#define UMAX16 65536
|
||||
#define UMAX8 256
|
||||
|
||||
@@ -832,6 +836,11 @@ struct uwsgi_cache {
|
||||
int purge_lru;
|
||||
uint64_t lru_head;
|
||||
uint64_t lru_tail;
|
||||
|
||||
int store_delete;
|
||||
int lazy_expire;
|
||||
uint64_t sweep_on_full;
|
||||
int clear_on_full;
|
||||
};
|
||||
|
||||
struct uwsgi_option {
|
||||
@@ -998,6 +1007,7 @@ struct uwsgi_protocol {
|
||||
};
|
||||
|
||||
struct uwsgi_server;
|
||||
struct uwsgi_instance;
|
||||
|
||||
struct uwsgi_plugin {
|
||||
|
||||
@@ -1056,6 +1066,9 @@ struct uwsgi_plugin {
|
||||
struct uwsgi_buffer* (*exception_msg)(struct wsgi_request *);
|
||||
struct uwsgi_buffer* (*exception_repr)(struct wsgi_request *);
|
||||
void (*exception_log)(struct wsgi_request *);
|
||||
|
||||
void (*vassal)(struct uwsgi_instance *);
|
||||
void (*vassal_before_exec)(struct uwsgi_instance *);
|
||||
};
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
@@ -2725,6 +2738,25 @@ struct uwsgi_server {
|
||||
int stats_no_cores;
|
||||
int stats_no_metrics;
|
||||
|
||||
// uWSGI 2.0.7
|
||||
int vassal_sos;
|
||||
|
||||
// uWSGI 2.0.8
|
||||
struct uwsgi_string_list *wait_for_fs;
|
||||
struct uwsgi_string_list *wait_for_dir;
|
||||
struct uwsgi_string_list *wait_for_file;
|
||||
int wait_for_fs_timeout;
|
||||
struct uwsgi_string_list *wait_for_mountpoint;
|
||||
#ifdef UWSGI_SSL
|
||||
int sslv3;
|
||||
struct uwsgi_string_list *ssl_options;
|
||||
#endif
|
||||
struct uwsgi_string_list *hook_post_fork;
|
||||
|
||||
// uWSGI 2.0.9
|
||||
char *subscribe_with_modifier1;
|
||||
struct uwsgi_string_list *pull_headers;
|
||||
|
||||
};
|
||||
|
||||
struct uwsgi_rpc {
|
||||
@@ -3060,6 +3092,7 @@ struct wsgi_request *find_first_accepting_wsgi_req(void);
|
||||
struct wsgi_request *find_wsgi_req_by_fd(int);
|
||||
struct wsgi_request *find_wsgi_req_by_id(int);
|
||||
void async_schedule_to_req_green(void);
|
||||
void async_schedule_to_req(void);
|
||||
|
||||
int async_add_fd_write(struct wsgi_request *, int, int);
|
||||
int async_add_fd_read(struct wsgi_request *, int, int);
|
||||
@@ -4153,6 +4186,7 @@ struct uwsgi_buffer *uwsgi_buffer_from_file(char *);
|
||||
ssize_t uwsgi_buffer_write_simple(struct wsgi_request *, struct uwsgi_buffer *);
|
||||
|
||||
struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
struct uwsgi_buffer *uwsgi_to_http_dumb(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
|
||||
ssize_t uwsgi_pipe(int, int, int);
|
||||
ssize_t uwsgi_pipe_sized(int, int, size_t, int);
|
||||
@@ -4233,6 +4267,28 @@ struct uwsgi_offload_request {
|
||||
|
||||
struct uwsgi_offload_request *prev;
|
||||
struct uwsgi_offload_request *next;
|
||||
|
||||
// added in 2.1
|
||||
struct uwsgi_buffer *ubuf1;
|
||||
struct uwsgi_buffer *ubuf2;
|
||||
struct uwsgi_buffer *ubuf3;
|
||||
struct uwsgi_buffer *ubuf4;
|
||||
struct uwsgi_buffer *ubuf5;
|
||||
struct uwsgi_buffer *ubuf6;
|
||||
struct uwsgi_buffer *ubuf7;
|
||||
struct uwsgi_buffer *ubuf8;
|
||||
|
||||
int64_t custom1;
|
||||
int64_t custom2;
|
||||
int64_t custom3;
|
||||
int64_t custom4;
|
||||
int64_t custom5;
|
||||
int64_t custom6;
|
||||
int64_t custom7;
|
||||
int64_t custom8;
|
||||
|
||||
void *data;
|
||||
void (*free)(struct uwsgi_offload_request *);
|
||||
};
|
||||
|
||||
struct uwsgi_offload_engine {
|
||||
@@ -4590,6 +4646,7 @@ void uwsgi_master_fifo_prepare();
|
||||
int uwsgi_master_fifo();
|
||||
int uwsgi_master_fifo_manage(int);
|
||||
|
||||
void uwsgi_log_do_rotate(char *, char *, off_t, int);
|
||||
void uwsgi_log_rotate();
|
||||
void uwsgi_log_reopen();
|
||||
void uwsgi_reload_workers();
|
||||
@@ -4788,6 +4845,10 @@ mode_t uwsgi_mode_t(char *, int *);
|
||||
|
||||
int uwsgi_notify_socket_manage(int);
|
||||
int uwsgi_notify_msg(char *, char *, size_t);
|
||||
void vassal_sos();
|
||||
|
||||
int uwsgi_wait_for_fs(char *, int);
|
||||
int uwsgi_wait_for_mountpoint(char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+25
-10
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '2.0.6'
|
||||
uwsgi_version = '2.0.9'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -53,6 +53,11 @@ if CPUCOUNT < 1:
|
||||
except:
|
||||
CPUCOUNT = 1
|
||||
|
||||
|
||||
# force single cpu in cygwin mode
|
||||
if uwsgi_os.startswith('CYGWIN'):
|
||||
CPUCOUNT=1
|
||||
|
||||
binary_list = []
|
||||
|
||||
started_at = time.time()
|
||||
@@ -398,18 +403,26 @@ def build_uwsgi(uc, print_only=False, gcll=None):
|
||||
|
||||
path = path.rstrip('/')
|
||||
|
||||
if not os.path.isdir(path):
|
||||
up = {}
|
||||
|
||||
if os.path.isfile(path):
|
||||
bname = os.path.basename(path)
|
||||
# override path
|
||||
path = os.path.dirname(path)
|
||||
up['GCC_LIST'] = [bname]
|
||||
up['NAME'] = bname.split('.')[0]
|
||||
if not path: path = '.'
|
||||
elif os.path.isdir(path):
|
||||
try:
|
||||
execfile('%s/uwsgiplugin.py' % path, up)
|
||||
except:
|
||||
f = open('%s/uwsgiplugin.py' % path)
|
||||
exec(f.read(), up)
|
||||
f.close()
|
||||
else:
|
||||
print("Error: plugin '%s' not found" % p)
|
||||
sys.exit(1)
|
||||
|
||||
up = {}
|
||||
try:
|
||||
execfile('%s/uwsgiplugin.py' % path, up)
|
||||
except:
|
||||
f = open('%s/uwsgiplugin.py' % path)
|
||||
exec(f.read(), up)
|
||||
f.close()
|
||||
|
||||
p_cflags = cflags[:]
|
||||
try:
|
||||
p_cflags += up['CFLAGS']
|
||||
@@ -1158,6 +1171,8 @@ class uConf(object):
|
||||
else:
|
||||
jsonconf = spcall("pkg-config --cflags yajl")
|
||||
if jsonconf:
|
||||
if jsonconf.endswith('include/yajl'):
|
||||
jsonconf = jsonconf.rstrip('yajl')
|
||||
self.cflags.append(jsonconf)
|
||||
self.cflags.append("-DUWSGI_JSON")
|
||||
self.gcc_list.append('core/json')
|
||||
|
||||
+28
-3
@@ -18,6 +18,29 @@ mule_functions = {}
|
||||
postfork_chain = []
|
||||
|
||||
|
||||
# Python3 compatibility
|
||||
def _encode1(val):
|
||||
if sys.version_info >= (3, 0) and isinstance(val, str):
|
||||
return val.encode('utf-8')
|
||||
else:
|
||||
return val
|
||||
|
||||
|
||||
def _decode1(val):
|
||||
if sys.version_info >= (3, 0) and isinstance(val, bytes):
|
||||
return val.decode('utf-8')
|
||||
else:
|
||||
return val
|
||||
|
||||
|
||||
def _encode_to_spooler(vars):
|
||||
return dict((_encode1(K), _encode1(V)) for (K, V) in vars.items())
|
||||
|
||||
|
||||
def _decode_from_spooler(vars):
|
||||
return dict((_decode1(K), _decode1(V)) for (K, V) in vars.items())
|
||||
|
||||
|
||||
def get_free_signal():
|
||||
for signum in range(0, 256):
|
||||
if not uwsgi.signal_registered(signum):
|
||||
@@ -27,6 +50,7 @@ def get_free_signal():
|
||||
|
||||
|
||||
def manage_spool_request(vars):
|
||||
vars = _decode_from_spooler(vars)
|
||||
f = spooler_functions[vars['ud_spool_func']]
|
||||
if 'args' in vars:
|
||||
args = pickle.loads(vars.pop('args'))
|
||||
@@ -67,7 +91,7 @@ class postfork(object):
|
||||
class _spoolraw(object):
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
arguments = self.base_dict
|
||||
arguments = self.base_dict.copy()
|
||||
if not self.pass_arguments:
|
||||
if len(args) > 0:
|
||||
arguments.update(args[0])
|
||||
@@ -79,8 +103,9 @@ class _spoolraw(object):
|
||||
if key in kwargs:
|
||||
spooler_args.update({key: kwargs.pop(key)})
|
||||
arguments.update(spooler_args)
|
||||
arguments.update({'args': pickle.dumps(args), 'kwargs': pickle.dumps(kwargs)})
|
||||
return uwsgi.spool(arguments)
|
||||
arguments.update(
|
||||
{'args': pickle.dumps(args), 'kwargs': pickle.dumps(kwargs)})
|
||||
return uwsgi.spool(_encode_to_spooler(arguments))
|
||||
|
||||
# For backward compatibility (uWSGI < 1.9.13)
|
||||
def spool(self, *args, **kwargs):
|
||||
|
||||
Reference in New Issue
Block a user