mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-07 17:38:52 +00:00
Compare commits
22
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1aa6eeca1b | ||
|
|
f778e30d48 | ||
|
|
e071184d53 | ||
|
|
1d09cde778 | ||
|
|
70ee29becb | ||
|
|
60e26333bf | ||
|
|
865b9c199d | ||
|
|
833193a1ba | ||
|
|
4eab050634 | ||
|
|
688d1d3b75 | ||
|
|
349daee614 | ||
|
|
0d272cf747 | ||
|
|
46ac28efae | ||
|
|
31b3bcc83d | ||
|
|
f364d676fa | ||
|
|
c72fde1eed | ||
|
|
a5cacfbba6 | ||
|
|
921cfa5d79 | ||
|
|
9c676c62f5 | ||
|
|
2917de3e76 | ||
|
|
e836272c07 | ||
|
|
7e25452242 |
@@ -29,3 +29,4 @@ Danila Shtan <danila@shtan.ru>
|
||||
Ævar Arnfjörð Bjarmason
|
||||
Yu Zhao (getcwd)
|
||||
Mathieu Dupuy
|
||||
Adriano Di Luzio (adriano@unbit.it)
|
||||
|
||||
+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
|
||||
|
||||
+84
-40
@@ -24,6 +24,42 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
*/
|
||||
|
||||
static void cache_full(struct uwsgi_cache *uc) {
|
||||
uint64_t i;
|
||||
|
||||
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 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) {
|
||||
uwsgi_cache_del2(uc, NULL, 0, i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uc->clear_on_full) {
|
||||
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 +456,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 +492,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 +515,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 +766,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 +781,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 +883,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 +1096,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 +1175,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 +1269,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 +1305,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 +1363,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) {
|
||||
|
||||
+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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-3
@@ -460,6 +460,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},
|
||||
@@ -1534,8 +1540,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()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3432,7 +3440,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,6 +321,13 @@ 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;
|
||||
}
|
||||
|
||||
PyObject *asyncio = PyImport_ImportModule("asyncio");
|
||||
if (!asyncio) uwsgi_pyexit;
|
||||
|
||||
|
||||
@@ -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;}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -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,13 @@ 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;
|
||||
|
||||
};
|
||||
|
||||
struct uwsgi_rpc {
|
||||
@@ -3071,6 +3083,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);
|
||||
@@ -4244,6 +4257,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 +4837,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
|
||||
|
||||
+18
-10
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '2.0.7'
|
||||
uwsgi_version = '2.0.8'
|
||||
|
||||
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']
|
||||
|
||||
+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