Hello community, here is the log from the commit of package uwsgi for openSUSE:Factory checked in at 2015-11-12 19:40:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/uwsgi (Old) and /work/SRC/openSUSE:Factory/.uwsgi.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "uwsgi" Changes: -------- --- /work/SRC/openSUSE:Factory/uwsgi/uwsgi.changes 2015-08-19 09:29:26.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.uwsgi.new/uwsgi.changes 2015-11-12 19:41:00.000000000 +0100 @@ -1,0 +2,46 @@ +Sat Sep 26 17:39:41 UTC 2015 - [email protected] + +- Remove uwsgi-2.0.10-gcc5.patch as it was integrated upstream +- Update to 2.0.11.1: + * Bugfixes + * fixed HTTPS router resource deallocation and fiel descriptors leak + * do not spit out ssl errors when errno is 0 + * New Features + * The unix_signal hook - You can now remap UNIX signals to specific + functions symbols +- Changes from 2.0.11: + * Bugfixes + * [pypy] fixed misuse of ffi.string + * fixed detection for gcc 5 (jimfunk) + * fixed shared sockets for gateways + * [psgi] Changed abs to labs because offset is declared as a long (Peter H. + Ezetta) + * add null terminator to uwsgi_get_dot_h() and uwsgi_config_py() (Jay + Oster) + * fixed thread waiting during stop/restart (Kaiwen Xu) + * fixed chain reloading verbosity + * [python] fixed spooler job reference counting (Curtis Maloney) + * various static analysis improvements (Riccardo Magliocchetti) + * fixed sharedarea support for very big ranges + * fixed gzip transformation for zero-sized responses (Curtis Maloney) + * fixed management of https client certificate authentication (Vladimir + Didenko) + * fixed OpenBSD build + * fixed TMPFILE permissions + * New Features + * The mem_collector thread - Evil memory monitors (like --evil-reload-on-rss) + are now asynchronously managed by a dedicated thread. This solves the issue + of runaway processes not catched by the master. + * fixpathinfo routing action - This is another step in removing the need of + the infamous uwsgi_modifier1 30 relic. + * uwsgi[sor] and time[micros] routing vars - This two new vars exposes the + start of the current request (in micros) and the current time (again in + micros) + * wait-for-socket - This works like wait-for-fs/iface/file/dir. The spawn + of the instance is suspended until the specified tcp/unix socket is + ready. You can use it to synchronize vassals spawn (like stopping a + vassal until a postgresql server has been spawned) + * wait_for hooks - All of the wait-for-* functions can now be used as a + hook + +------------------------------------------------------------------- Old: ---- debian.tar.gz uwsgi-2.0.10-gcc5.patch uwsgi-2.0.10.tar.gz uwsgi.dsc New: ---- uwsgi-2.0.11.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ uwsgi.spec ++++++ --- /var/tmp/diff_new_pack.S5YSRl/_old 2015-11-12 19:41:02.000000000 +0100 +++ /var/tmp/diff_new_pack.S5YSRl/_new 2015-11-12 19:41:02.000000000 +0100 @@ -17,7 +17,7 @@ Name: uwsgi -Version: 2.0.10 +Version: 2.0.11.1 Release: 0 Summary: Application Container Server for Networked/Clustered Web Applications License: GPL-2.0-with-GCC-exception @@ -42,8 +42,6 @@ Patch3: uwsgi-1.9.11-systemd_logger-old_systemd.patch # PATCH-FIX-OPENSUSE uwsgi-1.9.13-emperor_pg-Wformat.patch - gcc complains about lack of -Wformat with -Wformat-security from pg_config Patch4: uwsgi-1.9.13-emperor_pg-Wformat.patch -# PATCH-FIX-UPSTREAM uwsgi-2.0.10-gcc5.patch - Fix version detection for GCC 5 -Patch5: uwsgi-2.0.10-gcc5.patch %define apache_branch %(rpm -q --qf %%{version} apache2 | grep -E -o "2\\.[0-9]+") %if "%{apache_branch}" == "2.4" %define apxs %{_bindir}/apxs2 @@ -450,7 +448,6 @@ %patch2 -p1 %patch3 -p1 %patch4 -p1 -%patch5 -p1 # Generate a config that builds all plugins except for examples and stuff we # can't satisfy the requirements for or are just broken excluded_plugins="" ++++++ uwsgi-2.0.10.tar.gz -> uwsgi-2.0.11.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/CONTRIBUTORS new/uwsgi-2.0.11.1/CONTRIBUTORS --- old/uwsgi-2.0.10/CONTRIBUTORS 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/CONTRIBUTORS 2015-07-19 08:17:07.000000000 +0200 @@ -30,3 +30,5 @@ Yu Zhao (getcwd) Mathieu Dupuy Adriano Di Luzio ([email protected]) +Curtis Maloney +Vladimir Didenko diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/emperor.c new/uwsgi-2.0.11.1/core/emperor.c --- old/uwsgi-2.0.10/core/emperor.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/emperor.c 2015-07-19 08:17:07.000000000 +0200 @@ -2295,6 +2295,9 @@ } free(env_emperor_fd_config); } + if (fds) + free(fds); + close(proxy_fd); break; } next: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/gateway.c new/uwsgi-2.0.11.1/core/gateway.c --- old/uwsgi-2.0.10/core/gateway.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/gateway.c 2015-07-19 08:17:07.000000000 +0200 @@ -72,7 +72,7 @@ if (gw_pid == 0) { uwsgi_fixup_fds(0, 0, ug); - uwsgi_close_all_sockets(); + uwsgi_close_all_unshared_sockets(); if (uwsgi.master_as_root) uwsgi_as_root(); #ifdef __linux__ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/hooks.c new/uwsgi-2.0.11.1/core/hooks.c --- old/uwsgi-2.0.10/core/hooks.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/hooks.c 2015-07-19 08:17:07.000000000 +0200 @@ -407,6 +407,24 @@ #endif } +static int uwsgi_hook_unix_signal(char *arg) { + char *space = strchr(arg, ' '); + if (!space) { + uwsgi_log("invalid unix_signal syntax, must be <signum> <func>\n"); + return -1; + } + *space = 0; + int signum = atoi(arg); + *space = ' '; + void (*func)(int) = dlsym(RTLD_DEFAULT, space+1); + if (!func) { + uwsgi_log("unable to find function \"%s\"\n", space+1); + return -1; + } + uwsgi_unix_signal(signum, func); + return 0; +} + static int uwsgi_hook_callint(char *arg) { char *space = strchr(arg, ' '); @@ -557,6 +575,22 @@ return 0; } +static int uwsgi_hook_wait_for_fs(char *arg) { + return uwsgi_wait_for_fs(arg, 0); +} + +static int uwsgi_hook_wait_for_file(char *arg) { + return uwsgi_wait_for_fs(arg, 1); +} + +static int uwsgi_hook_wait_for_dir(char *arg) { + return uwsgi_wait_for_fs(arg, 2); +} + +static int uwsgi_hook_wait_for_socket(char *arg) { + return uwsgi_wait_for_socket(arg); +} + void uwsgi_register_base_hooks() { uwsgi_register_hook("cd", uwsgi_hook_chdir); uwsgi_register_hook("chdir", uwsgi_hook_chdir); @@ -598,6 +632,14 @@ uwsgi_register_hook("rpc", uwsgi_hook_rpc); uwsgi_register_hook("retryrpc", uwsgi_hook_retryrpc); + uwsgi_register_hook("wait_for_fs", uwsgi_hook_wait_for_fs); + uwsgi_register_hook("wait_for_file", uwsgi_hook_wait_for_file); + uwsgi_register_hook("wait_for_dir", uwsgi_hook_wait_for_dir); + + uwsgi_register_hook("wait_for_socket", uwsgi_hook_wait_for_socket); + + uwsgi_register_hook("unix_signal", uwsgi_hook_unix_signal); + // for testing uwsgi_register_hook("exit", uwsgi_hook_exit); uwsgi_register_hook("print", uwsgi_hook_print); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/init.c new/uwsgi-2.0.11.1/core/init.c --- old/uwsgi-2.0.10/core/init.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/init.c 2015-07-19 08:17:07.000000000 +0200 @@ -471,6 +471,10 @@ exit(1); } + if (uwsgi.evil_reload_on_rss || uwsgi.evil_reload_on_as) { + if (!uwsgi.mem_collector_freq) uwsgi.mem_collector_freq = 3; + } + /* here we try to choose if thunder lock is a good thing */ #ifdef UNBIT if (uwsgi.numproc > 1 && !uwsgi.map_socket) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/legion.c new/uwsgi-2.0.11.1/core/legion.c --- old/uwsgi-2.0.10/core/legion.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/legion.c 2015-07-19 08:17:07.000000000 +0200 @@ -277,14 +277,12 @@ memcpy(best_uuid, node->uuid, 36); } // go on if i am not an arbiter - else if (ul->valor > 0) { - // no potential Lord is available, i will propose myself - // but only if i am not suspended... - if (uwsgi_now() > ul->suspended_til) { - best_valor = ul->valor; - memcpy(best_uuid, ul->uuid, 36); - i_am_the_best = 1; - } + // no potential Lord is available, i will propose myself + // but only if i am not suspended... + else if (ul->valor > 0 && uwsgi_now() > ul->suspended_til) { + best_valor = ul->valor; + memcpy(best_uuid, ul->uuid, 36); + i_am_the_best = 1; } else { // empty lord diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/logging.c new/uwsgi-2.0.11.1/core/logging.c --- old/uwsgi-2.0.10/core/logging.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/logging.c 2015-07-19 08:17:07.000000000 +0200 @@ -3,6 +3,7 @@ #endif #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) #include <sys/user.h> +#include <sys/sysctl.h> #include <kvm.h> #elif defined(__sun__) /* Terrible Hack !!! */ @@ -13,10 +14,6 @@ #define _FILE_OFFSET_BITS 64 #endif -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) -#include <sys/sysctl.h> -#endif - #ifdef __DragonFly__ #include <uwsgi.h> #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/master_checks.c new/uwsgi-2.0.11.1/core/master_checks.c --- old/uwsgi-2.0.10/core/master_checks.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/master_checks.c 2015-07-19 08:17:07.000000000 +0200 @@ -39,6 +39,8 @@ // check for chain reload void uwsgi_master_check_chain() { + static time_t last_check = 0; + if (!uwsgi.status.chain_reloading) return; // we need to ensure the previous worker (if alive) is accepting new requests @@ -49,7 +51,11 @@ if (previous_worker->pid > 0 && !previous_worker->cheaped) { // the worker has been respawned but it is still not ready if (previous_worker->accepting == 0) { - uwsgi_log_verbose("chain is still waiting for worker %d...\n", uwsgi.status.chain_reloading-1); + time_t now = uwsgi_now(); + if (now != last_check) { + uwsgi_log_verbose("chain is still waiting for worker %d...\n", uwsgi.status.chain_reloading-1); + last_check = now; + } return; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/routing.c new/uwsgi-2.0.11.1/core/routing.c --- old/uwsgi-2.0.10/core/routing.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/routing.c 2015-07-19 08:17:07.000000000 +0200 @@ -1215,6 +1215,27 @@ return 0; } +// fixpathinfo route +static int uwsgi_router_fixpathinfo_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) { + if (wsgi_req->script_name_len == 0) + return UWSGI_ROUTE_NEXT; + + char *ptr = uwsgi_req_append(wsgi_req, "PATH_INFO", 9, wsgi_req->path_info+wsgi_req->script_name_len, wsgi_req->path_info_len - wsgi_req->script_name_len); + if (!ptr) { + return UWSGI_ROUTE_BREAK; + } + wsgi_req->path_info = wsgi_req->path_info+wsgi_req->script_name_len; + wsgi_req->path_info_len = wsgi_req->path_info_len - wsgi_req->script_name_len; + return UWSGI_ROUTE_NEXT; +} +static int uwsgi_router_fixpathinfo(struct uwsgi_route *ur, char *arg) { + ur->func = uwsgi_router_fixpathinfo_func; + ur->data = arg; + ur->data_len = strlen(arg); + return 0; +} + + // setscheme route static int uwsgi_router_setscheme_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) { char **subject = (char **) (((char *)(wsgi_req))+ur->subject); @@ -1778,6 +1799,10 @@ ret = uwsgi_64bit2str(wsgi_req->response_size); *vallen = strlen(ret); } + else if (!uwsgi_strncmp(key, keylen, "sor", 3)) { + ret = uwsgi_64bit2str(wsgi_req->start_of_request); + *vallen = strlen(ret); + } return ret; } @@ -1814,6 +1839,10 @@ ret = uwsgi_num2str(uwsgi_now()); *vallen = strlen(ret); } + else if (!uwsgi_strncmp(key, keylen, "micros", 6)) { + ret = uwsgi_64bit2str(uwsgi_micros()); + *vallen = strlen(ret); + } return ret; } @@ -1871,6 +1900,7 @@ uwsgi_register_router("seturi", uwsgi_router_seturi); uwsgi_register_router("setremoteaddr", uwsgi_router_setremoteaddr); uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo); + uwsgi_register_router("fixpathinfo", uwsgi_router_fixpathinfo); uwsgi_register_router("setdocroot", uwsgi_router_setdocroot); uwsgi_register_router("setscheme", uwsgi_router_setscheme); uwsgi_register_router("setprocname", uwsgi_router_setprocname); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/sharedarea.c new/uwsgi-2.0.11.1/core/sharedarea.c --- old/uwsgi-2.0.10/core/sharedarea.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/sharedarea.c 2015-07-19 08:17:07.000000000 +0200 @@ -280,8 +280,8 @@ } uwsgi.sharedareas[id]->id = id; uwsgi.sharedareas[id]->fd = fd; - uwsgi.sharedareas[id]->pages = len / uwsgi.page_size; - if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++; + uwsgi.sharedareas[id]->pages = len / (size_t) uwsgi.page_size; + if (len % (size_t) uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++; uwsgi.sharedareas[id]->max_pos = len-1; char *id_str = uwsgi_num2str(id); uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str)); @@ -292,12 +292,12 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) { int id = uwsgi_sharedarea_new_id(); - uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1)); - uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size; + uwsgi.sharedareas[id] = uwsgi_calloc_shared((size_t)uwsgi.page_size * (size_t)(pages + 1)); + uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + (size_t) uwsgi.page_size; uwsgi.sharedareas[id]->id = id; uwsgi.sharedareas[id]->fd = -1; uwsgi.sharedareas[id]->pages = pages; - uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1; + uwsgi.sharedareas[id]->max_pos = ((size_t)uwsgi.page_size * (size_t)pages) -1; char *id_str = uwsgi_num2str(id); uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str)); free(id_str); @@ -310,8 +310,8 @@ uwsgi.sharedareas[id]->area = area; uwsgi.sharedareas[id]->id = id; uwsgi.sharedareas[id]->fd = -1; - uwsgi.sharedareas[id]->pages = len / uwsgi.page_size; - if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++; + uwsgi.sharedareas[id]->pages = len / (size_t) uwsgi.page_size; + if (len % (size_t) uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++; uwsgi.sharedareas[id]->max_pos = len-1; char *id_str = uwsgi_num2str(id); uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str)); @@ -348,8 +348,8 @@ else { len = uwsgi_n64(s_size); } - pages = len / uwsgi.page_size; - if (len % uwsgi.page_size != 0) pages++; + pages = len / (size_t) uwsgi.page_size; + if (len % (size_t) uwsgi.page_size != 0) pages++; } if (s_offset) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/socket.c new/uwsgi-2.0.11.1/core/socket.c --- old/uwsgi-2.0.10/core/socket.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/socket.c 2015-07-19 08:17:07.000000000 +0200 @@ -1249,10 +1249,20 @@ } void uwsgi_close_all_sockets() { + struct uwsgi_socket *uwsgi_sock = uwsgi.sockets; + + while (uwsgi_sock) { + if (uwsgi_sock->bound) + close(uwsgi_sock->fd); + uwsgi_sock = uwsgi_sock->next; + } +} + +void uwsgi_close_all_unshared_sockets() { struct uwsgi_socket *uwsgi_sock = uwsgi.sockets; while (uwsgi_sock) { - if (uwsgi_sock->bound) + if (uwsgi_sock->bound && !uwsgi_sock->shared) close(uwsgi_sock->fd); uwsgi_sock = uwsgi_sock->next; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/ssl.c new/uwsgi-2.0.11.1/core/ssl.c --- old/uwsgi-2.0.10/core/ssl.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/ssl.c 2015-07-19 08:17:07.000000000 +0200 @@ -30,7 +30,18 @@ } int uwsgi_ssl_verify_callback(int ok, X509_STORE_CTX * x509_store) { - return 1; + if (!ok && uwsgi.ssl_verbose) { + char buf[256]; + X509 *err_cert; + int depth; + int err; + depth = X509_STORE_CTX_get_error_depth(x509_store); + err_cert = X509_STORE_CTX_get_current_cert(x509_store); + X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); + err = X509_STORE_CTX_get_error(x509_store); + uwsgi_log("[uwsgi-ssl] client certificate verify error: num=%d:%s:depth=%d:%s\n", err, X509_verify_cert_error_string(err), depth, buf); + } + return ok; } int uwsgi_ssl_session_new_cb(SSL *ssl, SSL_SESSION *sess) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/utils.c new/uwsgi-2.0.11.1/core/utils.c --- old/uwsgi-2.0.10/core/utils.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/utils.c 2015-07-19 08:17:07.000000000 +0200 @@ -3514,7 +3514,7 @@ tmpdir = "/tmp"; } #ifdef O_TMPFILE - fd = open(tmpdir, O_TMPFILE | O_RDWR); + fd = open(tmpdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR); if (fd >= 0) { return fd; } @@ -4446,6 +4446,7 @@ } } free(fds); + close(ns_fd); break; } if (fds) @@ -4510,6 +4511,7 @@ sleep(1); counter++; } + return -1; } // type -> 1 file, 2 dir, 0 both @@ -4534,4 +4536,29 @@ sleep(1); counter++; } + return -1; +} + +int uwsgi_wait_for_socket(char *socket_name) { + if (!uwsgi.wait_for_socket_timeout) { + uwsgi.wait_for_socket_timeout = 60; + } + uwsgi_log("waiting for %s (max %d seconds) ...\n", socket_name, uwsgi.wait_for_socket_timeout); + int counter = 0; + for (;;) { + if (counter > uwsgi.wait_for_socket_timeout) { + uwsgi_log("%s unavailable after %d seconds\n", socket_name, counter); + return -1; + } + // wait for 1 second to respect uwsgi.wait_for_fs_timeout + int fd = uwsgi_connect(socket_name, 1, 0); + if (fd < 0) goto retry; + close(fd); + uwsgi_log_verbose("%s ready\n", socket_name); + return 0; +retry: + sleep(1); + counter++; + } + return -1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/core/uwsgi.c new/uwsgi-2.0.11.1/core/uwsgi.c --- old/uwsgi-2.0.10/core/uwsgi.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/core/uwsgi.c 2015-07-19 08:17:07.000000000 +0200 @@ -469,6 +469,9 @@ {"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}, + {"wait-for-socket", required_argument, 0, "wait for the specified socket to be ready before loading apps", uwsgi_opt_add_string_list, &uwsgi.wait_for_socket, 0}, + {"wait-for-socket-timeout", required_argument, 0, "set the timeout for wait-for-socket", uwsgi_opt_set_int, &uwsgi.wait_for_socket_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}, @@ -518,6 +521,7 @@ {"reload-on-rss", required_argument, 0, "reload if rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_rss, UWSGI_OPT_MEMORY}, {"evil-reload-on-as", required_argument, 0, "force the master to reload a worker if its address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_as, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY}, {"evil-reload-on-rss", required_argument, 0, "force the master to reload a worker if its rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_rss, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY}, + {"mem-collector-freq", required_argument, 0, "set the memory collector frequency when evil reloads are in place", uwsgi_opt_set_int, &uwsgi.mem_collector_freq, 0}, {"reload-on-fd", required_argument, 0, "reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.reload_on_fd, UWSGI_OPT_MASTER}, {"brutal-reload-on-fd", required_argument, 0, "brutal reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.brutal_reload_on_fd, UWSGI_OPT_MASTER}, @@ -1176,7 +1180,7 @@ int sudden_death = 0; pthread_mutex_lock(&uwsgi.six_feet_under_lock); - for (i = 0; i < uwsgi.threads; i++) { + for (i = 1; i < uwsgi.threads; i++) { if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, pthread_self())) { if (pthread_cancel(uwsgi.workers[uwsgi.mywid].cores[i].thread_id)) { uwsgi_error("pthread_cancel()\n"); @@ -1189,7 +1193,7 @@ goto end; // wait for thread termination - for (i = 0; i < uwsgi.threads; i++) { + for (i = 1; i < uwsgi.threads; i++) { if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, pthread_self())) { ret = pthread_join(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, NULL); if (ret) { @@ -1198,6 +1202,22 @@ } } + // cancel inital thread last since after pthread_cancel() and + // pthread_join() is called on it, the whole process will appear to be + // a zombie. although it won't eliminate process zombie time, but it + // should minimize it. + if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[0].thread_id, pthread_self())) { + if (pthread_cancel(uwsgi.workers[uwsgi.mywid].cores[0].thread_id)) { + uwsgi_error("pthread_cancel() on initial thread\n"); + goto end; + } + + ret = pthread_join(uwsgi.workers[uwsgi.mywid].cores[0].thread_id, NULL); + if (ret) { + uwsgi_log("pthread_join() = %d on initial thread\n", ret); + } + } + end: pthread_mutex_unlock(&uwsgi.six_feet_under_lock); @@ -2544,6 +2564,11 @@ uwsgi_as_root(); } + // wait for socket + uwsgi_foreach(usl, uwsgi.wait_for_socket) { + if (uwsgi_wait_for_socket(usl->value)) exit(1); + } + if (uwsgi.logto2) { if (!uwsgi.is_a_reload || uwsgi.log_reopen) { logto(uwsgi.logto2); @@ -3212,6 +3237,24 @@ } +// this lives in a worker thread and periodically scans for memory usage +// when evil reloaders are in place +void *mem_collector(void *foobar) { + // block all signals + sigset_t smask; + sigfillset(&smask); + pthread_sigmask(SIG_BLOCK, &smask, NULL); + uwsgi_log_verbose("mem-collector thread started for worker %d\n", uwsgi.mywid); + for(;;) { + sleep(uwsgi.mem_collector_freq); + uint64_t rss, vsz; + get_memusage(&rss, &vsz); + uwsgi.workers[uwsgi.mywid].rss_size = rss; + uwsgi.workers[uwsgi.mywid].vsz_size = vsz; + } + return NULL; +} + int uwsgi_run() { // !!! from now on, we could be in the master or in a worker !!! @@ -3238,6 +3281,11 @@ } #endif + if (uwsgi.evil_reload_on_rss || uwsgi.evil_reload_on_as) { + pthread_t t; + pthread_create(&t, NULL, mem_collector, NULL); + } + // eventually maps (or disable) sockets for the worker uwsgi_map_sockets(); @@ -4415,6 +4463,7 @@ if (zerg == NULL) { uwsgi_log("--- invalid data received from zerg-server ---\n"); + close(zerg_fd); return -1; } @@ -4710,7 +4759,7 @@ char *uwsgi_get_dot_h() { char *src = uwsgi_dot_h; size_t len = strlen(src); - char *ptr = uwsgi_malloc(len / 2); + char *ptr = uwsgi_malloc((len / 2) + 1); char *base = ptr; size_t i; unsigned int u; @@ -4731,6 +4780,9 @@ base = ub->buf; ub->buf = NULL; uwsgi_buffer_destroy(ub); +#else + // add final null byte + *ptr = '\0'; #endif return base; } @@ -4743,7 +4795,7 @@ char *uwsgi_get_config_py() { char *src = uwsgi_config_py; size_t len = strlen(src); - char *ptr = uwsgi_malloc(len / 2); + char *ptr = uwsgi_malloc((len / 2) + 1); char *base = ptr; size_t i; unsigned int u; @@ -4764,6 +4816,9 @@ base = ub->buf; ub->buf = NULL; uwsgi_buffer_destroy(ub); +#else + // add final null byte + *ptr = '\0'; #endif return base; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/plugins/cgi/cgi_plugin.c new/uwsgi-2.0.11.1/plugins/cgi/cgi_plugin.c --- old/uwsgi-2.0.10/plugins/cgi/cgi_plugin.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/plugins/cgi/cgi_plugin.c 2015-07-19 08:17:07.000000000 +0200 @@ -533,9 +533,9 @@ memcpy(full_path, tmp_path, full_path_len+1); if (uwsgi_starts_with(full_path, full_path_len, docroot, docroot_len)) { + uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot); if (need_free) free(docroot); - uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot); return -1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/plugins/corerouter/corerouter.c new/uwsgi-2.0.11.1/plugins/corerouter/corerouter.c --- old/uwsgi-2.0.10/plugins/corerouter/corerouter.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/plugins/corerouter/corerouter.c 2015-07-19 08:17:07.000000000 +0200 @@ -95,7 +95,7 @@ if (peer->flush && !peer->is_flushing) { peer->is_flushing = 1; // on success, suspend the execution - if (peer->flush(peer) >= 0) return -1; + if (peer->flush(peer) > 0) return -1; } struct corerouter_peer *prev = peer->prev; struct corerouter_peer *next = peer->next; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/plugins/http/https.c new/uwsgi-2.0.11.1/plugins/http/https.c --- old/uwsgi-2.0.10/plugins/http/https.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/plugins/http/https.c 2015-07-19 08:17:07.000000000 +0200 @@ -320,7 +320,8 @@ } else if (err == SSL_ERROR_SYSCALL) { - uwsgi_cr_error(main_peer, "hr_ssl_write()"); + if (errno != 0) + uwsgi_cr_error(main_peer, "hr_ssl_write()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { @@ -380,7 +381,8 @@ } else if (err == SSL_ERROR_SYSCALL) { - uwsgi_cr_error(main_peer, "hr_ssl_read()"); + if (errno != 0) + uwsgi_cr_error(main_peer, "hr_ssl_read()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { @@ -420,7 +422,8 @@ } else if (err == SSL_ERROR_SYSCALL) { - uwsgi_cr_error(peer, "hr_ssl_shutdown()"); + if (errno != 0) + uwsgi_cr_error(peer, "hr_ssl_shutdown()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/plugins/psgi/psgi_loader.c new/uwsgi-2.0.11.1/plugins/psgi/psgi_loader.c --- old/uwsgi-2.0.10/plugins/psgi/psgi_loader.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/plugins/psgi/psgi_loader.c 2015-07-19 08:17:07.000000000 +0200 @@ -144,7 +144,7 @@ else { long orig_offset = 0; // first of all get the new orig_len; - offset = abs(offset); + offset = labs(offset); if (offset > (long) orig_len) { new_size = offset; orig_offset = offset - orig_len; @@ -285,7 +285,7 @@ uwsgi_log("[perl] WARNING !!! unable to build uwsgi::opt hash !!!\n"); goto end; } - if (SvTYPE(SvRV(*value)) == SVt_PVAV) { + if (SvROK(*value) && SvTYPE(SvRV(*value)) == SVt_PVAV) { if (uwsgi.exported_opts[i]->value == NULL) { av_push((AV *)SvRV(*value), newSViv(1)); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/plugins/pypy/pypy_setup.py new/uwsgi-2.0.11.1/plugins/pypy/pypy_setup.py --- old/uwsgi-2.0.10/plugins/pypy/pypy_setup.py 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/plugins/pypy/pypy_setup.py 2015-07-19 08:17:07.000000000 +0200 @@ -393,7 +393,7 @@ rlen = ffi.new('ssize_t*') chunk = lib.uwsgi_request_body_read(self.wsgi_req, size, rlen) if chunk != ffi.NULL: - return ffi.string(chunk, rlen[0]) + return ffi.buffer(chunk, rlen[0])[:] if rlen[0] < 0: raise IOError("error reading wsgi.input") raise IOError("error waiting for wsgi.input") @@ -402,7 +402,7 @@ rlen = ffi.new('ssize_t*') chunk = lib.uwsgi_request_body_readline(self.wsgi_req, hint, rlen) if chunk != ffi.NULL: - return ffi.string(chunk, rlen[0]) + return ffi.buffer(chunk, rlen[0])[:] if rlen[0] < 0: raise IOError("error reading line from wsgi.input") raise IOError("error waiting for line on wsgi.input") @@ -521,7 +521,7 @@ def __call__(self, argc, argv, argvs, buf): pargs = [] for i in range(0, argc): - pargs.append(ffi.string(argv[i], argvs[i])) + pargs.append(ffi.buffer(argv[i], argvs[i])[:]) response = self.func(*pargs) if len(response) > 0: buf[0] = lib.uwsgi_malloc(len(response)) @@ -560,7 +560,7 @@ response = lib.uwsgi_do_rpc(c_node, ffi.new("char[]",func), argc, argv, argvs, rsize) if response: - ret = ffi.string(response, rsize[0]) + ret = ffi.buffer(response, rsize[0])[:] lib.free(response) return ret return None @@ -587,7 +587,7 @@ value = lib.uwsgi_cache_magic_get(key, len(key), vallen, ffi.NULL, cache) if value == ffi.NULL: return None - ret = ffi.string(value, vallen[0]) + ret = ffi.buffer(value, vallen[0])[:] libc.free(value) return ret uwsgi.cache_get = uwsgi_pypy_uwsgi_cache_get @@ -617,8 +617,9 @@ uci = ffi.new('struct uwsgi_cache_item **') while True: uci[0] = lib.uwsgi_cache_keys(uc, pos, uci) - if uci[0] == ffi.NULL: break - l.append(ffi.string(lib.uwsgi_cache_item_key(uci[0]), uci[0].keysize)) + if uci[0] == ffi.NULL: + break + l.append(ffi.buffer(lib.uwsgi_cache_item_key(uci[0]), uci[0].keysize)[:]) lib.uwsgi_cache_rwunlock(uc) return l uwsgi.cache_keys = uwsgi_pypy_uwsgi_cache_keys @@ -849,7 +850,7 @@ ub = lib.uwsgi_websocket_recv(wsgi_req); if ub == ffi.NULL: raise IOError("unable to receive websocket message") - ret = ffi.string(ub.buf, ub.pos) + ret = ffi.buffer(ub.buf, ub.pos)[:] lib.uwsgi_buffer_destroy(ub) return ret uwsgi.websocket_recv = uwsgi_pypy_websocket_recv @@ -862,7 +863,7 @@ ub = lib.uwsgi_websocket_recv_nb(wsgi_req); if ub == ffi.NULL: raise IOError("unable to receive websocket message") - ret = ffi.string(ub.buf, ub.pos) + ret = ffi.buffer(ub.buf, ub.pos)[:] lib.uwsgi_buffer_destroy(ub) return ret uwsgi.websocket_recv_nb = uwsgi_pypy_websocket_recv_nb @@ -897,7 +898,7 @@ chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, timeout, 0) if chunk == ffi.NULL: raise IOError("unable to receive chunked part") - return ffi.string(chunk, rlen[0]) + return ffi.buffer(chunk, rlen[0])[:] uwsgi.chunked_read = uwsgi_pypy_chunked_read """ @@ -911,8 +912,7 @@ if lib.uwsgi_is_again() > 0: return None raise IOError("unable to receive chunked part") - - return ffi.string(chunk, rlen[0]) + return ffi.buffer(chunk, rlen[0])[:] uwsgi.chunked_read_nb = uwsgi_pypy_chunked_read_nb """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/plugins/python/python_plugin.c new/uwsgi-2.0.11.1/plugins/python/python_plugin.c --- old/uwsgi-2.0.10/plugins/python/python_plugin.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/plugins/python/python_plugin.c 2015-07-19 08:17:07.000000000 +0200 @@ -88,7 +88,7 @@ {"module", required_argument,'w', "load a WSGI module", uwsgi_opt_set_str, &up.wsgi_config, 0}, {"wsgi", required_argument, 'w', "load a WSGI module", uwsgi_opt_set_str, &up.wsgi_config, 0}, {"callable", required_argument, 0, "set default WSGI callable name", uwsgi_opt_set_str, &up.callable, 0}, - {"test", required_argument, 'J', "test a mdule import", uwsgi_opt_set_str, &up.test_module, 0}, + {"test", required_argument, 'J', "test a module import", uwsgi_opt_set_str, &up.test_module, 0}, {"home", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0}, {"virtualenv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0}, {"venv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0}, @@ -1670,6 +1670,8 @@ PyDict_SetItemString(spool_dict, "body", value); Py_DECREF(value); } + // PyTuple_SetItem steals a reference !!! + Py_INCREF(spool_dict); PyTuple_SetItem(pyargs, 0, spool_dict); ret = python_call(spool_func, pyargs, 0, NULL); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/plugins/python/uwsgi_pymodule.c new/uwsgi-2.0.11.1/plugins/python/uwsgi_pymodule.c --- old/uwsgi-2.0.10/plugins/python/uwsgi_pymodule.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/plugins/python/uwsgi_pymodule.c 2015-07-19 08:17:07.000000000 +0200 @@ -1448,6 +1448,72 @@ } +PyObject *py_uwsgi_sharedarea_inc32(PyObject * self, PyObject * args) { + int id; + uint64_t pos = 0; + int32_t value = 1; + + if (!PyArg_ParseTuple(args, "iL|i:sharedarea_inc32", &id, &pos, &value)) { + return NULL; + } + + UWSGI_RELEASE_GIL + int ret = uwsgi_sharedarea_inc32(id, pos, value); + UWSGI_GET_GIL + + if (ret) { + return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_inc32()"); + } + + Py_INCREF(Py_None); + return Py_None; + +} + +PyObject *py_uwsgi_sharedarea_dec64(PyObject * self, PyObject * args) { + int id; + uint64_t pos = 0; + int64_t value = 1; + + if (!PyArg_ParseTuple(args, "iL|l:sharedarea_dec64", &id, &pos, &value)) { + return NULL; + } + + UWSGI_RELEASE_GIL + int ret = uwsgi_sharedarea_dec64(id, pos, value); + UWSGI_GET_GIL + + if (ret) { + return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_dec64()"); + } + + Py_INCREF(Py_None); + return Py_None; + +} + +PyObject *py_uwsgi_sharedarea_dec32(PyObject * self, PyObject * args) { + int id; + uint64_t pos = 0; + int32_t value = 1; + + if (!PyArg_ParseTuple(args, "iL|i:sharedarea_dec32", &id, &pos, &value)) { + return NULL; + } + + UWSGI_RELEASE_GIL + int ret = uwsgi_sharedarea_dec32(id, pos, value); + UWSGI_GET_GIL + + if (ret) { + return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_dec32()"); + } + + Py_INCREF(Py_None); + return Py_None; + +} + PyObject *py_uwsgi_sharedarea_write32(PyObject * self, PyObject * args) { int id; uint64_t pos = 0; @@ -2569,6 +2635,9 @@ {"sharedarea_write16", py_uwsgi_sharedarea_write16, METH_VARARGS, ""}, {"sharedarea_inclong", py_uwsgi_sharedarea_inc64, METH_VARARGS, ""}, {"sharedarea_inc64", py_uwsgi_sharedarea_inc64, METH_VARARGS, ""}, + {"sharedarea_inc32", py_uwsgi_sharedarea_inc32, METH_VARARGS, ""}, + {"sharedarea_dec64", py_uwsgi_sharedarea_dec64, METH_VARARGS, ""}, + {"sharedarea_dec32", py_uwsgi_sharedarea_dec32, METH_VARARGS, ""}, {"sharedarea_rlock", py_uwsgi_sharedarea_rlock, METH_VARARGS, ""}, {"sharedarea_wlock", py_uwsgi_sharedarea_wlock, METH_VARARGS, ""}, {"sharedarea_unlock", py_uwsgi_sharedarea_unlock, METH_VARARGS, ""}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/plugins/sslrouter/sslrouter.c new/uwsgi-2.0.11.1/plugins/sslrouter/sslrouter.c --- old/uwsgi-2.0.10/plugins/sslrouter/sslrouter.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/plugins/sslrouter/sslrouter.c 2015-07-19 08:17:07.000000000 +0200 @@ -250,7 +250,8 @@ } else if (err == SSL_ERROR_SYSCALL) { - uwsgi_cr_error(main_peer, "sr_write()"); + if (errno != 0) + uwsgi_cr_error(main_peer, "sr_write()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { @@ -332,7 +333,8 @@ } else if (err == SSL_ERROR_SYSCALL) { - uwsgi_cr_error(main_peer, "sr_ssl_read()"); + if (errno != 0) + uwsgi_cr_error(main_peer, "sr_ssl_read()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/plugins/transformation_gzip/gzip.c new/uwsgi-2.0.11.1/plugins/transformation_gzip/gzip.c --- old/uwsgi-2.0.10/plugins/transformation_gzip/gzip.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/plugins/transformation_gzip/gzip.c 2015-07-19 08:17:07.000000000 +0200 @@ -24,7 +24,7 @@ struct uwsgi_buffer *ub = ut->chunk; if (ut->is_final) { - if (uwsgi_gzip_fix(&utgz->z, utgz->crc32, ub, utgz->len)) { + if (utgz->len > 0 && uwsgi_gzip_fix(&utgz->z, utgz->crc32, ub, utgz->len)) { free(utgz); return -1; } @@ -32,6 +32,11 @@ return 0; } + if (ub->pos == 0) { + // Don't try to compress empty responses. + return 0; + } + size_t dlen = 0; char *gzipped = uwsgi_gzip_chunk(&utgz->z, &utgz->crc32, ub->buf, ub->pos, &dlen); if (!gzipped) return -1; @@ -39,7 +44,7 @@ uwsgi_buffer_map(ub, gzipped, dlen); if (!utgz->header) { // do not check for errors !!! - uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4); + uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4); utgz->header = 1; if (uwsgi_buffer_insert(ub, 0, gzheader, 10)) { return -1; @@ -59,7 +64,7 @@ ut->can_stream = 1; // this is the trasformation clearing the memory ut = uwsgi_add_transformation(wsgi_req, transform_gzip, utgz); - ut->is_final = 1; + ut->is_final = 1; return UWSGI_ROUTE_NEXT; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/proto/base.c new/uwsgi-2.0.11.1/proto/base.c --- old/uwsgi-2.0.10/proto/base.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/proto/base.c 2015-07-19 08:17:07.000000000 +0200 @@ -287,7 +287,8 @@ } else if (err == SSL_ERROR_SYSCALL) { - uwsgi_error("uwsgi_proto_ssl_write()/SSL_write()"); + if (errno != 0) + uwsgi_error("uwsgi_proto_ssl_write()/SSL_write()"); } return -1; @@ -383,7 +384,8 @@ } else if (err == SSL_ERROR_SYSCALL) { - uwsgi_error("uwsgi_proto_ssl_read_body()/SSL_read()"); + if (errno != 0) + uwsgi_error("uwsgi_proto_ssl_read_body()/SSL_read()"); } return -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/proto/http.c new/uwsgi-2.0.11.1/proto/http.c --- old/uwsgi-2.0.10/proto/http.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/proto/http.c 2015-07-19 08:17:07.000000000 +0200 @@ -760,7 +760,8 @@ } else if (err == SSL_ERROR_SYSCALL) { - uwsgi_error("uwsgi_proto_https_parser()/SSL_read()"); + if (errno != 0) + uwsgi_error("uwsgi_proto_https_parser()/SSL_read()"); } return -1; empty: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/proto/uwsgi.c new/uwsgi-2.0.11.1/proto/uwsgi.c --- old/uwsgi-2.0.10/proto/uwsgi.c 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/proto/uwsgi.c 2015-07-19 08:17:07.000000000 +0200 @@ -83,7 +83,8 @@ } else if (err == SSL_ERROR_SYSCALL) { - uwsgi_error("uwsgi_proto_suwsgi_parser()/SSL_read()"); + if (errno != 0) + uwsgi_error("uwsgi_proto_suwsgi_parser()/SSL_read()"); } return -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/t/sharedarea/bigranges.ini new/uwsgi-2.0.11.1/t/sharedarea/bigranges.ini --- old/uwsgi-2.0.10/t/sharedarea/bigranges.ini 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.11.1/t/sharedarea/bigranges.ini 2015-07-19 08:17:07.000000000 +0200 @@ -0,0 +1,6 @@ +[uwsgi] +socket = /tmp/foo + +sharedarea = size=4300000000 + +pyrun = t/sharedarea/%n.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/t/sharedarea/bigranges.py new/uwsgi-2.0.11.1/t/sharedarea/bigranges.py --- old/uwsgi-2.0.10/t/sharedarea/bigranges.py 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.11.1/t/sharedarea/bigranges.py 2015-07-19 08:17:07.000000000 +0200 @@ -0,0 +1,16 @@ +import uwsgi +import unittest + +class SharedareaTest(unittest.TestCase): + + def test_32(self): + pos = 2L * (1024L ** 3) + uwsgi.sharedarea_write32(0, pos, 17) + self.assertEqual(uwsgi.sharedarea_read32(0, pos), 17) + + def test_64(self): + pos = 2L * (1024L ** 3) + uwsgi.sharedarea_write64(0, pos, 30) + self.assertEqual(uwsgi.sharedarea_read64(0, pos), 30) + +unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/t/sharedarea/sharedarea_incdec.ini new/uwsgi-2.0.11.1/t/sharedarea/sharedarea_incdec.ini --- old/uwsgi-2.0.10/t/sharedarea/sharedarea_incdec.ini 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.11.1/t/sharedarea/sharedarea_incdec.ini 2015-07-19 08:17:07.000000000 +0200 @@ -0,0 +1,6 @@ +[uwsgi] +socket = /tmp/foo + +sharedarea = size=64 + +pyrun = t/sharedarea/%n.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/t/sharedarea/sharedarea_incdec.py new/uwsgi-2.0.11.1/t/sharedarea/sharedarea_incdec.py --- old/uwsgi-2.0.10/t/sharedarea/sharedarea_incdec.py 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.11.1/t/sharedarea/sharedarea_incdec.py 2015-07-19 08:17:07.000000000 +0200 @@ -0,0 +1,34 @@ +import uwsgi +import unittest + +class SharedareaTest(unittest.TestCase): + + def setUp(self): + uwsgi.sharedarea_write(0, 0, '\0' * 64) + + def test_32(self): + uwsgi.sharedarea_write32(0, 0, 17) + self.assertEqual(uwsgi.sharedarea_read32(0, 0), 17) + + def test_inc32(self): + uwsgi.sharedarea_write32(0, 4, 30) + uwsgi.sharedarea_inc32(0, 4, 3) + self.assertEqual(uwsgi.sharedarea_read32(0, 4), 33) + + def test_dec32(self): + uwsgi.sharedarea_write32(0, 5, 30) + uwsgi.sharedarea_dec32(0, 5, 4) + self.assertEqual(uwsgi.sharedarea_read32(0, 5), 26) + + def test_inc64(self): + uwsgi.sharedarea_write64(0, 8, 17 * (1024 ** 5)) + uwsgi.sharedarea_inc64(0, 8, 1) + self.assertEqual(uwsgi.sharedarea_read64(0, 8), 17 * (1024 ** 5) + 1) + + def test_dec64(self): + uwsgi.sharedarea_write64(0, 8, 30 * (1024 ** 5)) + uwsgi.sharedarea_dec64(0, 8, 30 * (1024 ** 5) - 1) + self.assertEqual(uwsgi.sharedarea_read64(0, 8), 1) + + +unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/uwsgi.gemspec new/uwsgi-2.0.11.1/uwsgi.gemspec --- old/uwsgi-2.0.10/uwsgi.gemspec 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/uwsgi.gemspec 2015-07-19 08:17:07.000000000 +0200 @@ -2,7 +2,7 @@ s.name = 'uwsgi' s.license = 'GPL-2' s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'') - s.date = '2015-03-17' + s.date = '2015-07-19' s.summary = "uWSGI" s.description = "The uWSGI server for Ruby/Rack" s.authors = ["Unbit"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/uwsgi.h new/uwsgi-2.0.11.1/uwsgi.h --- old/uwsgi-2.0.10/uwsgi.h 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/uwsgi.h 2015-07-19 08:17:07.000000000 +0200 @@ -2760,6 +2760,11 @@ // uWSGI 2.0.10 struct uwsgi_string_list *emperor_wrapper_override; struct uwsgi_string_list *emperor_wrapper_fallback; + + // uWSGI 2.0.11 + struct uwsgi_string_list *wait_for_socket; + int wait_for_socket_timeout; + int mem_collector_freq; }; struct uwsgi_rpc { @@ -3469,6 +3474,7 @@ struct uwsgi_socket *uwsgi_del_socket(struct uwsgi_socket *); void uwsgi_close_all_sockets(void); +void uwsgi_close_all_unshared_sockets(void); struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **, char *); #ifdef UWSGI_PCRE @@ -4852,6 +4858,7 @@ int uwsgi_wait_for_fs(char *, int); int uwsgi_wait_for_mountpoint(char *); +int uwsgi_wait_for_socket(char *); #ifdef __cplusplus } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.10/uwsgiconfig.py new/uwsgi-2.0.11.1/uwsgiconfig.py --- old/uwsgi-2.0.10/uwsgiconfig.py 2015-03-17 08:34:34.000000000 +0100 +++ new/uwsgi-2.0.11.1/uwsgiconfig.py 2015-07-19 08:17:07.000000000 +0200 @@ -1,6 +1,6 @@ # uWSGI build system -uwsgi_version = '2.0.10' +uwsgi_version = '2.0.11.1' import os import re @@ -689,8 +689,13 @@ print("detected include path: %s" % self.include_path) try: - gcc_major = int(gcc_version.split('.')[0]) - gcc_minor = int(gcc_version.split('.')[1]) + gcc_version_components = gcc_version.split('.') + gcc_major = int(gcc_version_components[0]) + if len(gcc_version_components) > 1: + gcc_minor = int(gcc_version_components[1]) + else: + # gcc 5.0 is represented as simply "5" + gcc_minor = 0 except: raise Exception("you need a C compiler to build uWSGI") if (sys.version_info[0] == 2) or (gcc_major < 4) or (gcc_major == 4 and gcc_minor < 3): @@ -768,7 +773,7 @@ if 'UWSGI_PROFILE_OVERRIDE' in os.environ: for item in os.environ['UWSGI_PROFILE_OVERRIDE'].split(';'): - k,v = item.split('=', 2) + k,v = item.split('=', 1) self.set(k, v) if 'UWSGI_AS_LIB' in os.environ:
