Hello community, here is the log from the commit of package uwsgi for openSUSE:Factory checked in at 2014-04-09 13:17:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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 2014-03-28 16:29:12.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.uwsgi.new/uwsgi.changes 2014-04-09 13:17:41.000000000 +0200 @@ -1,0 +2,31 @@ +Sat Mar 29 17:28:02 UTC 2014 - jf...@funktronics.ca + +- Update to 2.0.3: + * Bugfixes + * fixed spooler 'at' key usage + * fixed a memory and fd leak with on-demand Emperor sockets + * on __APPLE__ use LOG_NOTICE for syslog plugin + * fixed mongrel2 support + * hack for avoiding libmongoclient to crash on broken cursor + * log alarm is now a uwsgi_log_verbose() wrapper + * fixed tuntap router memory corruption + * Set ECDHE curve independently from DHE parameters (Hynek Schlawack) + * do not wait for a whole Emperor cycle before checking for each waitpid + * fix a regression with caller() not indicating the starting *.psgi program + (Ævar Arnfjörð Bjarmason) + * New features + * The Emperor now responds to two new signals: + * SIGWINCH: force an emperor rescan of vassals + * SIGURG: cleanup the Emperor states (for now it only clears its blacklist) + * --build-plugin. Building plugins on-the-fly from git repositories + * uwsgi.add_var(key, value). You can now set request variables directly + from your app, for better integration with the internal routing + subsystem + * 'disableheaders' routing action. This new action disables the sending of + response headers, independently by the current request state + * Smarter Emperor on bad conditions. Now the Emperor completely destroys + internal vassal-related structures when it is impossible to correctly + kill a broken vassal (both for inconsistent Emperor state or for + internal system problems) + +------------------------------------------------------------------- @@ -4 +35 @@ -- Update to 2.0.1: +- Update to 2.0.2: Old: ---- uwsgi-2.0.2.tar.gz New: ---- uwsgi-2.0.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ uwsgi.spec ++++++ --- /var/tmp/diff_new_pack.jQl7rt/_old 2014-04-09 13:17:42.000000000 +0200 +++ /var/tmp/diff_new_pack.jQl7rt/_new 2014-04-09 13:17:42.000000000 +0200 @@ -17,7 +17,7 @@ Name: uwsgi -Version: 2.0.2 +Version: 2.0.3 Release: 0 Summary: Application Container Server for Networked/Clustered Web Applications License: GPL-2.0-with-GCC-exception ++++++ uwsgi-2.0.2.tar.gz -> uwsgi-2.0.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/.gitignore new/uwsgi-2.0.3/.gitignore --- old/uwsgi-2.0.2/.gitignore 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/.gitignore 2014-03-17 06:33:04.000000000 +0100 @@ -7,6 +7,7 @@ /uwsgi /uwsgibuild.* +/core/config_py.c /t/ring/target diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/CONTRIBUTORS new/uwsgi-2.0.3/CONTRIBUTORS --- old/uwsgi-2.0.2/CONTRIBUTORS 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/CONTRIBUTORS 2014-03-17 06:33:04.000000000 +0100 @@ -26,3 +26,4 @@ Roberto Leandrini Ryan Petrello Danila Shtan <dan...@shtan.ru> +Ævar Arnfjörð Bjarmason diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/core/alarm.c new/uwsgi-2.0.3/core/alarm.c --- old/uwsgi-2.0.2/core/alarm.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/core/alarm.c 2014-03-17 06:33:04.000000000 +0100 @@ -18,18 +18,18 @@ void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) { if (msg[len-1] != '\n') { if (uai->arg && strlen(uai->arg) > 0) { - uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg); + uwsgi_log_verbose("ALARM: %s %.*s\n", uai->arg, len, msg); } else { - uwsgi_log_alarm("] %.*s\n", len, msg); + uwsgi_log_verbose("ALARM: %.*s\n", len, msg); } } else { if (uai->arg && strlen(uai->arg) > 0) { - uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg); + uwsgi_log_verbose("ALARM: %s %.*s", uai->arg, len, msg); } else { - uwsgi_log_alarm("] %.*s", len, msg); + uwsgi_log_verbose("ALARM: %.*s", len, msg); } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/core/emperor.c new/uwsgi-2.0.3/core/emperor.c --- old/uwsgi-2.0.2/core/emperor.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/core/emperor.c 2014-03-17 06:33:04.000000000 +0100 @@ -39,6 +39,70 @@ struct uwsgi_emperor_blacklist_item *emperor_blacklist; +/* +this should be placed in core/socket.c but we realized it was needed +only after 2.0 so we cannot change uwsgi.h + +basically it is a stripped down bind_to_tcp/bind_to_unix with rollback +*/ +static int on_demand_bind(char *socket_name) { + union uwsgi_sockaddr us; + socklen_t addr_len = sizeof(struct sockaddr_un); + char *is_tcp = strchr(socket_name, ':'); + int af_family = is_tcp ? AF_INET : AF_UNIX; + int fd = socket(af_family, SOCK_STREAM, 0); + if (fd < 0) return -1; + + memset(&us, 0, sizeof(union uwsgi_sockaddr)); + + if (is_tcp) { + int reuse = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) { + goto error; + } + us.sa_in.sin_family = AF_INET; + us.sa_in.sin_port = htons(atoi(is_tcp+1)); + *is_tcp = 0; + if (socket_name[0] != 0) { + us.sa_in.sin_addr.s_addr = inet_addr(socket_name); + } + else { + us.sa_in.sin_addr.s_addr = INADDR_ANY; + } + *is_tcp = ':'; + addr_len = sizeof(struct sockaddr_in); + } + else { + if (unlink(socket_name) != 0 && errno != ENOENT) { + goto error; + } + + us.sa_un.sun_family = AF_UNIX; + memcpy(us.sa_un.sun_path, socket_name, UMIN(strlen(socket_name), 102)); + addr_len = strlen(socket_name) + ((void *) us.sa_un.sun_path - (void *) &us.sa_un); + } + + if (bind(fd, (struct sockaddr *) &us, addr_len) != 0) { + goto error; + } + + if (!is_tcp) { + if (chmod(socket_name, 0666)) { + goto error; + } + } + + if (listen(fd, uwsgi.listen_queue) != 0) { + goto error; + } + + return fd; + +error: + close(fd); + return -1; +} + struct uwsgi_emperor_blacklist_item *uwsgi_emperor_blacklist_check(char *id) { struct uwsgi_emperor_blacklist_item *uebi = emperor_blacklist; while (uebi) { @@ -157,7 +221,7 @@ if (fd < 0) return NULL; char *ret = uwsgi_read_fd(fd, &len, 1); close(fd); - // change the first non prinabel character to 0 + // change the first non printable character to 0 size_t i; for(i=0;i<len;i++) { if (ret[i] < 32) { @@ -629,6 +693,10 @@ free(c_ui->socket_name); } + if (c_ui->on_demand_fd != -1) { + close(c_ui->on_demand_fd); + } + free(c_ui); } @@ -637,8 +705,10 @@ if (c_ui->status == 1) return; // remove uWSGI instance - if (write(c_ui->pipe[0], "\0", 1) != 1) { - uwsgi_error("emperor_stop()/write()"); + if (c_ui->pid != -1) { + if (write(c_ui->pipe[0], "\0", 1) != 1) { + uwsgi_error("emperor_stop()/write()"); + } } c_ui->status = 1; @@ -658,10 +728,27 @@ } +// send configuration (if required to the vassal) +static void emperor_push_config(struct uwsgi_instance *c_ui) { + struct uwsgi_header uh; + + if (c_ui->use_config) { + uh.modifier1 = 115; + uh.pktsize = c_ui->config_len; + uh.modifier2 = 0; + if (write(c_ui->pipe_config[0], &uh, 4) != 4) { + uwsgi_error("[uwsgi-emperor] write() header config"); + } + else { + if (write(c_ui->pipe_config[0], c_ui->config, c_ui->config_len) != (long) c_ui->config_len) { + uwsgi_error("[uwsgi-emperor] write() config"); + } + } + } +} void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) { - struct uwsgi_header uh; // reload the uWSGI instance if (write(c_ui->pipe[0], "\1", 1) != 1) { @@ -669,20 +756,7 @@ } // push the config to the config pipe (if needed) - if (c_ui->use_config) { - uh.modifier1 = 115; - uh.pktsize = c_ui->config_len; - uh.modifier2 = 0; - if (write(c_ui->pipe_config[0], &uh, 4) != 4) { - uwsgi_error("[uwsgi-emperor] write() header config"); - } - else { - if (write(c_ui->pipe_config[0], c_ui->config, c_ui->config_len) != (long) c_ui->config_len) { - uwsgi_error("[uwsgi-emperor] write() config"); - } - } - } - + emperor_push_config(c_ui); c_ui->respawns++; c_ui->last_mod = mod; @@ -794,21 +868,12 @@ } n_ui->pid = -1; + n_ui->pipe[0] = -1; + n_ui->pipe[1] = -1; // ok here we check if we need to bind to the specified socket or continue with the activation if (socket_name) { - char *tcp_port = strchr(socket_name, ':'); - if (tcp_port) { - // disable deferred accept for this socket - int current_defer_accept = uwsgi.no_defer_accept; - uwsgi.no_defer_accept = 1; - n_ui->on_demand_fd = bind_to_tcp(socket_name, uwsgi.listen_queue, tcp_port); - uwsgi.no_defer_accept = current_defer_accept; - } - else { - n_ui->on_demand_fd = bind_to_unix(socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket); - } - + n_ui->on_demand_fd = on_demand_bind(socket_name); if (n_ui->on_demand_fd < 0) { uwsgi_error("emperor_add()/bind()"); free(n_ui); @@ -838,6 +903,7 @@ uwsgi_error("socketpair()"); return -1; } + uwsgi_socket_nb(n_ui->pipe[0]); event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->pipe[0]); @@ -846,6 +912,7 @@ uwsgi_error("socketpair()"); return -1; } + uwsgi_socket_nb(n_ui->pipe_config[0]); } if (n_ui->zerg) { @@ -1452,6 +1519,17 @@ } +static void emperor_wakeup(int sn) {} + +static void emperor_cleanup() { + uwsgi_log_verbose("[uwsgi-emperor] cleaning up blacklist ...\n"); + struct uwsgi_instance *ui_current = ui; + while (ui_current->ui_next) { + uwsgi_emperor_blacklist_remove(ui_current->name); + ui_current = ui_current->ui_next; + } +} + void emperor_loop() { // monitor a directory @@ -1480,11 +1558,13 @@ } signal(SIGPIPE, SIG_IGN); + signal(SIGWINCH, emperor_wakeup); uwsgi_unix_signal(SIGINT, royal_death); uwsgi_unix_signal(SIGTERM, royal_death); uwsgi_unix_signal(SIGQUIT, royal_death); uwsgi_unix_signal(SIGUSR1, emperor_stats); uwsgi_unix_signal(SIGHUP, emperor_massive_reload); + uwsgi_unix_signal(SIGURG, emperor_cleanup); memset(&ui_base, 0, sizeof(struct uwsgi_instance)); @@ -1552,7 +1632,11 @@ ui_current = ui->ui_next; while (ui_current) { uwsgi_log_verbose("[emperor] NO MERCY for vassal %s !!!\n", ui_current->name); - kill(ui_current->pid, SIGKILL); + if (kill(ui_current->pid, SIGKILL) < 0) { + uwsgi_error("[emperor] kill()"); + emperor_del(ui_current); + break; + } ui_current = ui_current->ui_next; } break; @@ -1635,6 +1719,9 @@ ui_current->last_ready = uwsgi_now(); uwsgi_log_verbose("[emperor] vassal %s has been spawned\n", ui_current->name); } + else if (byte == 2) { + emperor_push_config(ui_current); + } } } else { @@ -1667,8 +1754,10 @@ // set last_heartbeat to 0 avoiding races ui_current->last_heartbeat = 0; if (ui_current->pid > 0) { - if (kill(ui_current->pid, SIGKILL)) { + if (kill(ui_current->pid, SIGKILL) < 0) { uwsgi_error("[emperor] kill()"); + emperor_del(ui_current); + break; } } } @@ -1676,6 +1765,8 @@ ui_current = ui_current->ui_next; } + +recheck: // check for removed instances ui_current = ui; has_children = 0; @@ -1720,7 +1811,7 @@ while (ui_current->ui_next) { ui_current = ui_current->ui_next; time_t now = uwsgi_now(); - if (ui_current->pid == diedpid) { + if (diedpid > 0 && ui_current->pid == diedpid) { if (ui_current->status == 0) { // respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) { @@ -1743,15 +1834,26 @@ break; } } - else if (ui_current->cursed_at > 0 && now - ui_current->cursed_at >= uwsgi.emperor_curse_tolerance) { - ui_current->cursed_at = now; - if (kill(ui_current->pid, SIGKILL)) { - uwsgi_error("[emperor] kill"); + else if (ui_current->cursed_at > 0) { + if (ui_current->pid == -1) { + emperor_del(ui_current); + break; + } + else if (now - ui_current->cursed_at >= uwsgi.emperor_curse_tolerance) { + ui_current->cursed_at = now; + if (kill(ui_current->pid, SIGKILL) < 0) { + uwsgi_error("[emperor] kill()"); + // delete the vassal, something is seriously wrong better to not leak memory... + emperor_del(ui_current); + } + break; } - break; } } + // if waitpid returned an item, let's check for another (potential) one + if (diedpid > 0) goto recheck; + } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/core/fifo.c new/uwsgi-2.0.3/core/fifo.c --- old/uwsgi-2.0.2/core/fifo.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/core/fifo.c 2014-03-17 06:33:04.000000000 +0100 @@ -48,6 +48,14 @@ } } +static void emperor_rescan() { + if (uwsgi.emperor_pid > 0) { + if (kill(uwsgi.emperor_pid, SIGWINCH)) { + uwsgi_error("emperor_rescan()/kill()"); + } + } +} + /* this is called as soon as possibile allowing plugins (or hooks) to override it @@ -74,6 +82,7 @@ uwsgi_fifo_table['+'] = uwsgi_cheaper_increase; uwsgi_fifo_table['c'] = uwsgi_chain_reload; uwsgi_fifo_table['C'] = uwsgi_go_cheap; + uwsgi_fifo_table['E'] = emperor_rescan; uwsgi_fifo_table['f'] = uwsgi_refork_master; uwsgi_fifo_table['l'] = uwsgi_log_reopen; uwsgi_fifo_table['L'] = uwsgi_log_rotate; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/core/master_utils.c new/uwsgi-2.0.3/core/master_utils.c --- old/uwsgi-2.0.2/core/master_utils.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/core/master_utils.c 2014-03-17 06:33:04.000000000 +0100 @@ -412,9 +412,17 @@ uwsgi_log("fork()'ing uWSGI...\n"); } + // ask for configuration (if needed) + if (uwsgi.has_emperor && uwsgi.emperor_fd_config > -1) { + char byte = 2; + if (write(uwsgi.emperor_fd, &byte, 1) != 1) { + uwsgi_error("uwsgi_reload()/write()"); + } + } + uwsgi_log("chdir() to %s\n", uwsgi.cwd); if (chdir(uwsgi.cwd)) { - uwsgi_error("chdir()"); + uwsgi_error("uwsgi_reload()/chdir()"); } /* check fd table (a module can obviosly open some fd on initialization...) */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/core/routing.c new/uwsgi-2.0.3/core/routing.c --- old/uwsgi-2.0.2/core/routing.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/core/routing.c 2014-03-17 06:33:04.000000000 +0100 @@ -943,6 +943,20 @@ return 0; } +// disable headers +static int uwsgi_router_disableheaders_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) { + wsgi_req->headers_sent = 1; + return UWSGI_ROUTE_NEXT; +} + +static int uwsgi_router_disableheaders(struct uwsgi_route *ur, char *arg) { + ur->func = uwsgi_router_disableheaders_func; + ur->data = arg; + ur->data_len = strlen(arg); + return 0; +} + + // signal route static int uwsgi_router_signal_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) { @@ -1737,6 +1751,7 @@ uwsgi_register_router("remheader", uwsgi_router_remheader); uwsgi_register_router("clearheaders", uwsgi_router_clearheaders); uwsgi_register_router("resetheaders", uwsgi_router_clearheaders); + uwsgi_register_router("disableheaders", uwsgi_router_disableheaders); uwsgi_register_router("signal", uwsgi_router_signal); uwsgi_register_router("send", uwsgi_router_send); uwsgi_register_router("send-crnl", uwsgi_router_send_crnl); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/core/spooler.c new/uwsgi-2.0.3/core/spooler.c --- old/uwsgi-2.0.2/core/spooler.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/core/spooler.c 2014-03-17 06:33:04.000000000 +0100 @@ -190,6 +190,11 @@ } if (!uwsgi_strncmp(key, key_len, "at", 2)) { + // at can be a float... + char *dot = memchr(value, '.', value_len); + if (dot) { + value_len = dot - value; + } sr->at = uwsgi_str_num(value, value_len); return; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/core/ssl.c new/uwsgi-2.0.3/core/ssl.c --- old/uwsgi-2.0.2/core/ssl.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/core/ssl.c 2014-03-17 06:33:04.000000000 +0100 @@ -245,17 +245,19 @@ if (dh) { SSL_CTX_set_tmp_dh(ctx, dh); DH_free(dh); + } + } #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH #ifdef NID_X9_62_prime256v1 - EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - SSL_CTX_set_tmp_ecdh(ctx, ecdh); - EC_KEY_free(ecdh); + EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (ecdh) { + SSL_CTX_set_tmp_ecdh(ctx, ecdh); + EC_KEY_free(ecdh); + } #endif #endif #endif - } - } if (crt_need_free) free(crt); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/core/websockets.c new/uwsgi-2.0.3/core/websockets.c --- old/uwsgi-2.0.2/core/websockets.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/core/websockets.c 2014-03-17 06:33:04.000000000 +0100 @@ -1,4 +1,4 @@ -#include "uwsgi.h" +#include <uwsgi.h> /* @@ -10,6 +10,8 @@ extern struct uwsgi_server uwsgi; +#define REQ_DATA wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr + static struct uwsgi_buffer *uwsgi_websocket_message(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) { struct uwsgi_buffer *ub = wsgi_req->websocket_send_buf; if (!ub) { @@ -61,7 +63,7 @@ // pong not received ? if (wsgi_req->websocket_last_pong < wsgi_req->websocket_last_ping) { if (wsgi_req->websocket_last_ping - wsgi_req->websocket_last_pong > uwsgi.websockets_pong_tolerance) { - uwsgi_log("[uwsgi-websocket] no PONG received in %d seconds !!!\n", uwsgi.websockets_pong_tolerance); + uwsgi_log("[uwsgi-websocket] \"%.*s %.*s\" (%.*s) no PONG received in %d seconds !!!\n", REQ_DATA, uwsgi.websockets_pong_tolerance); return -1; } return 0; @@ -189,7 +191,7 @@ } goto wait; } - uwsgi_error("uwsgi_websockets_recv_pkt()"); + uwsgi_req_error("uwsgi_websockets_recv_pkt()"); return -1; } @@ -201,7 +203,7 @@ if (rlen <= 0) return -1; } if (ret < 0) { - uwsgi_error("uwsgi_websockets_recv_pkt()"); + uwsgi_req_error("uwsgi_websockets_recv_pkt()"); return -1; } // send unsolicited pong @@ -254,11 +256,11 @@ wsgi_req->websocket_size = uwsgi_be64(wsgi_req->websocket_buf->buf+2); } else { - uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n"); + uwsgi_log("[uwsgi-websocket] \"%.*s %.*s\" (%.*s) BUG error in websocket parser\n", REQ_DATA); return NULL; } if (wsgi_req->websocket_size > (uwsgi.websockets_max_size*1024)) { - uwsgi_log("[uwsgi-websocket] invalid packet size received: %llu, max allowed: %llu\n", wsgi_req->websocket_size, uwsgi.websockets_max_size * 1024); + uwsgi_log("[uwsgi-websocket] \"%.*s %.*s\" (%.*s) invalid packet size received: %llu, max allowed: %llu\n", REQ_DATA, wsgi_req->websocket_size, uwsgi.websockets_max_size * 1024); return NULL; } wsgi_req->websocket_phase = 2; @@ -312,7 +314,7 @@ break; // oops default: - uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n"); + uwsgi_log("[uwsgi-websocket] \"%.*s %.*s\" (%.*s) BUG error in websocket parser\n", REQ_DATA); return NULL; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/corerouter/cr.h new/uwsgi-2.0.3/plugins/corerouter/cr.h --- old/uwsgi-2.0.2/plugins/corerouter/cr.h 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/corerouter/cr.h 2014-03-17 06:33:04.000000000 +0100 @@ -7,8 +7,8 @@ #define cr_add_timeout_fast(u, x, t) uwsgi_add_rb_timer(u->timeouts, t+u->socket_timeout, x) #define cr_del_timeout(u, x) uwsgi_del_rb_timer(u->timeouts, x->timeout); free(x->timeout); -#define uwsgi_cr_error(x, y) uwsgi_log("[uwsgi-%s client_addr: %s client_port: %s] %s: %s [%s line %d]\n", x->session->corerouter->short_name, x->session->client_address, x->session->client_port, y, strerror(errno), __FILE__, __LINE__) -#define uwsgi_cr_log(x, y, ...) uwsgi_log("[uwsgi-%s client_addr: %s client_port: %s]" y, x->session->corerouter->short_name, x->session->client_address, x->session->client_port, __VA_ARGS__) +#define uwsgi_cr_error(x, y) uwsgi_log("[uwsgi-%s key: %.*s client_addr: %s client_port: %s] %s: %s [%s line %d]\n", x->session->corerouter->short_name, x->session->main_peer ? x->session->main_peer->key_len : 0, x->session->main_peer ? x->session->main_peer->key: "", x->session->client_address, x->session->client_port, y, strerror(errno), __FILE__, __LINE__) +#define uwsgi_cr_log(x, y, ...) uwsgi_log("[uwsgi-%s key: %.*s client_addr: %s client_port: %s]" y, x->session->corerouter->short_name, x->session->main_peer ? x->session->main_peer->key_len : 0, x->session->main_peer ? x->session->main_peer->key : "", x->session->client_address, x->session->client_port, __VA_ARGS__) #define cr_try_again if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {\ errno = EINPROGRESS;\ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/emperor_mongodb/emperor_mongodb.cc new/uwsgi-2.0.3/plugins/emperor_mongodb/emperor_mongodb.cc --- old/uwsgi-2.0.2/plugins/emperor_mongodb/emperor_mongodb.cc 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/emperor_mongodb/emperor_mongodb.cc 2014-03-17 06:33:04.000000000 +0100 @@ -20,7 +20,7 @@ try { // requested fields - mongo::BSONObj p = BSON( "name" << 1 << "config" << 1 << "ts" << 1 << "uid" << 1 << "gid" << 1 ); + mongo::BSONObj p = BSON( "name" << 1 << "config" << 1 << "ts" << 1 << "uid" << 1 << "gid" << 1 << "socket" << 1 ); mongo::BSONObj q = mongo::fromjson(uems->json); // the connection object (will be automatically destroyed at each cycle) mongo::DBClientConnection c; @@ -31,7 +31,7 @@ // run the query std::auto_ptr<mongo::DBClientCursor> cursor = c.query(uems->collection, q, 0, 0, &p); - while( cursor->more() ) { + while(cursor.get() && cursor->more() ) { mongo::BSONObj p = cursor->next(); // checking for an empty string is not required, but we reduce the load @@ -40,6 +40,7 @@ if (strlen(name) == 0) continue; const char *config = p.getStringField("config"); + if (strlen(config) == 0) config = NULL; time_t vassal_ts = 0; // ts must be a Date object !!! @@ -61,6 +62,7 @@ } const char *socket_name = p.getStringField("socket"); + if (strlen(socket_name) == 0) socket_name = NULL; uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid, (char *) socket_name); } @@ -76,6 +78,7 @@ b.append("name", c_ui->name); mongo::BSONObj q2 = b.obj(); cursor = c.query(uems->collection, q2, 0, 0, &p); + if (!cursor.get()) return; #ifdef UWSGI_DEBUG uwsgi_log("JSON: %s\n", q2.toString().c_str()); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/mongrel2/mongrel2.c new/uwsgi-2.0.3/plugins/mongrel2/mongrel2.c --- old/uwsgi-2.0.2/plugins/mongrel2/mongrel2.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/mongrel2/mongrel2.c 2014-03-17 06:33:04.000000000 +0100 @@ -102,6 +102,10 @@ } } + if ((json_val = uwsgi_mongrel2_json_get_string(root, "URL_SCHEME"))) { + wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "UWSGI_SCHEME", 12, json_val, strlen(json_val)); + } + if ((json_val = uwsgi_mongrel2_json_get_string(root, "host"))) { char *colon = strchr(json_val, ':'); if (colon) { @@ -210,6 +214,9 @@ wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, val, vallen); } } + else if (!uwsgi_strncmp("URL_SCHEME", 10, key, keylen)) { + wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "UWSGI_SCHEME", 12, val, vallen); + } } else { // add header @@ -299,6 +306,13 @@ // fake function, the body is in a file or completely in memory ssize_t uwsgi_proto_zeromq_read_body(struct wsgi_request *wsgi_req, char *buf, size_t len) { + size_t remains = wsgi_req->post_cl - wsgi_req->proto_parser_status; + if (remains > 0) { + if (len > remains) len = remains; + memcpy(buf, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_buf_size + wsgi_req->proto_parser_status, len); + wsgi_req->proto_parser_status += len; + return len; + } return 0; } @@ -410,7 +424,8 @@ } // pre-build the mongrel2 response_header - wsgi_req->proto_parser_buf = uwsgi_malloc(req_uuid_len + 1 + 11 + 1 + req_id_len + 1 + 1); + wsgi_req->proto_parser_buf_size = req_uuid_len + 1 + 11 + 1 + req_id_len + 1 + 1; + wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_buf_size); memcpy(wsgi_req->proto_parser_buf, req_uuid, req_uuid_len); ((char *) wsgi_req->proto_parser_buf)[req_uuid_len] = ' '; resp_id_len = uwsgi_num2str2(req_id_len, wsgi_req->proto_parser_buf + req_uuid_len + 1); @@ -422,13 +437,22 @@ wsgi_req->proto_parser_pos = (uint64_t) req_uuid_len + 1 + resp_id_len + 1 + req_id_len + 1 + 1; // handle post data (in memory) + // reallocate wsgi_req->proto_parser_buf and change its size to be able to store request body + // the parser status holds the current position for read_body hook if (wsgi_req->post_cl > 0 && !wsgi_req->post_file) { if (uwsgi_netstring(post_data, message_size - (post_data - message_ptr), &message_ptr, &wsgi_req->post_cl)) { + char *tmp = realloc(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf_size + wsgi_req->post_cl); + if (!tmp) { + uwsgi_error("realloc()"); + exit(1); + } + wsgi_req->proto_parser_buf = tmp; + // status is an offset... + wsgi_req->proto_parser_status = 0; #ifdef UWSGI_DEBUG uwsgi_log("post_size: %d\n", wsgi_req->post_cl); #endif - wsgi_req->post_read_buf = uwsgi_malloc(wsgi_req->post_cl); - memcpy(wsgi_req->post_read_buf, message_ptr, wsgi_req->post_cl); + memcpy(wsgi_req->proto_parser_buf + wsgi_req->proto_parser_buf_size, message_ptr, wsgi_req->post_cl); } } @@ -452,33 +476,7 @@ return -1; } -void uwsgi_proto_zeromq_close(struct wsgi_request *wsgi_req) { - zmq_msg_t reply; - - // check for already freed wsgi_req->proto_parser_buf/wsgi_req->proto_parser_pos - if (!wsgi_req->proto_parser_pos) - return; - - // no need to pass a free function (the buffer will be freed during cloe_request) - zmq_msg_init_data(&reply, wsgi_req->proto_parser_buf, wsgi_req->proto_parser_pos, NULL, NULL); - if (uwsgi.threads > 1) - pthread_mutex_lock(&wsgi_req->socket->lock); -#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0) - if (zmq_sendmsg(wsgi_req->socket->pub, &reply, 0)) { - uwsgi_error("uwsgi_proto_zeromq_close()/zmq_sendmsg()"); -#else - if (zmq_send(wsgi_req->socket->pub, &reply, 0)) { - uwsgi_error("uwsgi_proto_zeromq_close()/zmq_send()"); -#endif - } - if (uwsgi.threads > 1) - pthread_mutex_unlock(&wsgi_req->socket->lock); - zmq_msg_close(&reply); - -} - - -int uwsgi_proto_zeromq_write(struct wsgi_request *wsgi_req, char *buf, size_t len) { +static int uwsgi_proto_zeromq_write_do(struct wsgi_request *wsgi_req, char *buf, size_t len) { zmq_msg_t reply; if (zmq_msg_init_size(&reply, wsgi_req->proto_parser_pos + len)) { @@ -489,7 +487,8 @@ char *zmq_body = zmq_msg_data(&reply); memcpy(zmq_body, wsgi_req->proto_parser_buf, wsgi_req->proto_parser_pos); - memcpy(zmq_body + wsgi_req->proto_parser_pos, buf, len); + if (len > 0) + memcpy(zmq_body + wsgi_req->proto_parser_pos, buf, len); if (uwsgi.threads > 1) pthread_mutex_lock(&wsgi_req->socket->lock); @@ -510,6 +509,18 @@ return UWSGI_OK; } +int uwsgi_proto_zeromq_write(struct wsgi_request *wsgi_req, char *buf, size_t len) { + int ret = uwsgi_proto_zeromq_write_do(wsgi_req, buf, len); + if (ret == UWSGI_OK) { + wsgi_req->write_pos += len; + } + return ret; +} + +void uwsgi_proto_zeromq_close(struct wsgi_request *wsgi_req) { + uwsgi_proto_zeromq_write_do(wsgi_req, "", 0); +} + /* we have a problem... recent Mongrel2 releases introduced a ring buffer that limit the amount of messages we can send (or better, the amount of @@ -532,7 +543,7 @@ return -1; } wsgi_req->write_pos += rlen; - if (uwsgi_proto_zeromq_write(wsgi_req, tmp_buf, rlen) < 0) { + if (uwsgi_proto_zeromq_write_do(wsgi_req, tmp_buf, rlen) < 0) { free(tmp_buf); return -1; } @@ -574,6 +585,7 @@ static void mongrel2_connect() { struct uwsgi_socket *uwsgi_sock = uwsgi.sockets; while(uwsgi_sock) { + if (uwsgi_sock->proto != uwsgi_proto_zeromq_parser) goto next; uwsgi_sock->ctx = zmq_init(1); if (!uwsgi_sock->ctx) { uwsgi_error("mongrel2_connect()/zmq_init()"); @@ -581,7 +593,7 @@ } char *responder = strchr(uwsgi_sock->name, ','); if (!responder) { - uwsgi_log("invalid zeromq address\n"); + uwsgi_log("invalid zeromq address: %s\n", uwsgi_sock->name); exit(1); } uwsgi_sock->receiver = uwsgi_concat2n(uwsgi_sock->name, responder - uwsgi_sock->name, "", 0); @@ -653,6 +665,7 @@ #else uwsgi_sock->recv_flag = ZMQ_NOBLOCK; #endif +next: uwsgi_sock = uwsgi_sock->next; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/psgi/psgi_loader.c new/uwsgi-2.0.3/plugins/psgi/psgi_loader.c --- old/uwsgi-2.0.2/plugins/psgi/psgi_loader.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/psgi/psgi_loader.c 2014-03-17 06:33:04.000000000 +0100 @@ -54,7 +54,7 @@ psgi_check_args(1); HV *hv_args = (HV *) (SvRV(ST(0))); if (!hv_exists(hv_args, "level", 5) || !hv_exists(hv_args, "message", 7)) { - Perl_croak(aTHX_ "psgix.logger requires bot level and message items"); + Perl_croak(aTHX_ "psgix.logger requires both level and message items"); } char *level = SvPV_nolen(*(hv_fetch(hv_args, "level", 5, 0))); char *message = SvPV_nolen(*(hv_fetch(hv_args, "message", 7, 0))); @@ -108,7 +108,7 @@ unsigned long arg_len = SvIV(ST(2)); long offset = 0; - if (items > 2) { + if (items > 3) { offset = (long) SvIV(ST(3)); } @@ -370,12 +370,16 @@ // uperl.embedding as an argument so we won't execute // BEGIN blocks in app_name twice. { - char *perl_init_arg[] = { "", "-e", "0" }; + char *perl_e_arg = uwsgi_concat2("#line 0 ", app_name); + char *perl_init_arg[] = { "", "-e", perl_e_arg }; if (perl_parse(interpreters[i], xs_init, 3, perl_init_arg, NULL)) { // what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff... free(callables); + free(perl_e_arg); uwsgi_perl_free_stashes(); goto clear; + } else { + free(perl_e_arg); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/psgi/uwsgi_plmodule.c new/uwsgi-2.0.3/plugins/psgi/uwsgi_plmodule.c --- old/uwsgi-2.0.2/plugins/psgi/uwsgi_plmodule.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/psgi/uwsgi_plmodule.c 2014-03-17 06:33:04.000000000 +0100 @@ -955,6 +955,27 @@ XSRETURN_UNDEF; } +XS(XS_add_var) { + dXSARGS; + psgi_check_args(2); + + struct wsgi_request *wsgi_req = current_wsgi_req(); + + STRLEN keylen; + char *key = SvPV(ST(0), keylen); + + STRLEN vallen; + char *val = SvPV(ST(1), vallen); + + if (!uwsgi_req_append(wsgi_req, key, keylen, val, vallen)) { + croak("unable to add request var, check your buffer size"); + XSRETURN_UNDEF; + } + + XSRETURN_YES; + +} + void init_perl_embedded_module() { psgi_xs(reload); @@ -1016,5 +1037,7 @@ psgi_xs(spooler); psgi_xs(spool); + + psgi_xs(add_var); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/python/python_plugin.c new/uwsgi-2.0.3/plugins/python/python_plugin.c --- old/uwsgi-2.0.2/plugins/python/python_plugin.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/python/python_plugin.c 2014-03-17 06:33:04.000000000 +0100 @@ -197,6 +197,12 @@ uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1); } + if (Py_IsInitialized()) { + uwsgi_log("--- Python VM already initialized ---\n"); + PyGILState_Ensure(); + goto ready; + } + if (up.home != NULL) { #ifdef PYTHREE // check for PEP 405 virtualenv (starting from python 3.3) @@ -251,6 +257,8 @@ Py_Initialize(); +ready: + if (!uwsgi.has_threads) { uwsgi_log_initial("*** Python threads support is disabled. You can enable it with --enable-threads ***\n"); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/python/uwsgi_pymodule.c new/uwsgi-2.0.3/plugins/python/uwsgi_pymodule.c --- old/uwsgi-2.0.2/plugins/python/uwsgi_pymodule.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/python/uwsgi_pymodule.c 2014-03-17 06:33:04.000000000 +0100 @@ -4,6 +4,26 @@ extern struct uwsgi_python up; extern struct uwsgi_plugin python_plugin; +static PyObject *py_uwsgi_add_var(PyObject * self, PyObject * args) { + char *key = NULL; + Py_ssize_t keylen = 0; + char *val = NULL; + Py_ssize_t vallen = 0; + struct wsgi_request *wsgi_req = py_current_wsgi_req(); + + if (!PyArg_ParseTuple(args, "s#s#", &key, &keylen, &val, &vallen)) { + return NULL; + } + + if (!uwsgi_req_append(wsgi_req, key, keylen, val, vallen)) { + return PyErr_Format(PyExc_ValueError, "unable to add request var, check your buffer size"); + } + + Py_INCREF(Py_True); + return Py_True; +} + + static PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) { struct wsgi_request *wsgi_req = py_current_wsgi_req(); @@ -2417,6 +2437,8 @@ {"ready_fd", py_uwsgi_ready_fd, METH_VARARGS, ""}, + {"add_var", py_uwsgi_add_var, METH_VARARGS, ""}, + {NULL, NULL}, }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/syslog/syslog_plugin.c new/uwsgi-2.0.3/plugins/syslog/syslog_plugin.c --- old/uwsgi-2.0.2/plugins/syslog/syslog_plugin.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/syslog/syslog_plugin.c 2014-03-17 06:33:04.000000000 +0100 @@ -93,7 +93,11 @@ ul->configured = 1; } +#ifdef __APPLE__ + syslog(LOG_NOTICE, "%.*s", (int) len, message); +#else syslog(LOG_INFO, "%.*s", (int) len, message); +#endif return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/tuntap/common.c new/uwsgi-2.0.3/plugins/tuntap/common.c --- old/uwsgi-2.0.2/plugins/tuntap/common.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/tuntap/common.c 2014-03-17 06:33:04.000000000 +0100 @@ -2,6 +2,16 @@ extern struct uwsgi_tuntap utt; +// error reporting +void uwsgi_tuntap_error_do(struct uwsgi_tuntap_peer *uttp, char *msg, char *file, int line) { + if (uttp) { + uwsgi_log_verbose("[tuntap] peer fd: %d ip: %s %s: %s [%s line %d]\n", uttp->fd, uttp->ip, msg, strerror(errno), file, line); + } + else { + uwsgi_log_verbose("[tuntap] %s: %s [%s line %d]\n", msg, strerror(errno), file, line); + } +} + // create a new peer struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_create(struct uwsgi_tuntap_router *uttr, int fd, int is_router) { @@ -183,7 +193,7 @@ char ip[INET_ADDRSTRLEN + 1]; memset(ip, 0, INET_ADDRSTRLEN + 1); if (!inet_ntop(AF_INET, &uttp->addr, ip, INET_ADDRSTRLEN)) { - uwsgi_error("uwsgi_tuntap_register_addr()/inet_ntop()"); + uwsgi_tuntap_error(uttp, "uwsgi_tuntap_register_addr()/inet_ntop()"); return -1; } if (uttp != tmp_uttp) { @@ -205,7 +215,7 @@ if (rlen < 0) { if (uwsgi_is_again()) return 0; - uwsgi_error("uwsgi_tuntap_peer_dequeue()/read()"); + uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_dequeue()/read()"); return -1; } uttp->buf_pos += rlen; @@ -265,7 +275,7 @@ if (rlen < 0) { if (uwsgi_is_again()) return 0; - uwsgi_error("uwsgi_tuntap_peer_dequeue()/read()"); + uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_dequeue()/read()"); return -1; } uttp->header_pos += rlen; @@ -282,14 +292,14 @@ ssize_t rlen = write(uttp->fd, uttp->write_buf + uttp->written, uttp->write_buf_pktsize - uttp->written); if (rlen == 0) { - uwsgi_error("uwsgi_tuntap_peer_enqueue()/write()"); + uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_enqueue()/write()"); return -1; } if (rlen < 0) { if (uwsgi_is_again()) goto retry; - uwsgi_error("uwsgi_tuntap_peer_enqueue()/write()"); + uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_enqueue()/write()"); return -1; } @@ -303,13 +313,13 @@ if (uttr->wait_for_write) { uttp->blocked_read = 1; if (event_queue_del_fd(uttr->queue, uttp->fd, event_queue_write())) { - uwsgi_error("uwsgi_tuntap_peer_enqueue()/event_queue_del_fd()"); + uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_enqueue()/event_queue_del_fd()"); return -1; } } else { if (event_queue_fd_readwrite_to_read(uttr->queue, uttp->fd)) { - uwsgi_error("uwsgi_tuntap_peer_enqueue()/event_queue_fd_write_to_read()"); + uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_enqueue()/event_queue_fd_write_to_read()"); return -1; } } @@ -324,7 +334,7 @@ retry: if (!uttp->wait_for_write) { if (event_queue_fd_read_to_readwrite(uttr->queue, uttp->fd)) { - uwsgi_error("uwsgi_tuntap_peer_enqueue()/event_queue_fd_read_to_write()"); + uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_enqueue()/event_queue_fd_read_to_write()"); return -1; } uttp->wait_for_write = 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/tuntap/common.h new/uwsgi-2.0.3/plugins/tuntap/common.h --- old/uwsgi-2.0.2/plugins/tuntap/common.h 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/tuntap/common.h 2014-03-17 06:33:04.000000000 +0100 @@ -116,3 +116,5 @@ void uwsgi_tuntap_peer_send_rules(int, struct uwsgi_tuntap_peer *); int uwsgi_tuntap_peer_rules_check(struct uwsgi_tuntap_router *, struct uwsgi_tuntap_peer *, char *, size_t, int); +#define uwsgi_tuntap_error(x, y) uwsgi_tuntap_error_do(x, y, __FILE__, __LINE__) +void uwsgi_tuntap_error_do(struct uwsgi_tuntap_peer *, char *, char *, int); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/tuntap/firewall.c new/uwsgi-2.0.3/plugins/tuntap/firewall.c --- old/uwsgi-2.0.2/plugins/tuntap/firewall.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/tuntap/firewall.c 2014-03-17 06:33:04.000000000 +0100 @@ -1,6 +1,7 @@ #include "common.h" extern struct uwsgi_tuntap utt; +extern struct uwsgi_server uwsgi; int uwsgi_tuntap_peer_rules_check(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp, char *pkt, size_t len, int direction) { if (uttp->rules_cnt == 0) return 0; @@ -51,7 +52,25 @@ sin.sin_port = rule->target_port; sin.sin_addr.s_addr = rule->target; if (sendto(uttr->gateway_fd, pkt, len, 0, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) < 0) { - uwsgi_error("uwsgi_tuntap_route_check()/sendto()"); + if (uwsgi_is_again()) { + // suspend and retry + struct pollfd pfd; + memset(&pfd, 0, sizeof(struct pollfd)); + pfd.fd = uttr->gateway_fd; + pfd.events = POLLOUT; + int ret = poll(&pfd, 1, uwsgi.socket_timeout * 1000); + if (ret > 0) { + if (sendto(uttr->gateway_fd, pkt, len, 0, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) < 0) { + uwsgi_tuntap_error(uttp,"uwsgi_tuntap_route_check()/sendto()"); + } + } + else { + uwsgi_tuntap_error(uttp,"uwsgi_tuntap_route_check()/poll()"); + } + } + else { + uwsgi_tuntap_error(uttp,"uwsgi_tuntap_route_check()/sendto()"); + } } } return 2; @@ -305,7 +324,7 @@ *slash = 0; } if (inet_pton(AF_INET, argv[1], &utpr.src) != 1) { - uwsgi_error("uwsgi_tuntap_peer_send_rules()/inet_pton()"); + uwsgi_tuntap_error(peer, "uwsgi_tuntap_peer_send_rules()/inet_pton()"); exit(1); } if (slash) *slash = '/'; @@ -317,7 +336,7 @@ *slash = 0; } if (inet_pton(AF_INET, argv[2], &utpr.dst) != 1) { - uwsgi_error("uwsgi_tuntap_peer_send_rules()/inet_pton()"); + uwsgi_tuntap_error(peer, "uwsgi_tuntap_peer_send_rules()/inet_pton()"); exit(1); } if (slash) *slash = '/'; @@ -352,7 +371,7 @@ } *colon = 0; if (inet_pton(AF_INET, argv[4], &utpr.target) != 1) { - uwsgi_error("uwsgi_tuntap_peer_send_rules()/inet_pton()"); + uwsgi_tuntap_error(peer, "uwsgi_tuntap_peer_send_rules()/inet_pton()"); exit(1); } *colon = ':'; @@ -370,7 +389,7 @@ size_t len = ub->pos; uwsgi_buffer_destroy(ub); if (write(fd,peer->rules, len) != (ssize_t)len) { - uwsgi_error("uwsgi_tuntap_peer_send_rules()/write()"); + uwsgi_tuntap_error(peer, "uwsgi_tuntap_peer_send_rules()/write()"); exit(1); } return; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/plugins/tuntap/tuntap.c new/uwsgi-2.0.3/plugins/tuntap/tuntap.c --- old/uwsgi-2.0.2/plugins/tuntap/tuntap.c 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/plugins/tuntap/tuntap.c 2014-03-17 06:33:04.000000000 +0100 @@ -117,6 +117,13 @@ uwsgi_error("uwsgi_tuntap_loop()/read()"); exit(1); } + + // check for full write buffer + if (uttp->write_buf_pktsize + 4 + rlen > utt.buffer_size) { + uttp->dropped++; + continue; + } + uint16_t pktsize = rlen; char *ptr = uttp->write_buf + uttp->write_buf_pktsize; memcpy(ptr + 4, uttr->buf, rlen); @@ -126,7 +133,7 @@ ptr[3] = 0; uttp->write_buf_pktsize+= pktsize+4; if (uwsgi_tuntap_peer_enqueue(uttr, uttp)) { - uwsgi_log("server disconnected...\n"); + uwsgi_log_verbose("tuntap server disconnected...\n"); exit(1); } continue; @@ -137,7 +144,7 @@ // read from the client if (!uttp->wait_for_write) { if (uwsgi_tuntap_peer_dequeue(uttr, uttp, 0)) { - uwsgi_log("server disconnected...\n"); + uwsgi_log_verbose("tuntap server disconnected...\n"); exit(1); } } @@ -149,7 +156,7 @@ // write to the client if (uwsgi_tuntap_peer_enqueue(uttr, uttp)) { - uwsgi_log("server disconnected...\n"); + uwsgi_log_verbose("tuntap server disconnected...\n"); exit(1); } } @@ -507,7 +514,7 @@ ssize_t res = write(client_fd, us->base + pos, remains); if (res <= 0) { if (res < 0) { - uwsgi_error("write()"); + uwsgi_error("tuntaprouter_send_stats()/write()"); } goto end0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/t/perl/test.psgi new/uwsgi-2.0.3/t/perl/test.psgi --- old/uwsgi-2.0.2/t/perl/test.psgi 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/t/perl/test.psgi 2014-03-17 06:33:04.000000000 +0100 @@ -59,6 +59,10 @@ uwsgi::signal(17); uwsgi::signal(30); + my ($package, $filename, $line) = caller; + die "Expecting reasonable caller() return values, not [$package, $filename, $line]" + unless $package eq 'main' and $filename =~ /\btest\.psgi$/s and $line == 0; + if ($env->{'psgix.cleanup'}) { print "cleanup supported\n"; push @{$env->{'psgix.cleanup.handlers'}}, $one; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/t/perl/test_input_with_offset.pl new/uwsgi-2.0.3/t/perl/test_input_with_offset.pl --- old/uwsgi-2.0.2/t/perl/test_input_with_offset.pl 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/t/perl/test_input_with_offset.pl 2014-03-17 06:33:04.000000000 +0100 @@ -20,11 +20,13 @@ push @tests, ['3', 'HELLO', "oneHELLOthree_four"]; push @tests, ['30', 'HELLO', "one_two_three_four\0\0\0\0\0\0\0\0\0\0\0\0HELLO"]; +@ARGV or die "You must provide a host to test on, e.g. localhost:8080"; + foreach(@tests) { print "testing: offset(".$_->[0].") body(".$_->[1].")\n"; my $req = "POST /?".$base." HTTP/1.0\r\nContent-Length: ".length($_->[1])."\r\nuWSGI-Offset: ".$_->[0]."\r\n\r\n".$_->[1]; - my $s = IO::Socket::INET->new(PeerAddr => $ARGV[0]); + my $s = IO::Socket::INET->new(PeerAddr => $ARGV[0]) or die "PANIC: Unable to construct socket"; $s->send($req); my $response = ''; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/t/perl/test_post.psgi new/uwsgi-2.0.3/t/perl/test_post.psgi --- old/uwsgi-2.0.2/t/perl/test_post.psgi 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.3/t/perl/test_post.psgi 2014-03-17 06:33:04.000000000 +0100 @@ -0,0 +1,47 @@ +use strict; +use warnings; + +sub { + my $env = shift; + + my $cl = $env->{CONTENT_LENGTH}; + $env->{'psgi.input'}->seek(0,0); + my $content = ''; + while ($cl) { + $env->{'psgi.input'}->read(my $chunk, $cl < 8192 ? $cl : 8192); + my $read = length $chunk; + $cl -= $read; + $content .= $chunk; + } + + return [200, [], [ "Your content was: <$content>" ]]; +}; + +__END__ + +This is a trival test that prints out a POST request, it's here to +test a regression introduced in 2.0-103-gf041d10 where doing reads +without offsets, e.g.: + + $ http_proxy= curl -d '{ "what": "ever" }' http://localhost:8080/ + Your content was: $VAR1 = '{ "what": "ever" }'; + +Would result in: + + Use of uninitialized value in subroutine entry at + /home/v-perlbrew/perl5/perlbrew/perls/perl-5.19.6/lib/site_perl/5.19.6/Plack/Request.pm + line 280. + +Which is due to this commit having a one-off error in counting stack +items. + + $ git bisect good + f041d1095ddf7541c4b275e16d2ed3355a8e2be9 is the first bad commit + commit f041d1095ddf7541c4b275e16d2ed3355a8e2be9 + Author: Unbit <i...@unbit.it> + Date: Wed Feb 5 11:21:01 2014 +0100 + + perl refactoring + + :040000 040000 98a25406b7edb9bd0b9be8bbcd351a99e7ce2d33 0087e3ca4b6bd65a087fade65d43a56085298ef0 M plugins + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/t/perl/test_streaming.psgi new/uwsgi-2.0.3/t/perl/test_streaming.psgi --- old/uwsgi-2.0.2/t/perl/test_streaming.psgi 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.3/t/perl/test_streaming.psgi 2014-03-17 06:33:04.000000000 +0100 @@ -0,0 +1,48 @@ +use strict; +use warnings; + +sub { + my $env = shift; + + return sub { + my $responder = shift; + my $writer = $responder->([ 200, [ 'Content-Type', 'text/plain' ]]); + sleep 3; + $writer->write("hello\n"); + sleep 3; + $writer->write("world\n"); + $writer->close; + return; + }; +} + +__END__ + +Making a request to this will give you: + + $ date; curl -s -N -D - 'http://localhost:8080' + Sat Mar 15 14:08:25 UTC 2014 + HTTP/1.1 200 OK + Content-Type: text/plain + + hello + world + +And monitoring it with tcpflow shows how the output (including +headers) is flushed right away: + + $ sudo tcpflow -i lo -c port 8080 | perl -pe 's/^/localtime . " "/ge' + Sat Mar 15 14:09:08 2014 127.000.000.001.55058-127.000.000.001.08080: GET / HTTP/1.1 + Sat Mar 15 14:09:08 2014 User-Agent: curl/7.35.0 + Sat Mar 15 14:09:08 2014 Host: localhost:8080 + Sat Mar 15 14:09:08 2014 Accept: */* + Sat Mar 15 14:09:08 2014 + Sat Mar 15 14:09:08 2014 + Sat Mar 15 14:09:08 2014 127.000.000.001.08080-127.000.000.001.55058: HTTP/1.1 200 OK + Sat Mar 15 14:09:08 2014 Content-Type: text/plain + Sat Mar 15 14:09:08 2014 + Sat Mar 15 14:09:08 2014 + Sat Mar 15 14:09:11 2014 127.000.000.001.08080-127.000.000.001.55058: hello + Sat Mar 15 14:09:11 2014 + Sat Mar 15 14:09:14 2014 127.000.000.001.08080-127.000.000.001.55058: world + Sat Mar 15 14:09:14 2014 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.2/uwsgi.gemspec new/uwsgi-2.0.3/uwsgi.gemspec --- old/uwsgi-2.0.2/uwsgi.gemspec 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/uwsgi.gemspec 2014-03-17 06:33:04.000000000 +0100 @@ -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 = '2014-02-26' + s.date = '2014-03-17' 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.2/uwsgiconfig.py new/uwsgi-2.0.3/uwsgiconfig.py --- old/uwsgi-2.0.2/uwsgiconfig.py 2014-02-26 17:06:47.000000000 +0100 +++ new/uwsgi-2.0.3/uwsgiconfig.py 2014-03-17 06:33:04.000000000 +0100 @@ -1,6 +1,6 @@ # uWSGI build system -uwsgi_version = '2.0.2' +uwsgi_version = '2.0.3' import os import re @@ -367,6 +367,15 @@ if len(kv) > 1: p = kv[1] p = p.strip() + if p.startswith('http://') or p.startswith('https://') or p.startswith('git://') or p.startswith('ssh://'): + git_dir = p.split('/').pop() + if not os.path.isdir(git_dir): + if os.system('git clone %s' % p) != 0: + sys.exit(1) + else: + if os.system('cd %s ; git pull' % git_dir) != 0: + sys.exit(1) + p = git_dir path = os.path.abspath(p) else: p = kv[0] @@ -1275,6 +1284,16 @@ up = {} + if path.startswith('http://') or path.startswith('https://') or path.startswith('git://') or path.startswith('ssh://'): + git_dir = path.split('/').pop() + if not os.path.isdir(git_dir): + if os.system('git clone %s' % path) != 0: + sys.exit(1) + else: + if os.system('cd %s ; git pull' % git_dir) != 0: + sys.exit(1) + path = os.path.abspath(git_dir) + if os.path.isfile(path): bname = os.path.basename(path) # override path ++++++ uwsgi.dsc ++++++ --- /var/tmp/diff_new_pack.jQl7rt/_old 2014-04-09 13:17:42.000000000 +0200 +++ /var/tmp/diff_new_pack.jQl7rt/_new 2014-04-09 13:17:42.000000000 +0200 @@ -4,7 +4,7 @@ python3-uwsgidecorators, uwsgi-extra Architecture: any all -Version: 2.0.2-1 +Version: 2.0.3-1 Maintainer: Janos Guljas <ja...@debian.org> Uploaders: Jonas Smedegaard <d...@jones.dk> Homepage: http://projects.unbit.it/uwsgi/ -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org