From 951f24e7111652839afa13db9546314183af61ff Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Sat, 22 Feb 2014 10:46:46 +0100 Subject: [PATCH 01/21] fixed #546 --- core/async.c | 18 +++ plugins/cgi/cgi_plugin.c | 326 ++++++++++++++++++++++----------------- 2 files changed, 203 insertions(+), 141 deletions(-) diff --git a/core/async.c b/core/async.c index bb8ff412..41651fdf 100644 --- a/core/async.c +++ b/core/async.c @@ -387,6 +387,23 @@ end: } +static int uwsgi_async_wait_milliseconds_hook(int timeout) { + struct wsgi_request *wsgi_req = current_wsgi_req(); + timeout = timeout / 1000; + if (!timeout) timeout = 1; + async_add_timeout(wsgi_req, timeout); + wsgi_req->async_force_again = 1; + if (uwsgi.schedule_to_main) { + uwsgi.schedule_to_main(wsgi_req); + } + if (wsgi_req->async_timed_out) { + wsgi_req->async_timed_out = 0; + return 0; + } + + return -1; +} + void async_loop() { if (uwsgi.async < 2) { @@ -414,6 +431,7 @@ void async_loop() { uwsgi.wait_write_hook = async_wait_fd_write; uwsgi.wait_read_hook = async_wait_fd_read; uwsgi.wait_read2_hook = async_wait_fd_read2; + uwsgi.wait_milliseconds_hook = uwsgi_async_wait_milliseconds_hook; if (uwsgi.signal_socket > -1) { event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket); diff --git a/plugins/cgi/cgi_plugin.c b/plugins/cgi/cgi_plugin.c index 0518081e..3cf5e641 100644 --- a/plugins/cgi/cgi_plugin.c +++ b/plugins/cgi/cgi_plugin.c @@ -2,6 +2,8 @@ extern struct uwsgi_server uwsgi; +#define kill_on_error if (!uc.do_not_kill_on_error) { if (kill(cgi_pid, SIGKILL)) uwsgi_error("kill()");} + struct uwsgi_cgi { struct uwsgi_dyn_dict *mountpoint; struct uwsgi_dyn_dict *helpers; @@ -16,6 +18,8 @@ struct uwsgi_cgi { int has_mountpoints; struct uwsgi_dyn_dict *default_cgi; int path_info; + int do_not_kill_on_error; + int async_max_attempts; } uc ; static void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) { @@ -62,6 +66,9 @@ struct uwsgi_option uwsgi_cgi_options[] = { {"cgi-path-info", no_argument, 0, "disable PATH_INFO management in cgi scripts", uwsgi_opt_true, &uc.path_info, 0}, + {"cgi-do-not-kill-on-error", no_argument, 0, "do not send SIGKILL to cgi script on errors", uwsgi_opt_true, &uc.do_not_kill_on_error, 0}, + {"cgi-async-max-attempts", no_argument, 0, "max waitpid() attempts in cgi async mode (default 10)", uwsgi_opt_set_int, &uc.async_max_attempts, 0}, + {0, 0, 0, 0, 0, 0, 0}, }; @@ -179,118 +186,154 @@ static char *uwsgi_cgi_get_helper(char *filename) { } -static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) { - - size_t i; +/* +start reading each line until Status or Location are found +-1 error +0 not found +1 found +*/ +static int uwsgi_cgi_check_status(struct wsgi_request *wsgi_req, char *buf, size_t len) { char *key = buf, *value = NULL; size_t header_size = 0; - int status_sent = 0; + size_t i; - // Search for Status/Location headers for(i=0;i buf) { - if ((buf[i-1]) == '\r') { - header_size--; - } + // invalid header + else if (value == NULL) return -1; + header_size = (buf+i) - key; + // security check + if (buf+i > buf) { + // remove \r + if ((buf[i-1]) == '\r') { + header_size--; + } + } + + // enough space for Status ? + if (header_size >= 11) { + // "Status: NNN" + if (!strncasecmp("Status: ", key, 8)) { +#ifdef UWSGI_DEBUG + uwsgi_log("found Status header: %.*s\n", header_size, key); +#endif + if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1; + return 1; + } + // Location: X + if (!strncasecmp("Location: ", key, 10)) { +#ifdef UWSGI_DEBUG + uwsgi_log("found Location header: %.*s\n", header_size, key); +#endif + if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1; + return 1; + } } - if (header_size >= 11) { - // "Status: NNN" - if (!strncasecmp("Status: ", key, 8)) { -#ifdef UWSGI_DEBUG - uwsgi_log("found Status header: %.*s\n", header_size, key); -#endif - if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1; - break; - } - // Location: X - if (!strncasecmp("Location: ", key, 10)) { -#ifdef UWSGI_DEBUG - uwsgi_log("found Location header: %.*s\n", header_size, key); -#endif - if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1; - break; - } - } - - key = NULL; - value = NULL; + key = NULL; + value = NULL; } - else if (buf[i] == ':') { + else if (buf[i] == ':') { value = buf+i; - } - else if (buf[i] != '\r') { - if (key == NULL) { - key = buf + i; - } - } + } + else if (buf[i] != '\r') { + if (key == NULL) key = buf + i; + } + } - key = buf; - value = NULL; + // no Status/Location found + return 0; - for(i=0;i buf) { - if ((buf[i-1]) == '\r') { - header_size--; +} + +static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, int fd, char *buf, size_t blen) { + + size_t i; + size_t header_size = 0; + int status_sent = 0; + size_t remains = blen; + char *ptr = buf; + size_t len = 0; + + while(remains > 0) { + ssize_t rlen = uwsgi_read_true_nb(fd, ptr, remains, uc.timeout); + if (rlen < 0) { + if (!errno) return 1; + return -1; + } + // timed out + if (rlen == 0) return -1; + remains -= rlen; + len += rlen; + ptr += rlen; + + // Search for Status/Location headers + if (!status_sent) { + status_sent = uwsgi_cgi_check_status(wsgi_req, buf, len); + if (status_sent < 0) return -1; + // need more data ? + if (status_sent == 0) continue; + } + + // send headers + char *key = buf; + char *value = NULL; + + for(i=0;i buf) { + if ((buf[i-1]) == '\r') { + header_size--; + } } - } #ifdef UWSGI_DEBUG - uwsgi_log("found CGI header: %.*s\n", header_size, key); + uwsgi_log("found CGI header: %.*s\n", header_size, key); #endif - // Ignore "Status: NNN" header - if (status_sent == 0 && header_size >= 11) { - if (!strncasecmp("Status: ", key, 8)) { - status_sent = 1; - key = NULL; - value = NULL; - continue; + // Ignore "Status: NNN" header + if (header_size >= 11) { + if (!strncasecmp("Status: ", key, 8)) { + key = NULL; + value = NULL; + continue; + } } + + uwsgi_response_add_header(wsgi_req, NULL, 0, key, header_size); + key = NULL; + value = NULL; } - - uwsgi_response_add_header(wsgi_req, NULL, 0, key, header_size); - - key = NULL; - value = NULL; - } - else if (buf[i] == ':') { - value = buf+i; - } - else if (buf[i] != '\r') { - if (key == NULL) { - key = buf + i; + else if (buf[i] == ':') { + value = buf+i; + } + else if (buf[i] != '\r') { + if (key == NULL) { + key = buf + i; + } } } } @@ -592,7 +635,6 @@ static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t do int post_pipe[2]; int nargs = 0; int waitpid_status; - ssize_t len; int i; char **argv; @@ -630,6 +672,9 @@ static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t do close(cgi_pipe[1]); close(post_pipe[0]); + uwsgi_socket_nb(cgi_pipe[0]); + uwsgi_socket_nb(post_pipe[1]); + // ok start sending post data... size_t remains = wsgi_req->post_cl; while(remains > 0) { @@ -650,73 +695,72 @@ static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t do close(post_pipe[1]); // wait for data - char *headers_buf = uwsgi_malloc(uc.buffer_size); - char *ptr = headers_buf; - remains = uc.buffer_size; - int completed = 0; - while(remains > 0) { - int ret = uwsgi.wait_read_hook(cgi_pipe[0], uc.timeout); - if (ret > 0) { - len = read(cgi_pipe[0], ptr, remains); - if (len > 0) { - ptr+=len; - remains -= len; - } - else if (len == 0) { - completed = 1; - break; - } - else { - uwsgi_error("read()"); - goto clear; - } - continue; - } - else if (ret == 0) { - uwsgi_log("CGI timeout !!!\n"); - goto clear; - } - break; - } + char *buf = uwsgi_malloc(uc.buffer_size); - if (uwsgi_cgi_parse(wsgi_req, headers_buf, uc.buffer_size-remains)) { - uwsgi_log("invalid CGI output !!!\n"); + int completed = uwsgi_cgi_parse(wsgi_req, cgi_pipe[0], buf, uc.buffer_size); + if (completed < 0) { + uwsgi_log("invalid CGI response !!!\n"); + kill_on_error goto clear; } while (!completed) { - int ret = uwsgi.wait_read_hook(cgi_pipe[0], uc.timeout); - if (ret > 0) { - len = read(cgi_pipe[0], headers_buf, uc.buffer_size); - if (len > 0) { - uwsgi_response_write_body_do(wsgi_req, headers_buf, len); - } - // end of output - else if (len == 0) { - break; - } - else { - uwsgi_error("read()"); + ssize_t rlen = uwsgi_read_true_nb(cgi_pipe[0], buf, uc.buffer_size, uc.timeout); + if (rlen > 0) { + if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) { + kill_on_error goto clear; } - continue; } - else if (ret == 0) { - uwsgi_log("CGI timeout !!!\n"); - goto clear; - } - break; + else if (rlen == 0) { + uwsgi_log("CGI timeout !!!\n"); + kill_on_error + goto clear; + } + else { + if (errno) { + uwsgi_req_error("error reading CGI response\n"); + kill_on_error + } + goto clear; + } } clear: - free(headers_buf); + free(buf); clear2: close(cgi_pipe[0]); close(post_pipe[1]); // now wait for process exit/death - if (waitpid(cgi_pid, &waitpid_status, 0) < 0) { - uwsgi_error("waitpid()"); + // in async mode we need a trick... + if (uwsgi.async > 1) { + int max_attempts = uc.async_max_attempts; + if (!max_attempts) max_attempts = 10; + while(max_attempts) { + pid_t diedpid = waitpid(cgi_pid, &waitpid_status, WNOHANG); + if (diedpid < 0) { + uwsgi_error("waitpid()"); + break; + } + else if (diedpid == 0) { + int ret = uwsgi.wait_milliseconds_hook(1000); + if (ret < 0) { + kill_on_error; + goto wait_for_pid_sync; + } + } + else { + break; + } + max_attempts--; + } + } + else { +wait_for_pid_sync: + if (waitpid(cgi_pid, &waitpid_status, 0) < 0) { + uwsgi_error("waitpid()"); + } } return UWSGI_OK; From 952c4ce854fec68a7ac78c9fe3a0fc5b4c9dc1e9 Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Sat, 22 Feb 2014 11:13:50 +0100 Subject: [PATCH 02/21] minor fixes in non-blocking reads --- core/io.c | 2 ++ plugins/cgi/cgi_plugin.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/io.c b/core/io.c index 03560b86..6ff1a0c5 100644 --- a/core/io.c +++ b/core/io.c @@ -967,6 +967,7 @@ int uwsgi_read_nb(int fd, char *buf, size_t remains, int timeout) { ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) { int ret; + errno = 0; ssize_t rlen = read(fd, buf, len); if (rlen > 0) { return rlen; @@ -979,6 +980,7 @@ ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) { wait: ret = uwsgi.wait_read_hook(fd, timeout); if (ret > 0) { + errno = 0; rlen = read(fd, buf, len); if (rlen > 0) { return rlen; diff --git a/plugins/cgi/cgi_plugin.c b/plugins/cgi/cgi_plugin.c index 3cf5e641..38d0d5ea 100644 --- a/plugins/cgi/cgi_plugin.c +++ b/plugins/cgi/cgi_plugin.c @@ -681,19 +681,16 @@ static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t do ssize_t rlen = 0; char *buf = uwsgi_request_body_read(wsgi_req, 8192, &rlen); if (!buf) { - close(post_pipe[1]); goto clear2; } if (buf == uwsgi.empty) break; // write data to the node if (uwsgi_write_true_nb(post_pipe[1], buf, rlen, uc.timeout)) { - close(post_pipe[1]); goto clear2; } remains -= rlen; } - close(post_pipe[1]); // wait for data char *buf = uwsgi_malloc(uc.buffer_size); From 9e6a21602a96b8389e4487e290528cd91d651963 Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Sat, 22 Feb 2014 11:40:23 +0100 Subject: [PATCH 03/21] more cgi improvements --- plugins/cgi/cgi_plugin.c | 94 +++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/plugins/cgi/cgi_plugin.c b/plugins/cgi/cgi_plugin.c index 38d0d5ea..2dcaa90e 100644 --- a/plugins/cgi/cgi_plugin.c +++ b/plugins/cgi/cgi_plugin.c @@ -732,29 +732,16 @@ clear2: // now wait for process exit/death // in async mode we need a trick... if (uwsgi.async > 1) { - int max_attempts = uc.async_max_attempts; - if (!max_attempts) max_attempts = 10; - while(max_attempts) { - pid_t diedpid = waitpid(cgi_pid, &waitpid_status, WNOHANG); - if (diedpid < 0) { - uwsgi_error("waitpid()"); - break; - } - else if (diedpid == 0) { - int ret = uwsgi.wait_milliseconds_hook(1000); - if (ret < 0) { - kill_on_error; - goto wait_for_pid_sync; - } - } - else { - break; - } - max_attempts--; + pid_t diedpid = waitpid(cgi_pid, &waitpid_status, WNOHANG); + if (diedpid < 0) { + uwsgi_error("waitpid()"); + } + else if (diedpid == 0) { + // pass the pid of the cgi to async_plagued (the after request hook will clear the process) + wsgi_req->async_plagued = (int) cgi_pid; } } else { -wait_for_pid_sync: if (waitpid(cgi_pid, &waitpid_status, 0) < 0) { uwsgi_error("waitpid()"); } @@ -763,34 +750,18 @@ wait_for_pid_sync: return UWSGI_OK; } - // close all the fd except wsgi_req->poll.fd and 2; - - for(i=0;i< (int)uwsgi.max_fd;i++) { - if (post_pipe[0] == i) { - continue; - } - if (wsgi_req->post_file) { - if (fileno(wsgi_req->post_file) == i) { - continue; - } - } - if (i != wsgi_req->fd && i != 2 && i != cgi_pipe[1]) { - close(i); - } - } - // now map wsgi_req->poll.fd (or async_post) to 0 & cgi_pipe[1] to 1 - if (post_pipe[0] != 0) { - dup2(post_pipe[0], 0); - close(post_pipe[0]); - } - -#ifdef UWSGI_DEBUG - uwsgi_log("mapping cgi_pipe %d to 1\n", cgi_pipe[1]); -#endif + dup2(post_pipe[0], 0); + close(post_pipe[0]); dup2(cgi_pipe[1],1); - + close(cgi_pipe[1]); + + // close all the fd > 2 + for(i=3;i<(int)uwsgi.max_fd;i++) { + close(i); + } + // fill cgi env for(i=0;ivar_cnt;i++) { // no need to free the putenv() memory @@ -954,6 +925,39 @@ wait_for_pid_sync: static void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) { + if (wsgi_req->async_plagued > 0) { + int waitpid_status; + pid_t cgi_pid = (pid_t) wsgi_req->async_plagued; + int max_attempts = uc.async_max_attempts; + if (!max_attempts) max_attempts = 10; + while(max_attempts) { + pid_t diedpid = waitpid(cgi_pid, &waitpid_status, WNOHANG); + if (diedpid < 0) { + uwsgi_error("waitpid()"); + break; + } + else if (diedpid == 0) { + int ret = uwsgi.wait_milliseconds_hook(1000); + if (ret < 0) { + kill_on_error + if (waitpid(cgi_pid, &waitpid_status, 0) < 0) { + uwsgi_error("waitpid()"); + } + } + } + else { + break; + } + max_attempts--; + } + if (max_attempts == 0) { + kill_on_error + if (waitpid(cgi_pid, &waitpid_status, 0) < 0) { + uwsgi_error("waitpid()"); + } + } + } + log_request(wsgi_req); } From 5e276b43ad699e39631d2b6df4a84e6624122253 Mon Sep 17 00:00:00 2001 From: Unbit Date: Mon, 24 Feb 2014 09:14:14 +0100 Subject: [PATCH 04/21] fix poll() usage in #546 --- core/io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/io.c b/core/io.c index 6ff1a0c5..30334dce 100644 --- a/core/io.c +++ b/core/io.c @@ -978,6 +978,7 @@ ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) { } return -1; wait: + errno = 0; ret = uwsgi.wait_read_hook(fd, timeout); if (ret > 0) { errno = 0; From a7e6dfc469cf67850a23d99be7290bcd696b9a3d Mon Sep 17 00:00:00 2001 From: Unbit Date: Tue, 25 Feb 2014 07:05:46 +0100 Subject: [PATCH 05/21] fixed python 3 on old compilers, fixes #551 --- plugins/python/wsgi_subhandler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/python/wsgi_subhandler.c b/plugins/python/wsgi_subhandler.c index f57a16de..7eb57b08 100644 --- a/plugins/python/wsgi_subhandler.c +++ b/plugins/python/wsgi_subhandler.c @@ -21,12 +21,13 @@ int uwsgi_python_send_body(struct wsgi_request *wsgi_req, PyObject *chunk) { char *content = NULL; size_t content_len = 0; - if (!up.wsgi_accept_buffer && !wsgi_req->is_raw) goto strict; #if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER) Py_buffer pbuf; int has_buffer = 0; #endif + if (!up.wsgi_accept_buffer && !wsgi_req->is_raw) goto strict; + #if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER) if (PyObject_CheckBuffer(chunk)) { if (!PyObject_GetBuffer(chunk, &pbuf, PyBUF_SIMPLE)) { From 3480c30674f239185ec3a362c2f45d1fc591505f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Tue, 25 Feb 2014 17:47:12 +0000 Subject: [PATCH 06/21] perl: Don't run BEGIN blocks twice in the provided *.psgi The psgi loaded was calling perl_parse() with the script ostensibly to set up xsinit. However it would also call perl_parse() with the path to our *.psgi file, whith the result that any BEGIN block in the *.psgi file would be run twice, but anything outside BEGIN blocks would only run once. This means that any code within explicit BEGIN blocks will run twice, and any "use" statement in the *.psgi file will run its import() routine twice, but due to the module being in %INC already we won't actually compile things twice. The previous behavior dates all the way back to the initial introduction of the PSGI plugin in 299fd9c. Then when support for local::lib was added in 7cbe751 we initially did a perl_eval_pv() of a "use" statement like I'm doing here again now, but later on in 1561dd3 changed it to call perl_parse with the commit message "another PSGI loading fix". Since there's no info on what that fixed or what was broken before I have no idea if I'm introducing a regression here, but I don't see why this way of loding local::lib shouldn't work, and it correctly munges @INC for me when I try it. We may still have this bug in the remaining perl_parse() calls that remain for supporting "preinit" and "mule". I haven't tested those modes (I don't use them), but when we load the Perl apps we should only perl_parse() once with -e1, and then perl_eval_pv() to actually load the application. We should not call perl_parse() on code that we're just about to perl_eval_pv(), or we'll run into this bug. To test this just run: ./uwsgi --http 127.0.0.1:8080 --psgi ./t/perl/test.psgi It'll no longer PANIC on the BEGIN block being run twice now, at least in that simplistic non-"preinit" non-"mule" mode. --- plugins/psgi/psgi_loader.c | 33 ++++++++++++++------------------- t/perl/test.psgi | 4 ++++ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/plugins/psgi/psgi_loader.c b/plugins/psgi/psgi_loader.c index f8cc4b8f..dceaf1b8 100644 --- a/plugins/psgi/psgi_loader.c +++ b/plugins/psgi/psgi_loader.c @@ -368,31 +368,26 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe uperl.tmp_current_i = i; - - if (uperl.locallib) { - uwsgi_log("using %s as local::lib directory\n", uperl.locallib); - uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib); - uperl.embedding[2] = app_name; - if (perl_parse(interpreters[i], xs_init, 3, uperl.embedding, NULL)) { - // what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff... - free(uperl.embedding[1]); - uperl.embedding[1] = app_name; - free(callables); - uwsgi_perl_free_stashes(); - goto clear; - } - free(uperl.embedding[1]); - uperl.embedding[1] = app_name; - } - else { - if (perl_parse(interpreters[i], xs_init, 2, uperl.embedding, NULL)) { + // We need to initialize the interpreter to execute + // our xs_init hook, but we're *not* calling it with + // uperl.embedding as an argument so we won't execute + // BEGIN blocks in app_name twice. + { + char *perl_init_arg[] = { "", "-e", "1" }; + 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); uwsgi_perl_free_stashes(); goto clear; - } + } } + if (uperl.locallib) { + uwsgi_log("using %s as local::lib directory\n", uperl.locallib); + char *local_lib_use = uwsgi_concat3("use local::lib qw(", uperl.locallib, ");"); + perl_eval_pv(local_lib_use, 1); + free(local_lib_use); + } perl_eval_pv("use IO::Handle;", 1); perl_eval_pv("use IO::File;", 1); perl_eval_pv("use IO::Socket;", 1); diff --git a/t/perl/test.psgi b/t/perl/test.psgi index 1e7a6bc6..2535e36a 100644 --- a/t/perl/test.psgi +++ b/t/perl/test.psgi @@ -1,5 +1,9 @@ use strict; use warnings; +BEGIN { + die "PANIC: We should only load this once" if ++$main::count_BEGIN > 1; +} +die "PANIC: We should only run this once" if ++$main::count_runs > 1; uwsgi::register_rpc('hello', sub { my ($one, $two, $three) = @_; From c5d7d30439d90fee3d397713fdb43d86b995aab9 Mon Sep 17 00:00:00 2001 From: Unbit Date: Wed, 26 Feb 2014 11:39:00 +0100 Subject: [PATCH 07/21] try to better address #553 --- plugins/psgi/psgi_loader.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/plugins/psgi/psgi_loader.c b/plugins/psgi/psgi_loader.c index dceaf1b8..c6f49803 100644 --- a/plugins/psgi/psgi_loader.c +++ b/plugins/psgi/psgi_loader.c @@ -313,9 +313,6 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe char *app_name = uwsgi_concat2n(app, app_len, "", 0); - size_t size; - char *buf = uwsgi_open_and_read(app_name, &size, 1, NULL); - if (uwsgi_file_exists(app_name)) { // prepare for $0 (if the file is local) uperl.embedding[1] = app_name; @@ -373,7 +370,7 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe // uperl.embedding as an argument so we won't execute // BEGIN blocks in app_name twice. { - char *perl_init_arg[] = { "", "-e", "1" }; + char *perl_init_arg[] = { "", "-e", "0" }; 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); @@ -392,9 +389,6 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe perl_eval_pv("use IO::File;", 1); perl_eval_pv("use IO::Socket;", 1); perl_eval_pv("use Scalar::Util;", 1); - if (!uperl.no_die_catch) { - perl_eval_pv("use Devel::StackTrace; $SIG{__DIE__} = sub { print Devel::StackTrace->new()->as_string() };", 0); - } if (uperl.argv_items || uperl.argv_item) { AV *uperl_argv = GvAV(PL_argvgv); @@ -412,12 +406,26 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe } } - SV *dollar_zero = get_sv("0", GV_ADD); sv_setsv(dollar_zero, newSVpv(app, app_len)); - callables[i] = perl_eval_pv(uwsgi_concat4("#line 1 ", app_name, "\n", buf), 0); - if (!callables[i]) { + SV *has_plack = perl_eval_pv("use Plack::Util;", 0); + if (!has_plack || SvTRUE(ERRSV)) { + uwsgi_log("Plack::Util is not installed, using \"do\" instead of \"load_psgi\"\n"); + char *code = uwsgi_concat3("do '", app_name, "';"); + callables[i] = perl_eval_pv(code, 0); + free(code); + } + else { + char *code = uwsgi_concat3("Plack::Util::load_psgi '", app_name , "';"); + callables[i] = perl_eval_pv(code, 0); + free(code); + } + + if (!callables[i] || SvTYPE(callables[i]) == SVt_NULL || SvTRUE(ERRSV)) { + if (SvTRUE(ERRSV)) { + uwsgi_log("%s", SvPV_nolen(ERRSV)); + } uwsgi_log("unable to find PSGI function entry point.\n"); // what to do here ? i hope no-one will use threads with dynamic apps... free(callables); @@ -425,11 +433,13 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe goto clear; } + if (!uperl.no_die_catch) { + perl_eval_pv("use Devel::StackTrace; $SIG{__DIE__} = sub { print Devel::StackTrace->new()->as_string() };", 0); + } + PERL_SET_CONTEXT(interpreters[0]); } - free(buf); - if(SvTRUE(ERRSV)) { uwsgi_log("%s", SvPV_nolen(ERRSV)); free(callables); From 30eebfd335f801a50a3043a7ece9b0940ac2497d Mon Sep 17 00:00:00 2001 From: Unbit Date: Wed, 26 Feb 2014 12:07:00 +0100 Subject: [PATCH 08/21] better perl do usage and --perl-no-plack flag --- plugins/psgi/psgi.h | 2 ++ plugins/psgi/psgi_loader.c | 12 +++++++++--- plugins/psgi/psgi_plugin.c | 2 ++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/plugins/psgi/psgi.h b/plugins/psgi/psgi.h index 264704b4..92e6b588 100644 --- a/plugins/psgi/psgi.h +++ b/plugins/psgi/psgi.h @@ -65,6 +65,8 @@ struct uwsgi_perl { int shell_oneshot; CV *spooler; + + int no_plack; }; void init_perl_embedded_module(void); diff --git a/plugins/psgi/psgi_loader.c b/plugins/psgi/psgi_loader.c index c6f49803..015cd8bc 100644 --- a/plugins/psgi/psgi_loader.c +++ b/plugins/psgi/psgi_loader.c @@ -409,10 +409,16 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe SV *dollar_zero = get_sv("0", GV_ADD); sv_setsv(dollar_zero, newSVpv(app, app_len)); - SV *has_plack = perl_eval_pv("use Plack::Util;", 0); + SV *has_plack = NULL; + if (!uperl.no_plack) { + has_plack = perl_eval_pv("use Plack::Util;", 0); + } + if (!has_plack || SvTRUE(ERRSV)) { - uwsgi_log("Plack::Util is not installed, using \"do\" instead of \"load_psgi\"\n"); - char *code = uwsgi_concat3("do '", app_name, "';"); + if (!uperl.no_plack) { + uwsgi_log("Plack::Util is not installed, using \"do\" instead of \"load_psgi\"\n"); + } + char *code = uwsgi_concat3("my $app = do '", app_name, "'; if ( !$app && ( my $error = $@ || $! )) { die $error; }; $app"); callables[i] = perl_eval_pv(code, 0); free(code); } diff --git a/plugins/psgi/psgi_plugin.c b/plugins/psgi/psgi_plugin.c index d5ebe9f5..f0979ac1 100644 --- a/plugins/psgi/psgi_plugin.c +++ b/plugins/psgi/psgi_plugin.c @@ -44,6 +44,8 @@ struct uwsgi_option uwsgi_perl_options[] = { {"plshell", optional_argument, 0, "run a perl interactive shell", uwsgi_opt_plshell, NULL, 0}, {"plshell-oneshot", no_argument, 0, "run a perl interactive shell (one shot)", uwsgi_opt_plshell, NULL, 0}, + + {"perl-no-plack", no_argument, 0, "force the use of do instead of Plack::Util::load_psgi", uwsgi_opt_true, &uperl.no_plack, 0}, {0, 0, 0, 0, 0, 0, 0}, }; From 757c76b5696b34f816f1ed9563cc76ce0958703c Mon Sep 17 00:00:00 2001 From: Unbit Date: Wed, 26 Feb 2014 12:12:41 +0100 Subject: [PATCH 09/21] fix -bash in perl hooks --- plugins/psgi/psgi_loader.c | 2 ++ plugins/psgi/psgi_plugin.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/plugins/psgi/psgi_loader.c b/plugins/psgi/psgi_loader.c index 015cd8bc..df9ff431 100644 --- a/plugins/psgi/psgi_loader.c +++ b/plugins/psgi/psgi_loader.c @@ -515,6 +515,8 @@ void uwsgi_psgi_preinit_apps() { perl_parse(uperl.main[0], xs_init, 3, uperl.embedding, NULL); struct uwsgi_string_list *usl; uwsgi_foreach(usl, uperl.exec) { + SV *dollar_zero = get_sv("0", GV_ADD); + sv_setsv(dollar_zero, newSVpv(usl->value, usl->len)); uwsgi_perl_exec(usl->value); } } diff --git a/plugins/psgi/psgi_plugin.c b/plugins/psgi/psgi_plugin.c index f0979ac1..a764cb2c 100644 --- a/plugins/psgi/psgi_plugin.c +++ b/plugins/psgi/psgi_plugin.c @@ -707,6 +707,8 @@ void uwsgi_perl_post_fork() { struct uwsgi_string_list *usl; uwsgi_foreach(usl, uperl.exec_post_fork) { + SV *dollar_zero = get_sv("0", GV_ADD); + sv_setsv(dollar_zero, newSVpv(usl->value, usl->len)); uwsgi_perl_exec(usl->value); } From d3493df032c07bde80265a258034e010023d6c51 Mon Sep 17 00:00:00 2001 From: Unbit Date: Wed, 26 Feb 2014 17:06:21 +0100 Subject: [PATCH 10/21] do not expode if Devel::StackTrace is missing --- plugins/psgi/psgi_loader.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/plugins/psgi/psgi_loader.c b/plugins/psgi/psgi_loader.c index df9ff431..bc2515a0 100644 --- a/plugins/psgi/psgi_loader.c +++ b/plugins/psgi/psgi_loader.c @@ -441,18 +441,14 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe if (!uperl.no_die_catch) { perl_eval_pv("use Devel::StackTrace; $SIG{__DIE__} = sub { print Devel::StackTrace->new()->as_string() };", 0); + if(SvTRUE(ERRSV)) { + uwsgi_log("%s", SvPV_nolen(ERRSV)); + } } PERL_SET_CONTEXT(interpreters[0]); } - if(SvTRUE(ERRSV)) { - uwsgi_log("%s", SvPV_nolen(ERRSV)); - free(callables); - uwsgi_perl_free_stashes(); - goto clear; - } - if (uwsgi_apps_cnt >= uwsgi.max_apps) { uwsgi_log("ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps); goto clear; From b0159ea23ba21f595d2a09b756297e461800da02 Mon Sep 17 00:00:00 2001 From: Unbit Date: Wed, 26 Feb 2014 17:06:47 +0100 Subject: [PATCH 11/21] prepare for 2.0.2 --- uwsgi.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uwsgi.gemspec b/uwsgi.gemspec index fcbb9b0a..cccfa6b8 100644 --- a/uwsgi.gemspec +++ b/uwsgi.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |s| s.name = 'uwsgi' s.license = 'GPL-2' s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'') - s.date = '2014-02-09' + s.date = '2014-02-26' s.summary = "uWSGI" s.description = "The uWSGI server for Ruby/Rack" s.authors = ["Unbit"] From 5d76b63fac95bf0ac33330e7ffaf4c89eed1048c Mon Sep 17 00:00:00 2001 From: Unbit Date: Sat, 1 Mar 2014 08:25:35 +0100 Subject: [PATCH 12/21] fixed #555 --- core/spooler.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/spooler.c b/core/spooler.c index 2245ecee..cc92c701 100644 --- a/core/spooler.c +++ b/core/spooler.c @@ -190,6 +190,11 @@ static void spooler_req_parser_hook(char *key, uint16_t key_len, char *value, ui } 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; } From 8c118c8f6291b2f7874efdf36f2718c5d3f9b128 Mon Sep 17 00:00:00 2001 From: Unbit Date: Sun, 2 Mar 2014 09:36:17 +0100 Subject: [PATCH 13/21] fixed (and improved) on demand emperor socket --- core/emperor.c | 94 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 20 deletions(-) diff --git a/core/emperor.c b/core/emperor.c index d30a4955..169c6ea7 100644 --- a/core/emperor.c +++ b/core/emperor.c @@ -39,6 +39,59 @@ struct uwsgi_emperor_blacklist_item { 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; + us.sa_in.sin_addr.s_addr = inet_addr(socket_name); + *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 (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 +210,7 @@ static char *emperor_check_on_demand_socket(char *filename) { 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;isocket_name); } + if (c_ui->on_demand_fd != -1) { + close(c_ui->on_demand_fd); + } + free(c_ui); } @@ -637,8 +694,10 @@ void emperor_stop(struct uwsgi_instance *c_ui) { 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; @@ -797,18 +856,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha // 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); @@ -1743,12 +1791,18 @@ void emperor_loop() { 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)) { + uwsgi_error("[emperor] kill"); + } + break; } - break; } } From 7e4341a7cd064d6e368cbcc45c3f59708e4585c9 Mon Sep 17 00:00:00 2001 From: Unbit Date: Sun, 2 Mar 2014 10:14:58 +0100 Subject: [PATCH 14/21] force on demand unix socket to 666 --- core/emperor.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/emperor.c b/core/emperor.c index 169c6ea7..3b8676b6 100644 --- a/core/emperor.c +++ b/core/emperor.c @@ -81,6 +81,12 @@ static int on_demand_bind(char *socket_name) { goto error; } + if (!is_tcp) { + if (chmod(socket_name, 0666)) { + goto error; + } + } + if (listen(fd, uwsgi.listen_queue) != 0) { goto error; } From 3965c01880f04e36a5268bfadcda2e1a9b3d757a Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Tue, 4 Mar 2014 05:44:18 +0100 Subject: [PATCH 15/21] on __APPLE__ use LOG_NOTICE for syslog plugin --- plugins/syslog/syslog_plugin.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/syslog/syslog_plugin.c b/plugins/syslog/syslog_plugin.c index acebccf3..a1cfa5c7 100644 --- a/plugins/syslog/syslog_plugin.c +++ b/plugins/syslog/syslog_plugin.c @@ -93,7 +93,11 @@ ssize_t uwsgi_syslog_logger(struct uwsgi_logger *ul, char *message, size_t len) ul->configured = 1; } +#ifdef __APPLE__ + syslog(LOG_NOTICE, "%.*s", (int) len, message); +#else syslog(LOG_INFO, "%.*s", (int) len, message); +#endif return 0; } From 367c4b9bab280de95477153e9b5577d790e971cb Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Tue, 4 Mar 2014 06:08:16 +0100 Subject: [PATCH 16/21] added on_demand sockets support to mongodb Emperor plugin --- plugins/emperor_mongodb/emperor_mongodb.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/emperor_mongodb/emperor_mongodb.cc b/plugins/emperor_mongodb/emperor_mongodb.cc index 0719cb9a..b92117f5 100644 --- a/plugins/emperor_mongodb/emperor_mongodb.cc +++ b/plugins/emperor_mongodb/emperor_mongodb.cc @@ -20,7 +20,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues 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; @@ -40,6 +40,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues 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 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues } 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); } From 536ae8d01389d8575c130893b55fbfe4af08d538 Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Tue, 4 Mar 2014 06:32:40 +0100 Subject: [PATCH 17/21] fixed mongrel2 post_fork hook --- plugins/mongrel2/mongrel2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/mongrel2/mongrel2.c b/plugins/mongrel2/mongrel2.c index 198ac1d3..bd8f3691 100644 --- a/plugins/mongrel2/mongrel2.c +++ b/plugins/mongrel2/mongrel2.c @@ -574,6 +574,7 @@ static void mongrel2_register_proto() { 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()"); @@ -653,6 +654,7 @@ static void mongrel2_connect() { #else uwsgi_sock->recv_flag = ZMQ_NOBLOCK; #endif +next: uwsgi_sock = uwsgi_sock->next; } } From 839638a0ad7e82d63add7b095d5454bc55ce2dd1 Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Tue, 4 Mar 2014 06:38:42 +0100 Subject: [PATCH 18/21] report socket name on invalid zeromq syntax --- plugins/mongrel2/mongrel2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mongrel2/mongrel2.c b/plugins/mongrel2/mongrel2.c index bd8f3691..708a758f 100644 --- a/plugins/mongrel2/mongrel2.c +++ b/plugins/mongrel2/mongrel2.c @@ -582,7 +582,7 @@ static void mongrel2_connect() { } 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); From 62d74951db53c95dbf77210a5defc60f23d6e187 Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Wed, 5 Mar 2014 08:28:17 +0100 Subject: [PATCH 19/21] support for git-based plugins --- uwsgiconfig.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/uwsgiconfig.py b/uwsgiconfig.py index c40835e9..cdde3aa8 100644 --- a/uwsgiconfig.py +++ b/uwsgiconfig.py @@ -367,6 +367,15 @@ def build_uwsgi(uc, print_only=False, gcll=None): 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] From 332fab2150f47379ad2166c40b9fbeef3a2aa878 Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Fri, 7 Mar 2014 07:31:42 +0100 Subject: [PATCH 20/21] hack for avoiding libmongoclient to crash on broken cursor --- plugins/emperor_mongodb/emperor_mongodb.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/emperor_mongodb/emperor_mongodb.cc b/plugins/emperor_mongodb/emperor_mongodb.cc index b92117f5..7960e42d 100644 --- a/plugins/emperor_mongodb/emperor_mongodb.cc +++ b/plugins/emperor_mongodb/emperor_mongodb.cc @@ -31,7 +31,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues // run the query std::auto_ptr 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 @@ -78,6 +78,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues 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 From d2474244423c204509a123e8ae5850f9a315b421 Mon Sep 17 00:00:00 2001 From: Unbit Date: Fri, 7 Mar 2014 16:09:04 +0100 Subject: [PATCH 21/21] more useful log alarm --- core/alarm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/alarm.c b/core/alarm.c index 3a1fe46c..eb50ea7b 100644 --- a/core/alarm.c +++ b/core/alarm.c @@ -18,18 +18,18 @@ void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) { 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); } } }