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 | ||
|
|
f14cb7e02a |
+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
|
||||
|
||||
@@ -29,3 +29,4 @@ 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);
|
||||
}
|
||||
|
||||
+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
|
||||
|
||||
+91
-40
@@ -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;
|
||||
@@ -420,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);
|
||||
@@ -445,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) {
|
||||
@@ -468,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;
|
||||
@@ -718,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;
|
||||
}
|
||||
@@ -741,16 +788,8 @@ 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) {
|
||||
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++;
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
if (uc->purge_lru && uc->lru_head)
|
||||
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
|
||||
cache_full(uc);
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
@@ -851,16 +890,8 @@ 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) {
|
||||
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++;
|
||||
uci->first_block = old_first_block;
|
||||
if (uc->purge_lru && uc->lru_head)
|
||||
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
|
||||
cache_full(uc);
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
@@ -1072,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);
|
||||
@@ -1151,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() {
|
||||
@@ -1241,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,
|
||||
@@ -1273,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);
|
||||
@@ -1326,6 +1370,13 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
|
||||
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) {
|
||||
|
||||
+12
-1
@@ -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) {
|
||||
@@ -1554,6 +1564,7 @@ void uwsgi_emperor_run_scanners(void) {
|
||||
ues->monitor->func(ues);
|
||||
ues = ues->next;
|
||||
}
|
||||
emperor_warming_up = 0;
|
||||
}
|
||||
|
||||
void emperor_build_scanners() {
|
||||
|
||||
+1
-1
@@ -948,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 {
|
||||
|
||||
+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();
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -861,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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
+73
-1
@@ -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) {
|
||||
@@ -3399,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;
|
||||
}
|
||||
}
|
||||
@@ -4463,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++;
|
||||
}
|
||||
}
|
||||
|
||||
+26
-3
@@ -393,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},
|
||||
@@ -460,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},
|
||||
@@ -625,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
|
||||
@@ -637,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
|
||||
@@ -850,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},
|
||||
@@ -1534,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()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2533,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);
|
||||
@@ -3281,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;
|
||||
@@ -3357,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);
|
||||
@@ -3430,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
@@ -518,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);
|
||||
}
|
||||
@@ -559,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
|
||||
@@ -659,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)) {
|
||||
@@ -727,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;
|
||||
}
|
||||
|
||||
@@ -856,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;
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
@@ -1270,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
|
||||
@@ -1286,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;
|
||||
|
||||
|
||||
@@ -1418,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) {
|
||||
|
||||
@@ -1993,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) {
|
||||
|
||||
@@ -2425,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");\
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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-09-05'
|
||||
s.date = '2014-12-30'
|
||||
s.summary = "uWSGI"
|
||||
s.description = "The uWSGI server for Ruby/Rack"
|
||||
s.authors = ["Unbit"]
|
||||
|
||||
@@ -8,6 +8,8 @@ extern "C" {
|
||||
|
||||
#define UWSGI_PLUGIN_API 1
|
||||
|
||||
#define UWSGI_HAS_OFFLOAD_UBUFS 1
|
||||
|
||||
#define UMAX16 65536
|
||||
#define UMAX8 256
|
||||
|
||||
@@ -836,6 +838,9 @@ struct uwsgi_cache {
|
||||
uint64_t lru_tail;
|
||||
|
||||
int store_delete;
|
||||
int lazy_expire;
|
||||
uint64_t sweep_on_full;
|
||||
int clear_on_full;
|
||||
};
|
||||
|
||||
struct uwsgi_option {
|
||||
@@ -2736,6 +2741,22 @@ struct uwsgi_server {
|
||||
// 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 {
|
||||
@@ -3071,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);
|
||||
@@ -4164,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);
|
||||
@@ -4244,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 {
|
||||
@@ -4802,6 +4847,9 @@ 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
|
||||
}
|
||||
#endif
|
||||
|
||||
+20
-10
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '2.0.7'
|
||||
uwsgi_version = '2.0.9'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -403,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']
|
||||
@@ -1163,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