Compare commits

...
Author SHA1 Message Date
Roberto De Ioris 1aa6eeca1b added sweep_on_full, clear_on_full and no_expire 2014-10-14 05:24:28 +02:00
Unbit f778e30d48 run the sweeper only if required 2014-10-13 13:00:07 +02:00
Unbit e071184d53 ignore lazy caches from the sweeper 2014-10-13 12:55:26 +02:00
Unbit 1d09cde778 implemented cache lazy expire 2014-10-13 12:40:40 +02:00
Greg Dahlman 70ee29becb added wait for fs and wait for mountpoint 2014-10-10 11:06:44 +02:00
Unbit 60e26333bf allows building external plugins as embedded 2014-10-10 11:00:28 +02:00
Unbit 865b9c199d improved offload api 2014-10-10 10:58:45 +02:00
Unbit 833193a1ba added UWSGI_HAS_OFFLOAD_UBUFS 2014-10-10 10:58:41 +02:00
Unbit 4eab050634 added 8 uwsgi_buffer and 8 custom fields to offload request 2014-10-10 10:57:03 +02:00
Aldur 688d1d3b75 fixed python3 support in spooler decorators 2014-10-10 10:55:18 +02:00
Unbit 349daee614 fixed uwsgidecorators spooler arguments 2014-10-10 10:49:18 +02:00
Unbit 0d272cf747 added Adriano Di Luzio to 2.0 CONTRIBUTORS 2014-10-10 10:47:19 +02:00
Unbit 46ac28efae fixed tcsetattr 2014-10-10 10:45:58 +02:00
Unbit 31b3bcc83d fixed kevent 2014-10-10 10:45:06 +02:00
Unbit f364d676fa automatically manage HTTP_X_FORWARDED_PROTO 2014-10-10 10:40:13 +02:00
Unbit c72fde1eed ensure PSGI response headers are in the right format [2] 2014-10-03 08:32:03 +02:00
Unbit a5cacfbba6 ensure PSGI response headers are in the right format 2014-10-03 08:31:52 +02:00
Unbit 921cfa5d79 backported daemons and proto http fixes from 2.1 2014-10-03 08:30:11 +02:00
Roberto De Ioris 9c676c62f5 destroy the whole instance on Emperor error 2014-10-03 08:26:57 +02:00
Roberto De Ioris 2917de3e76 exit on Emperor error 2014-10-03 08:26:43 +02:00
Unbit e836272c07 attempt to fix #732 2014-10-03 08:26:21 +02:00
Roberto De Ioris 7e25452242 set version to 2.0.7.1 2014-09-12 06:37:06 +02:00
19 changed files with 411 additions and 88 deletions
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+38
View File
@@ -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) {
+5
View File
@@ -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;
}
+72
View File
@@ -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
View File
@@ -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);
}
}
+7 -2
View File
@@ -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;
+1 -1
View File
@@ -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;}
+30 -23
View File
@@ -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;
+61
View File
@@ -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) {
+2
View File
@@ -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");\
+2 -2
View File
@@ -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
View File
@@ -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);
+38
View File
@@ -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
View File
@@ -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
View File
@@ -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):