Hello community, here is the log from the commit of package uwsgi for openSUSE:Factory checked in at 2020-11-29 12:29:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/uwsgi (Old) and /work/SRC/openSUSE:Factory/.uwsgi.new.5913 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "uwsgi" Sun Nov 29 12:29:30 2020 rev:39 rq:851302 version:2.0.19.1 Changes: -------- --- /work/SRC/openSUSE:Factory/uwsgi/uwsgi.changes 2020-09-21 17:26:17.616077832 +0200 +++ /work/SRC/openSUSE:Factory/.uwsgi.new.5913/uwsgi.changes 2020-11-29 12:29:31.734068970 +0100 @@ -1,0 +2,38 @@ +Thu Nov 26 18:51:29 UTC 2020 - Dirk Mueller <[email protected]> + +- update 2.0.19.1: + * Reverted CGI chunked encoding support + * Fixed bug with WSGI responses returning + * Update travis to xenial (Terence D. Honles) + * Fix segfault in logsocket plugin (Riccardo Magliocchetti, #2010) + * Backport Coverity fixes from master (Riccardo Magliocchetti) + * Fix Python 3.7 warnings (Orivej Desh) + * Fix uwsgi.workers() leak in Python plugin (Arne Welzel, #2056) + * Backport redislog plugin 32-bit build fixes (Riccardo Magliocchetti, #1828) + * Fix stack overflow in core/rpc (Nicola Martino) + * Fix build with spaces in the path (Arne Welzel, #1939) + * Add missing initialization for zend_file_handle in php plugin (Arne Welzel) + * Build Python 3.7 and 3.8 plugins in CI (Arne Welzel) + * Add Trove classifiers for Python 3.7 and 3.8 (Hugo) + * Graceful shutdown for vassals (Sponsored by guppyltd.com) + * Improve yaml parsing with libyaml (Arne Welzel, #2097) + * Add smart-daemon2 option to notify daemon of master reloading (Eduardo Felipe Castegnaro) + * Do not chroot multiple times when root (Arne Welzel) + * Support io.BytesIO with wsgi.file_wrapper (Arne Welzel, #1126) + * Add websocket continuation frames support (Timi, #1350) + * Fix compilation with gevent 1.5.0 (Vytautas Liuolia) + * Fix PSGI plugin build with gcc 10 (Jorge Gallegos) + * Get rid of paste.script dependency in pypy/python plugins (Thomas De Schampheleire) + * Improve performance for santitizing file descriptors with cgi plugin (Natanael Copa, #2053) + * Fix offload-threads with honour-range (Liss Tarnell) + * Fix logging packet size length overflow (Pawel Marokwsi) + * Fix possible deadlock in install (Jacob Tolar) + * Fix parsing of http port for ipv6 (Cyril Baÿ) + * Fix impossibility of determining the end of the chunked stream with psgi plugin (ols) + * Fix parsing of http-socket port for ipv6 (Daniel Holth) + * Add chunked request decoding to the CGI plugin (Robert Schindler) + * Add add max-worker-lifetime-delta to reload workers with a delta (Marcin Lulek , #2020) + +- remove uwsgi-2.0.18-psgi-fix-duplicate-uperl.patch (upstream) + +------------------------------------------------------------------- Old: ---- uwsgi-2.0.18-psgi-fix-duplicate-uperl.patch uwsgi-2.0.18.tar.gz New: ---- uwsgi-2.0.19.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ uwsgi.spec ++++++ --- /var/tmp/diff_new_pack.B3JCiD/_old 2020-11-29 12:29:32.494069739 +0100 +++ /var/tmp/diff_new_pack.B3JCiD/_new 2020-11-29 12:29:32.498069744 +0100 @@ -17,7 +17,7 @@ Name: uwsgi -Version: 2.0.18 +Version: 2.0.19.1 Release: 0 Summary: Application Container Server for Networked/Clustered Web Applications License: Apache-2.0 AND GPL-2.0-only WITH GCC-exception-2.0 @@ -43,8 +43,6 @@ Patch3: uwsgi-1.9.11-systemd_logger-old_systemd.patch # PATCH-FIX-OPENSUSE uwsgi-2.0.18-postgresql-config.patch - Use pkg-config instead of pg_config Patch4: uwsgi-2.0.18-postgresql-config.patch -# PATCH-FIX-OPENSUSE uwsgi-2.0.18-psgi-fix-duplicate-uperl.patch - Fix duplicate uperl with gcc 10 -Patch5: uwsgi-2.0.18-psgi-fix-duplicate-uperl.patch %define apache_branch %(rpm -q --qf %%{version} apache2 | grep -E -o "2\\.[0-9]+") %if "%{apache_branch}" == "2.4" %define apxs %{_bindir}/apxs2 @@ -439,7 +437,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.18.tar.gz -> uwsgi-2.0.19.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/.travis.yml new/uwsgi-2.0.19.1/.travis.yml --- old/uwsgi-2.0.18/.travis.yml 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/.travis.yml 2020-06-17 11:03:34.000000000 +0200 @@ -1,3 +1,5 @@ +dist: xenial + language: c compiler: @@ -23,6 +25,12 @@ - echo -e "\n\n>>> Building python36 plugin" - /usr/bin/python3.6 -V - /usr/bin/python3.6 uwsgiconfig.py --plugin plugins/python base python36 + - echo -e "\n\n>>> Building python37 plugin" + - /usr/bin/python3.7 -V + - /usr/bin/python3.7 uwsgiconfig.py --plugin plugins/python base python37 + - echo -e "\n\n>>> Building python38 plugin" + - /usr/bin/python3.8 -V + - /usr/bin/python3.8 uwsgiconfig.py --plugin plugins/python base python38 - echo -e "\n\n>>> Building rack plugin" - rvm use 2.4 - ruby -v @@ -35,10 +43,13 @@ - ./tests/travis.sh before_install: + - sudo apt-get update -qq + - sudo apt-get install -qqyf software-properties-common - sudo add-apt-repository ppa:deadsnakes/ppa -y - sudo add-apt-repository ppa:ondrej/php -y - sudo apt-get update -qq - - sudo apt-get install -qqyf python2.6-dev python3.4-dev python3.5-dev python3.6-dev + - sudo apt-get install -qqyf python{2.6,3.4,3.5,3.6,3.7,3.8}-dev + - sudo apt-get install -qqyf python3.8-distutils - sudo apt-get install -qqyf libxml2-dev libpcre3-dev libcap2-dev - sudo apt-get install -qqyf php7.2-dev libphp7.2-embed libargon2-0-dev libsodium-dev - sudo apt-get install -qqyf liblua5.1-0-dev @@ -49,6 +60,6 @@ - sudo apt-get install -qqyf libwrap0-dev libgeoip-dev libv8-dev libxslt1-dev - sudo apt-get install -qqyf libboost-thread-dev libboost-filesystem-dev - sudo apt-get install -qqyf libssl-dev libacl1-dev python-greenlet-dev - - sudo apt-get install -qqyf openjdk-7-jdk libgloox-dev gccgo + - sudo apt-get install -qqyf openjdk-8-jdk libgloox-dev gccgo - sudo apt-get install -qqyf cli-common-dev mono-devel mono-mcs uuid-dev - sudo apt-get install -qqyf curl diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/CONTRIBUTORS new/uwsgi-2.0.19.1/CONTRIBUTORS --- old/uwsgi-2.0.18/CONTRIBUTORS 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/CONTRIBUTORS 2020-06-17 11:03:34.000000000 +0200 @@ -32,3 +32,7 @@ Adriano Di Luzio ([email protected]) Curtis Maloney Vladimir Didenko +Alexandre Bonnetain +Darvame Hleran +Sokolov Yura <[email protected]> +Marcin Lulek <[email protected]> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/PKG-INFO new/uwsgi-2.0.19.1/PKG-INFO --- old/uwsgi-2.0.18/PKG-INFO 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/PKG-INFO 2020-06-17 11:03:34.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: uWSGI -Version: 2.0.18 +Version: 2.0.19.1 Summary: The uWSGI server Home-page: https://uwsgi-docs.readthedocs.io/en/latest/ Author: Unbit diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/daemons.c new/uwsgi-2.0.19.1/core/daemons.c --- old/uwsgi-2.0.18/core/daemons.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/daemons.c 2020-06-17 11:03:34.000000000 +0200 @@ -254,6 +254,16 @@ // unregister daemon to prevent it from being respawned ud->registered = 0; } + + // smart daemons that have to be notified when master is reloading or stopping + if (ud->notifypid && ud->pid > 0 && ud->pidfile) { + if (uwsgi_instance_is_reloading) { + kill(-(ud->pid), ud->reload_signal > 0 ? ud->reload_signal : SIGHUP); + } + else { + kill(-(ud->pid), ud->stop_signal); + } + } ud = ud->next; } } @@ -520,6 +530,7 @@ char *d_ns_pid = NULL; char *d_chdir = NULL; char *d_max_throttle = NULL; + char *d_notifypid = NULL; char *arg = uwsgi_str(value); @@ -543,6 +554,7 @@ "ns_pid", &d_ns_pid, "chdir", &d_chdir, "max_throttle", &d_max_throttle, + "notifypid", &d_notifypid, NULL)) { uwsgi_log("invalid --%s keyval syntax\n", opt); exit(1); @@ -594,6 +606,8 @@ uwsgi_ud->max_throttle = d_max_throttle ? atoi(d_max_throttle) : 0; + uwsgi_ud->notifypid = d_notifypid ? 1 : 0; + if (d_touch) { size_t i,rlen = 0; char **argv = uwsgi_split_quoted(d_touch, strlen(d_touch), ";", &rlen); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/emperor.c new/uwsgi-2.0.19.1/core/emperor.c --- old/uwsgi-2.0.18/core/emperor.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/emperor.c 2020-06-17 11:03:34.000000000 +0200 @@ -722,7 +722,7 @@ // remove uWSGI instance if (c_ui->pid != -1) { - if (write(c_ui->pipe[0], "\0", 1) != 1) { + if (write(c_ui->pipe[0], uwsgi.emperor_graceful_shutdown ? "\2" : "\0", 1) != 1) { uwsgi_error("emperor_stop()/write()"); } } @@ -739,7 +739,7 @@ // remove uWSGI instance if (c_ui->pid != -1) { - if (write(c_ui->pipe[0], "\0", 1) != 1) { + if (write(c_ui->pipe[0], uwsgi.emperor_graceful_shutdown ? "\2" : "\0", 1) != 1) { uwsgi_error("emperor_stop()/write()"); } } @@ -2410,8 +2410,9 @@ if (byte == 0) { uwsgi_hooks_run(uwsgi.hook_emperor_stop, "emperor-stop", 0); close(uwsgi.emperor_fd); - if (!uwsgi.status.brutally_reloading) + if (!uwsgi.status.brutally_reloading && !uwsgi.status.brutally_destroying) { kill_them_all(0); + } } // reload me else if (byte == 1) { @@ -2422,6 +2423,14 @@ grace_them_all(0); uwsgi_unblock_signal(SIGHUP); } + // remove me gracefully + else if (byte == 2) { + uwsgi_hooks_run(uwsgi.hook_emperor_stop, "emperor-stop", 0); + close(uwsgi.emperor_fd); + if (!uwsgi.status.brutally_reloading && !uwsgi.status.brutally_destroying) { + gracefully_kill_them_all(0); + } + } } #ifdef UWSGI_EVENT_USE_PORT // special cose for port event system diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/fifo.c new/uwsgi-2.0.19.1/core/fifo.c --- old/uwsgi-2.0.18/core/fifo.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/fifo.c 2020-06-17 11:03:34.000000000 +0200 @@ -104,7 +104,9 @@ char *path = uwsgi_fifo_by_slot(); - unlink(path); + if (unlink(path) != 0 && errno != ENOENT) { + uwsgi_error("uwsgi_master_fifo()/unlink()"); + } if (mkfifo(path, S_IRUSR|S_IWUSR)) { uwsgi_error("uwsgi_master_fifo()/mkfifo()"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/logging.c new/uwsgi-2.0.19.1/core/logging.c --- old/uwsgi-2.0.18/core/logging.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/logging.c 2020-06-17 11:03:34.000000000 +0200 @@ -752,10 +752,11 @@ i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss); if (i != 2) { uwsgi_log("warning: invalid record in /proc/self/stat\n"); + } else { + *rss = *rss * uwsgi.page_size; } fclose(procfile); } - *rss = *rss * uwsgi.page_size; #elif defined(__CYGWIN__) // same as Linux but rss is not in pages... FILE *procfile; @@ -1082,19 +1083,18 @@ return strlen(*buf); } - static ssize_t uwsgi_lf_rsize(struct wsgi_request *wsgi_req, char **buf) { - *buf = uwsgi_num2str(wsgi_req->response_size); + *buf = uwsgi_size2str(wsgi_req->response_size); return strlen(*buf); } static ssize_t uwsgi_lf_hsize(struct wsgi_request *wsgi_req, char **buf) { - *buf = uwsgi_num2str(wsgi_req->headers_size); + *buf = uwsgi_size2str(wsgi_req->headers_size); return strlen(*buf); } static ssize_t uwsgi_lf_size(struct wsgi_request *wsgi_req, char **buf) { - *buf = uwsgi_num2str(wsgi_req->headers_size+wsgi_req->response_size); + *buf = uwsgi_size2str(wsgi_req->headers_size+wsgi_req->response_size); return strlen(*buf); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/master_checks.c new/uwsgi-2.0.19.1/core/master_checks.c --- old/uwsgi-2.0.18/core/master_checks.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/master_checks.c 2020-06-17 11:03:34.000000000 +0200 @@ -218,7 +218,7 @@ // check if worker was running longer than allowed lifetime if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.max_worker_lifetime > 0) { uint64_t lifetime = uwsgi_now() - uwsgi.workers[i].last_spawn; - if (lifetime > uwsgi.max_worker_lifetime && uwsgi.workers[i].manage_next_request == 1) { + if (lifetime > (uwsgi.max_worker_lifetime + (i-1) * uwsgi.max_worker_lifetime_delta) && uwsgi.workers[i].manage_next_request == 1) { uwsgi_log("worker %d lifetime reached, it was running for %llu second(s)\n", i, (unsigned long long) lifetime); uwsgi.workers[i].manage_next_request = 0; kill(uwsgi.workers[i].pid, SIGWINCH); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/offload.c new/uwsgi-2.0.19.1/core/offload.c --- old/uwsgi-2.0.18/core/offload.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/offload.c 2020-06-17 11:03:34.000000000 +0200 @@ -671,11 +671,12 @@ uwsgi.offload_engine_pipe = uwsgi_offload_register_engine("pipe", u_offload_pipe_prepare, u_offload_pipe_do); } -int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) { +int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) { struct uwsgi_offload_request uor; uwsgi_offload_setup(uwsgi.offload_engine_sendfile, &uor, wsgi_req, 1); uor.fd = fd; uor.len = len; + uor.pos = pos; return uwsgi_offload_run(wsgi_req, &uor, NULL); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/rpc.c new/uwsgi-2.0.19.1/core/rpc.c --- old/uwsgi-2.0.18/core/rpc.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/rpc.c 2020-06-17 11:03:34.000000000 +0200 @@ -12,6 +12,11 @@ return -1; } + if (strlen(name) >= UMAX8) { + uwsgi_log("the supplied RPC name string is too long, max size is %d\n", UMAX8-1); + return -1; + } + uwsgi_lock(uwsgi.rpc_table_lock); // first check if a function is already registered diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/utils.c new/uwsgi-2.0.19.1/core/utils.c --- old/uwsgi-2.0.18/core/utils.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/utils.c 2020-06-17 11:03:34.000000000 +0200 @@ -585,13 +585,15 @@ } } - if (uwsgi.chroot && !uwsgi.reloads) { + if (uwsgi.chroot && !uwsgi.is_chrooted && !uwsgi.reloads) { if (!uwsgi.master_as_root) uwsgi_log("chroot() to %s\n", uwsgi.chroot); + if (chroot(uwsgi.chroot)) { uwsgi_error("chroot()"); exit(1); } + uwsgi.is_chrooted = 1; #ifdef __linux__ if (uwsgi.logging_options.memory_report) { uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n"); @@ -989,7 +991,7 @@ return; nonroot: - if (uwsgi.chroot && !uwsgi.is_a_reload) { + if (uwsgi.chroot && !uwsgi.is_chrooted && !uwsgi.is_a_reload) { uwsgi_log("cannot chroot() as non-root user\n"); exit(1); } @@ -1920,6 +1922,12 @@ return str; } +char *uwsgi_size2str(size_t num) { + char *str = uwsgi_malloc(sizeof(UMAX64_STR) + 1); + snprintf(str, sizeof(UMAX64_STR) + 1, "%llu", (unsigned long long) num); + return str; +} + int uwsgi_num2str2(int num, char *ptr) { return snprintf(ptr, 11, "%d", num); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/uwsgi.c new/uwsgi-2.0.19.1/core/uwsgi.c --- old/uwsgi-2.0.18/core/uwsgi.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/uwsgi.c 2020-06-17 11:03:34.000000000 +0200 @@ -239,6 +239,7 @@ #if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) {"emperor-use-clone", required_argument, 0, "use clone() instead of fork() passing the specified unshare() flags", uwsgi_opt_set_unshare, &uwsgi.emperor_clone, 0}, #endif + {"emperor-graceful-shutdown", no_argument, 0, "use vassals graceful shutdown during ragnarok", uwsgi_opt_true, &uwsgi.emperor_graceful_shutdown, 0}, #ifdef UWSGI_CAP {"emperor-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 0}, {"vassals-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 0}, @@ -275,6 +276,7 @@ {"max-requests", required_argument, 'R', "reload workers after the specified amount of managed requests", uwsgi_opt_set_64bit, &uwsgi.max_requests, 0}, {"min-worker-lifetime", required_argument, 0, "number of seconds worker must run before being reloaded (default is 60)", uwsgi_opt_set_64bit, &uwsgi.min_worker_lifetime, 0}, {"max-worker-lifetime", required_argument, 0, "reload workers after the specified amount of seconds (default is disabled)", uwsgi_opt_set_64bit, &uwsgi.max_worker_lifetime, 0}, + {"max-worker-lifetime-delta", required_argument, 0, "add (worker_id * delta) seconds to the max_worker_lifetime value of each worker", uwsgi_opt_set_int, &uwsgi.max_worker_lifetime_delta, 0}, {"socket-timeout", required_argument, 'z', "set internal sockets timeout", uwsgi_opt_set_int, &uwsgi.socket_timeout, 0}, {"no-fd-passing", no_argument, 0, "disable file descriptor passing", uwsgi_opt_true, &uwsgi.no_fd_passing, 0}, @@ -3301,7 +3303,7 @@ uwsgi_log_verbose("mem-collector thread started for worker %d\n", uwsgi.mywid); for(;;) { sleep(uwsgi.mem_collector_freq); - uint64_t rss, vsz; + uint64_t rss = 0, vsz = 0; get_memusage(&rss, &vsz); uwsgi.workers[uwsgi.mywid].rss_size = rss; uwsgi.workers[uwsgi.mywid].vsz_size = vsz; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/websockets.c new/uwsgi-2.0.19.1/core/websockets.c --- old/uwsgi-2.0.18/core/websockets.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/websockets.c 2020-06-17 11:03:34.000000000 +0200 @@ -144,6 +144,7 @@ static void uwsgi_websocket_parse_header(struct wsgi_request *wsgi_req) { uint8_t byte1 = wsgi_req->websocket_buf->buf[0]; uint8_t byte2 = wsgi_req->websocket_buf->buf[1]; + wsgi_req->websocket_is_fin = byte1 >> 7; wsgi_req->websocket_opcode = byte1 & 0xf; wsgi_req->websocket_has_mask = byte2 >> 7; wsgi_req->websocket_size = byte2 & 0x7f; @@ -161,14 +162,38 @@ } } - struct uwsgi_buffer *ub = uwsgi_buffer_new(wsgi_req->websocket_size); + struct uwsgi_buffer *ub = NULL; + if (wsgi_req->websocket_opcode == 0) { + if (uwsgi.websockets_continuation_buffer == NULL) { + uwsgi_log("Error continuation with empty previous buffer"); + goto error; + } + ub = uwsgi.websockets_continuation_buffer; + } + else { + ub = uwsgi_buffer_new(wsgi_req->websocket_size); + } if (uwsgi_buffer_append(ub, (char *) ptr, wsgi_req->websocket_size)) goto error; if (uwsgi_buffer_decapitate(wsgi_req->websocket_buf, wsgi_req->websocket_pktsize)) goto error; wsgi_req->websocket_phase = 0; wsgi_req->websocket_need = 2; + + if (wsgi_req->websocket_is_fin) { + uwsgi.websockets_continuation_buffer = NULL; + /// Freeing websockets_continuation_buffer is done by the caller + return ub; + } + uwsgi.websockets_continuation_buffer = ub; + /// Message is not complete, send empty dummy buffer to signal waiting for full message + ub = uwsgi_buffer_new(1); + uwsgi_buffer_append(ub, "\0", 1); return ub; error: uwsgi_buffer_destroy(ub); + if (uwsgi.websockets_continuation_buffer != NULL && ub != uwsgi.websockets_continuation_buffer) { + uwsgi_buffer_destroy(uwsgi.websockets_continuation_buffer); + } + uwsgi.websockets_continuation_buffer = NULL; return NULL; } @@ -338,12 +363,20 @@ return NULL; } +static void clear_continuation_buffer() { + if (uwsgi.websockets_continuation_buffer != NULL) { + uwsgi_buffer_destroy(uwsgi.websockets_continuation_buffer); + uwsgi.websockets_continuation_buffer = NULL; + } +} + struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *wsgi_req) { if (wsgi_req->websocket_closed) { return NULL; } struct uwsgi_buffer *ub = uwsgi_websocket_recv_do(wsgi_req, 0); if (!ub) { + clear_continuation_buffer(); wsgi_req->websocket_closed = 1; } return ub; @@ -355,6 +388,7 @@ } struct uwsgi_buffer *ub = uwsgi_websocket_recv_do(wsgi_req, 1); if (!ub) { + clear_continuation_buffer(); wsgi_req->websocket_closed = 1; } return ub; @@ -432,4 +466,5 @@ uwsgi.websockets_ping_freq = 30; uwsgi.websockets_pong_tolerance = 3; uwsgi.websockets_max_size = 1024; + uwsgi.websockets_continuation_buffer = NULL; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/writer.c new/uwsgi-2.0.19.1/core/writer.c --- old/uwsgi-2.0.18/core/writer.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/writer.c 2020-06-17 11:03:34.000000000 +0200 @@ -634,7 +634,7 @@ fd = tmp_fd; can_close = 1; } - if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, len)) { + if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, pos, len)) { wsgi_req->via = UWSGI_VIA_OFFLOAD; wsgi_req->response_size += len; return 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/core/yaml.c new/uwsgi-2.0.19.1/core/yaml.c --- old/uwsgi-2.0.18/core/yaml.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/core/yaml.c 2020-06-17 11:03:34.000000000 +0200 @@ -156,44 +156,49 @@ break; case YAML_FLOW_SEQUENCE_START_TOKEN: case YAML_BLOCK_SEQUENCE_START_TOKEN: - status = 3; + if (in_uwsgi_section) + in_uwsgi_section++; + // fallthrough + case YAML_FLOW_ENTRY_TOKEN: + case YAML_BLOCK_ENTRY_TOKEN: + status = 3; // inside a sequence break; case YAML_BLOCK_MAPPING_START_TOKEN: - if (!in_uwsgi_section) { - if (key) { - if (!strcmp(section_asked, key)) { - in_uwsgi_section = 1; - } + if (in_uwsgi_section) { + in_uwsgi_section++; + break; + } + if (key) { + if (!strcmp(section_asked, key)) { + in_uwsgi_section = 1; } } break; case YAML_BLOCK_END_TOKEN: - if (in_uwsgi_section) { - parsing = 0; - break; - } + case YAML_FLOW_SEQUENCE_END_TOKEN: + if (in_uwsgi_section) + parsing = !!(--in_uwsgi_section); + key = NULL; + status = 0; break; case YAML_SCALAR_TOKEN: - case YAML_FLOW_ENTRY_TOKEN: - case YAML_BLOCK_ENTRY_TOKEN: if (status == 1) { key = (char *) token.data.scalar.value; } - else if (status == 2) { + else if (status == 2 || status == 3) { val = (char *) token.data.scalar.value; if (key && val && in_uwsgi_section) { add_exported_option(key, val, 0); } - status = 0; - } - else if (status == 3) { - val = (char *) token.data.scalar.value; - if (key && val && in_uwsgi_section) { - add_exported_option(key, val, 0); + + // If this was the scalar of a value token, forget the state. + if (status == 2) { + key = NULL; + status = 0; } } else { - uwsgi_log("unsupported YAML token in %s block\n", section_asked); + uwsgi_log("unsupported YAML token %d in %s block\n", token.type, section_asked); parsing = 0; break; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/cgi/cgi_plugin.c new/uwsgi-2.0.19.1/plugins/cgi/cgi_plugin.c --- old/uwsgi-2.0.18/plugins/cgi/cgi_plugin.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/cgi/cgi_plugin.c 2020-06-17 11:03:34.000000000 +0200 @@ -780,8 +780,21 @@ close(cgi_pipe[1]); // close all the fd > 2 - for(i=3;i<(int)uwsgi.max_fd;i++) { - close(i); + DIR *dirp = opendir("/proc/self/fd"); + if (dirp == NULL) + dirp = opendir("/dev/fd"); + if (dirp != NULL) { + struct dirent *dent; + while ((dent = readdir(dirp)) != NULL) { + int fd = atoi(dent->d_name); + if ((fd > 2) && fd != dirfd(dirp)) + close(fd); + } + closedir(dirp); + } else { + for(i=3;i<(int)uwsgi.max_fd;i++) { + close(i); + } } // fill cgi env diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/corerouter/cr_common.c new/uwsgi-2.0.19.1/plugins/corerouter/cr_common.c --- old/uwsgi-2.0.18/plugins/corerouter/cr_common.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/corerouter/cr_common.c 2020-06-17 11:03:34.000000000 +0200 @@ -62,7 +62,7 @@ // fix SERVER_PORT if (!ugs->port || !ugs->port_len) { - ugs->port = strchr(ugs->name, ':'); + ugs->port = strrchr(ugs->name, ':'); if (ugs->port) { ugs->port++; ugs->port_len = strlen(ugs->port); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/gevent/gevent.c new/uwsgi-2.0.19.1/plugins/gevent/gevent.c --- old/uwsgi-2.0.18/plugins/gevent/gevent.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/gevent/gevent.c 2020-06-17 11:03:34.000000000 +0200 @@ -433,8 +433,13 @@ ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn"); if (!ugevent.spawn) uwsgi_pyexit; - ugevent.signal = PyDict_GetItemString(gevent_dict, "signal"); - if (!ugevent.signal) uwsgi_pyexit; + ugevent.signal = PyDict_GetItemString(gevent_dict, "signal_handler"); + if (!ugevent.signal) { + // gevent.signal_handler appears in gevent 1.3. + // On older gevent, fall back to the deprecated gevent.signal. + ugevent.signal = PyDict_GetItemString(gevent_dict, "signal"); + if (!ugevent.signal) uwsgi_pyexit; + } ugevent.greenlet_switch = PyDict_GetItemString(gevent_dict, "sleep"); if (!ugevent.greenlet_switch) uwsgi_pyexit; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/logsocket/logsocket_plugin.c new/uwsgi-2.0.19.1/plugins/logsocket/logsocket_plugin.c --- old/uwsgi-2.0.18/plugins/logsocket/logsocket_plugin.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/logsocket/logsocket_plugin.c 2020-06-17 11:03:34.000000000 +0200 @@ -43,6 +43,7 @@ else { ul->msg.msg_iov = uwsgi_malloc(sizeof(struct iovec)); ul->msg.msg_iovlen = 1; + ul->count = 0; } if (comma) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/php/php_plugin.c new/uwsgi-2.0.19.1/plugins/php/php_plugin.c --- old/uwsgi-2.0.18/plugins/php/php_plugin.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/php/php_plugin.c 2020-06-17 11:03:34.000000000 +0200 @@ -1061,10 +1061,9 @@ SG(request_info).path_translated = wsgi_req->file; + memset(&file_handle, 0, sizeof(zend_file_handle)); file_handle.type = ZEND_HANDLE_FILENAME; file_handle.filename = real_filename; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; if (php_request_startup(TSRMLS_C) == FAILURE) { uwsgi_500(wsgi_req); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/psgi/psgi.h new/uwsgi-2.0.19.1/plugins/psgi/psgi.h --- old/uwsgi-2.0.18/plugins/psgi/psgi.h 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/psgi/psgi.h 2020-06-17 11:03:34.000000000 +0200 @@ -87,3 +87,5 @@ void uwsgi_perl_check_auto_reload(void); void uwsgi_psgi_preinit_apps(void); + +extern struct uwsgi_perl uperl; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/psgi/psgi_loader.c new/uwsgi-2.0.19.1/plugins/psgi/psgi_loader.c --- old/uwsgi-2.0.18/plugins/psgi/psgi_loader.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/psgi/psgi_loader.c 2020-06-17 11:03:34.000000000 +0200 @@ -1,7 +1,6 @@ #include "psgi.h" extern struct uwsgi_server uwsgi; -struct uwsgi_perl uperl; extern struct uwsgi_plugin psgi_plugin; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/psgi/psgi_plugin.c new/uwsgi-2.0.19.1/plugins/psgi/psgi_plugin.c --- old/uwsgi-2.0.18/plugins/psgi/psgi_plugin.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/psgi/psgi_plugin.c 2020-06-17 11:03:34.000000000 +0200 @@ -3,11 +3,7 @@ extern char **environ; extern struct uwsgi_server uwsgi; -#ifdef __APPLE__ -extern struct uwsgi_perl uperl; -#else struct uwsgi_perl uperl; -#endif struct uwsgi_plugin psgi_plugin; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/psgi/uwsgi_plmodule.c new/uwsgi-2.0.19.1/plugins/psgi/uwsgi_plmodule.c --- old/uwsgi-2.0.18/plugins/psgi/uwsgi_plmodule.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/psgi/uwsgi_plmodule.c 2020-06-17 11:03:34.000000000 +0200 @@ -883,7 +883,7 @@ XSRETURN_UNDEF; } - ST(0) = newSVpv(chunk, len); + ST(0) = newSVpvn(chunk, len); sv_2mortal(ST(0)); XSRETURN(1); } @@ -902,7 +902,7 @@ XSRETURN_UNDEF; } - ST(0) = newSVpv(chunk, len); + ST(0) = newSVpvn(chunk, len); sv_2mortal(ST(0)); XSRETURN(1); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/pypy/pypy_setup.py new/uwsgi-2.0.19.1/plugins/pypy/pypy_setup.py --- old/uwsgi-2.0.18/plugins/pypy/pypy_setup.py 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/pypy/pypy_setup.py 2020-06-17 11:03:34.000000000 +0200 @@ -326,10 +326,10 @@ if c[0] != '/': c = os.getcwd() + '/' + c try: - from paste.script.util.logging_config import fileConfig + from logging.config import fileConfig fileConfig(c) except ImportError: - print "PyPy WARNING: unable to load paste.script.util.logging_config" + print "PyPy WARNING: unable to load logging.config" from paste.deploy import loadapp wsgi_application = loadapp('config:%s' % c) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/python/pyloader.c new/uwsgi-2.0.19.1/plugins/python/pyloader.c --- old/uwsgi-2.0.18/plugins/python/pyloader.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/python/pyloader.c 2020-06-17 11:03:34.000000000 +0200 @@ -678,7 +678,7 @@ uwsgi_log( "Loading paste environment: %s\n", paste); if (up.paste_logger) { - PyObject *paste_logger_dict = get_uwsgi_pydict("paste.script.util.logging_config"); + PyObject *paste_logger_dict = get_uwsgi_pydict("logging.config"); if (paste_logger_dict) { PyObject *paste_logger_fileConfig = PyDict_GetItemString(paste_logger_dict, "fileConfig"); if (paste_logger_fileConfig) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/python/uwsgi_pymodule.c new/uwsgi-2.0.19.1/plugins/python/uwsgi_pymodule.c --- old/uwsgi-2.0.18/plugins/python/uwsgi_pymodule.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/python/uwsgi_pymodule.c 2020-06-17 11:03:34.000000000 +0200 @@ -2167,8 +2167,6 @@ goto clear; } - apps_tuple = PyDict_GetItemString(worker_dict, "apps"); - PyDict_Clear(worker_dict); zero = PyInt_FromLong(uwsgi.workers[i + 1].id); @@ -2322,9 +2320,10 @@ PyTuple_SetItem(apps_tuple, j, apps_dict); } - + PyDict_SetItemString(worker_dict, "apps", apps_tuple); + Py_DECREF(apps_tuple); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/python/wsgi_handlers.c new/uwsgi-2.0.19.1/plugins/python/wsgi_handlers.c --- old/uwsgi-2.0.18/plugins/python/wsgi_handlers.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/python/wsgi_handlers.c 2020-06-17 11:03:34.000000000 +0200 @@ -461,31 +461,32 @@ } PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) { - + int chunk_size; + PyObject *filelike; struct wsgi_request *wsgi_req = py_current_wsgi_req(); - if (!PyArg_ParseTuple(args, "O|i:uwsgi_sendfile", &wsgi_req->async_sendfile, &wsgi_req->sendfile_fd_chunk)) { + if (!PyArg_ParseTuple(args, "O|i:uwsgi_sendfile", &filelike, &chunk_size)) { return NULL; } -#ifdef PYTHREE - wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile); - if (wsgi_req->sendfile_fd >= 0) { - Py_INCREF((PyObject *)wsgi_req->async_sendfile); - } -#else - if (PyFile_Check((PyObject *)wsgi_req->async_sendfile)) { - Py_INCREF((PyObject *)wsgi_req->async_sendfile); - wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile); + if (!PyObject_HasAttrString(filelike, "read")) { + PyErr_SetString(PyExc_AttributeError, "object has no attribute 'read'"); + return NULL; } -#endif - // PEP 333 hack - wsgi_req->sendfile_obj = wsgi_req->async_sendfile; - //wsgi_req->sendfile_obj = (void *) PyTuple_New(0); + // wsgi.file_wrapper called a second time? Forget the old reference. + if (wsgi_req->async_sendfile) { + Py_DECREF(wsgi_req->async_sendfile); + } - Py_INCREF((PyObject *) wsgi_req->sendfile_obj); - return (PyObject *) wsgi_req->sendfile_obj; + // XXX: Not 100% sure why twice. + // Maybe: We keep one at async_sendfile and transfer + // one to the caller (even though he gave it to us). + Py_INCREF(filelike); + Py_INCREF(filelike); + wsgi_req->async_sendfile = filelike; + wsgi_req->sendfile_fd_chunk = chunk_size; + return filelike; } void threaded_swap_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/python/wsgi_subhandler.c new/uwsgi-2.0.19.1/plugins/python/wsgi_subhandler.c --- old/uwsgi-2.0.18/plugins/python/wsgi_subhandler.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/python/wsgi_subhandler.c 2020-06-17 11:03:34.000000000 +0200 @@ -76,7 +76,18 @@ return 1; } return 0; -} +} + +/* + * attempt to make a fd from a file-like PyObject - returns -1 on error. + */ +static int uwsgi_python_try_filelike_as_fd(PyObject *filelike) { + int fd; + if ((fd = PyObject_AsFileDescriptor(filelike)) < 0) { + PyErr_Clear(); + } + return fd; +} /* this is a hack for supporting non-file object passed to wsgi.file_wrapper @@ -253,7 +264,9 @@ if (uwsgi_python_send_body(wsgi_req, (PyObject *)wsgi_req->async_result)) goto clear; } - if (wsgi_req->sendfile_obj == wsgi_req->async_result) { + // Check if wsgi.file_wrapper has been used. + if (wsgi_req->async_sendfile == wsgi_req->async_result) { + wsgi_req->sendfile_fd = uwsgi_python_try_filelike_as_fd((PyObject *)wsgi_req->async_sendfile); if (wsgi_req->sendfile_fd >= 0) { UWSGI_RELEASE_GIL uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0); @@ -299,8 +312,14 @@ Py_DECREF(pychunk); goto clear; } - } - else if (wsgi_req->sendfile_obj == pychunk) { + } else if (wsgi_req->async_sendfile == pychunk) { + // + // XXX: It's not clear whether this can ever be sensibly reached + // based on PEP 333/3333 - it would mean the iterator yielded + // the result of wsgi.file_wrapper. However, the iterator should + // only ever yield `bytes`... + // + wsgi_req->sendfile_fd = uwsgi_python_try_filelike_as_fd((PyObject *)wsgi_req->async_sendfile); if (wsgi_req->sendfile_fd >= 0) { UWSGI_RELEASE_GIL uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0); @@ -310,22 +329,30 @@ else if (PyObject_HasAttrString(pychunk, "read")) { uwsgi_python_consume_file_wrapper_read(wsgi_req, pychunk); } - uwsgi_py_check_write_errors { uwsgi_py_write_exception(wsgi_req); Py_DECREF(pychunk); goto clear; } + } else if (pychunk != Py_None) { + // The iterator returned something that we were not able to handle. + PyObject *pystr = PyObject_Repr(pychunk); +#ifdef PYTHREE + const char *cstr = PyUnicode_AsUTF8(pystr); +#else + const char *cstr = PyString_AsString(pystr); +#endif + uwsgi_log("[ERROR] Unhandled object from iterator: %s (%p)\n", cstr, pychunk); + Py_DECREF(pystr); } - Py_DECREF(pychunk); return UWSGI_AGAIN; clear: - - if (wsgi_req->sendfile_fd != -1) { - Py_DECREF((PyObject *)wsgi_req->async_sendfile); + // Release the reference that we took in py_uwsgi_sendfile. + if (wsgi_req->async_sendfile != NULL) { + Py_DECREF((PyObject *) wsgi_req->async_sendfile); } if (wsgi_req->async_placeholder) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/pyuwsgi/pyuwsgi.c new/uwsgi-2.0.19.1/plugins/pyuwsgi/pyuwsgi.c --- old/uwsgi-2.0.18/plugins/pyuwsgi/pyuwsgi.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/pyuwsgi/pyuwsgi.c 2020-06-17 11:03:34.000000000 +0200 @@ -82,7 +82,7 @@ PyObject *py_str = PyObject_Str(item); PyList_Append(args_li, py_str); #ifdef PYTHREE - char *str = PyUnicode_AsUTF8(py_str); + const char *str = PyUnicode_AsUTF8(py_str); size += strlen(str) + 1; #else size += PyObject_Length(item) + 1; @@ -102,7 +102,7 @@ for (i = 0; i < new_argc; i++) { PyObject *arg = PyList_GetItem(args_li, i); #ifdef PYTHREE - char *arg_str = PyUnicode_AsUTF8(arg); + const char *arg_str = PyUnicode_AsUTF8(arg); #else char *arg_str = PyString_AsString(arg); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/redislog/redislog_plugin.c new/uwsgi-2.0.19.1/plugins/redislog/redislog_plugin.c --- old/uwsgi-2.0.18/plugins/redislog/redislog_plugin.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/redislog/redislog_plugin.c 2020-06-17 11:03:34.000000000 +0200 @@ -159,7 +159,7 @@ uredislog->fd = uwsgi_connect(uredislog->address, uwsgi.socket_timeout, 0); if (uredislog->password) { setup_iov.iov_len = snprintf( - setup_buf, sizeof (setup_buf), "*2\r\n$4\r\nauth\r\n$%lu\r\n%*s\r\n", + setup_buf, sizeof (setup_buf), "*2\r\n$4\r\nauth\r\n$%zu\r\n%*s\r\n", strlen(uredislog->password), (int)strlen(uredislog->password), uredislog->password); setup_iov.iov_base = setup_buf; ret = writev(uredislog->fd, &setup_iov, 1); @@ -172,7 +172,7 @@ } if (uredislog->id) { setup_iov.iov_len = snprintf( - setup_buf, sizeof (setup_buf), "*2\r\n$6\r\nselect\r\n$%lu\r\n%*s\r\n", + setup_buf, sizeof (setup_buf), "*2\r\n$6\r\nselect\r\n$%zu\r\n%*s\r\n", strlen(uredislog->id), (int)strlen(uredislog->id), uredislog->id); setup_iov.iov_base = setup_buf; ret = writev(uredislog->fd, &setup_iov, 1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/router_static/router_static.c new/uwsgi-2.0.19.1/plugins/router_static/router_static.c --- old/uwsgi-2.0.18/plugins/router_static/router_static.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/router_static/router_static.c 2020-06-17 11:03:34.000000000 +0200 @@ -239,7 +239,7 @@ } if (wsgi_req->socket->can_offload) { - if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, st.st_size)) { + if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, 0, st.st_size)) { wsgi_req->via = UWSGI_VIA_OFFLOAD; wsgi_req->response_size += st.st_size; // the fd will be closed by the offload engine diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/plugins/transformation_offload/offload.c new/uwsgi-2.0.19.1/plugins/transformation_offload/offload.c --- old/uwsgi-2.0.18/plugins/transformation_offload/offload.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/plugins/transformation_offload/offload.c 2020-06-17 11:03:34.000000000 +0200 @@ -25,7 +25,7 @@ struct uwsgi_transformation *orig_ut = (struct uwsgi_transformation *) ut->data; // sendfile offload if (orig_ut->fd > -1) { - if (!uwsgi_offload_request_sendfile_do(wsgi_req, orig_ut->fd, orig_ut->len)) { + if (!uwsgi_offload_request_sendfile_do(wsgi_req, orig_ut->fd, 0, orig_ut->len)) { // the fd will be closed by the offload engine orig_ut->fd = -1; wsgi_req->via = UWSGI_VIA_OFFLOAD; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/proto/http.c new/uwsgi-2.0.19.1/proto/http.c --- old/uwsgi-2.0.18/proto/http.c 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/proto/http.c 2020-06-17 11:03:34.000000000 +0200 @@ -276,7 +276,7 @@ } } else { - char *server_port = strchr(wsgi_req->socket->name, ':'); + char *server_port = strrchr(wsgi_req->socket->name, ':'); if (server_port) { wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, server_port+1, strlen(server_port+1)); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/setup.py new/uwsgi-2.0.19.1/setup.py --- old/uwsgi-2.0.18/setup.py 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/setup.py 2020-06-17 11:03:34.000000000 +0200 @@ -136,5 +136,7 @@ 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', ], ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/tests/static/test.txt new/uwsgi-2.0.19.1/tests/static/test.txt --- old/uwsgi-2.0.18/tests/static/test.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.19.1/tests/static/test.txt 2020-06-17 11:03:34.000000000 +0200 @@ -0,0 +1 @@ +cookie diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/tests/static/test2.txt new/uwsgi-2.0.19.1/tests/static/test2.txt --- old/uwsgi-2.0.18/tests/static/test2.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.19.1/tests/static/test2.txt 2020-06-17 11:03:34.000000000 +0200 @@ -0,0 +1 @@ +cookie2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/tests/testfilewrapper.py new/uwsgi-2.0.19.1/tests/testfilewrapper.py --- old/uwsgi-2.0.18/tests/testfilewrapper.py 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.19.1/tests/testfilewrapper.py 2020-06-17 11:03:34.000000000 +0200 @@ -0,0 +1,122 @@ +from __future__ import print_function +import gc +import io +import os.path +import time + +import flask +import flask.helpers + + +application = flask.Flask(__name__) + +FILENAME = os.path.join(os.path.dirname(__file__), "static", "test.txt") +FILENAME2 = os.path.join(os.path.dirname(__file__), "static", "test2.txt") + [email protected]_request +def _after(response): + gc.collect() + fds = os.listdir("/proc/self/fd") + print("PY: objects:", len(gc.get_objects()), "fds:", len(fds)) + return response + [email protected]("/") +def index(): + return "HELLO\n" + [email protected]("/1") +def send_file_1(): + fp = open(FILENAME, "rb") + return flask.send_file(fp, attachment_filename="test.txt") + + [email protected]("/2") +def send_file_2(): + bio = io.BytesIO(b"cookie\n") + return flask.send_file(bio, attachment_filename="test.txt") + + [email protected]("/3") +def send_file_3(): + """ + What happens if we call the wsgi.file_wrapper twice? + + This should respond with cookie2 + """ + fp = open(FILENAME, "rb") + flask.send_file(fp, attachment_filename="test.txt") + fp = open(FILENAME2, "rb") + return flask.send_file(fp, attachment_filename="test.txt") + + [email protected]("/4") +def send_file_4(): + """ + Non-filelike object to send_file/wrap_file/wsgi.file_wrapper. + + AttributeError on the call to wsgi.file_wrapper. + """ + return flask.send_file(object(), attachment_filename="test.txt") + + [email protected]("/stream1") +def stream1(): + """ + Unrelated to wsgi.file_wrapper, just ensuring the iterator stuff still works. + """ + def _yield(): + start = time.time() + for i in range(3): + time.sleep(0.1) + yield " {:.2f} cookie".format(time.time() - start).encode("utf-8") + yield b"\n" + return flask.Response(_yield(), mimetype="text/plain") + + [email protected]("/stream2") +def stream2(): + """ + Yielding the result of a wrap_file call with a file object. + + gunicorn / werkzeug do not support this as it's not required. + """ + fp = open(FILENAME, "rb") + resp = flask.helpers.wrap_file(flask.request.environ, fp) + print("PY: resp after return", hex(id(resp))) + + def _yield(): + print("PY: _yield() run", hex(id(resp)), repr(resp)) + yield resp + return flask.Response(_yield()) + + [email protected]("/stream3") +def stream3(): + """ + Yielding the result of a wrap_file call with a BytesIO object. + + gunicorn / werkzeug do not support this as it's not required. + """ + bio = io.BytesIO(b"cookie\n") + resp = flask.helpers.wrap_file(flask.request.environ, bio) + + def _yield(): + yield resp + return flask.Response(_yield()) + + [email protected]("/stream4") +def stream4(): + """ + werkzeug logs: AssertionError: applications must write bytes + gunicorn logs: TypeError: <Response streamed [200 OK]> is not a byte + uwsgi didn't log, should now.. + """ + fp = open(FILENAME, "rb") + resp = flask.send_file(fp, attachment_filename="test.txt") + print("PY: resp after return", hex(id(resp))) + + def _yield(): + print("PY: _yield() run", hex(id(resp)), repr(resp)) + yield resp + return flask.Response(_yield(), direct_passthrough=True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/tests/testrpc.py new/uwsgi-2.0.19.1/tests/testrpc.py --- old/uwsgi-2.0.18/tests/testrpc.py 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.19.1/tests/testrpc.py 2020-06-17 11:03:34.000000000 +0200 @@ -0,0 +1,13 @@ +import uwsgi + +def hello(): + pass + +def application(env, start_response): + try: + uwsgi.register_rpc("A"*300, hello) + start_response('500 Buffer Overflow', [('Content-Type', 'text/plain')]) + except ValueError: + start_response('200 OK', [('Content-Type', 'text/plain')]) + + return () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/tests/testworkers.py new/uwsgi-2.0.19.1/tests/testworkers.py --- old/uwsgi-2.0.18/tests/testworkers.py 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.19.1/tests/testworkers.py 2020-06-17 11:03:34.000000000 +0200 @@ -0,0 +1,26 @@ +""" +Regression test for #2056 - uwsgi.workers() leaking objects. +""" +import uwsgi +import gc + + +def application(env, start_response): + gc.collect() + start_objs = len(gc.get_objects()) + + for i in range(200): + uwsgi.workers() + + gc.collect() + end_objs = len(gc.get_objects()) + diff_objs = end_objs - start_objs + + # Sometimes there is a spurious diff of 4 objects or so. + if diff_objs > 10: + start_response('500 Leaking', [('Content-Type', 'text/plain')]) + yield "Leaking objects...\n".format(diff_objs).encode("utf-8") + else: + start_response('200 OK', [('Content-Type', 'text/plain')]) + + yield "{} {} {}\n".format(start_objs, end_objs, diff_objs).encode("utf-8") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/tests/travis.sh new/uwsgi-2.0.19.1/tests/travis.sh --- old/uwsgi-2.0.18/tests/travis.sh 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/tests/travis.sh 2020-06-17 11:03:34.000000000 +0200 @@ -1,4 +1,5 @@ #!/bin/bash +set -u txtund=$(tput sgr 0 1) # underline @@ -57,13 +58,13 @@ test_python() { date > reload.txt rm -f uwsgi.log - echo -e "${bldyel}================== TESTING $1 =====================${txtrst}" + echo -e "${bldyel}================== TESTING $1 $2 =====================${txtrst}" echo -e "${bldyel}>>> Spawning uWSGI python app${txtrst}" echo -en "${bldred}" - ./uwsgi --master --plugin 0:$1 --http :8080 --exit-on-reload --touch-reload reload.txt --wsgi-file tests/staticfile.py --daemonize uwsgi.log + ./uwsgi --master --plugin 0:$1 --http :8080 --exit-on-reload --touch-reload reload.txt --wsgi-file $2 --daemonize uwsgi.log echo -en "${txtrst}" http_test "http://localhost:8080/" - echo -e "${bldyel}===================== DONE $1 =====================${txtrst}\n\n" + echo -e "${bldyel}===================== DONE $1 $2 =====================${txtrst}\n\n" } @@ -71,31 +72,35 @@ date > reload.txt rm -f uwsgi.log # the code assumes that ruby environment is activated by `rvm use` - echo -e "${bldyel}================== TESTING $1 =====================${txtrst}" + echo -e "${bldyel}================== TESTING $1 $2 =====================${txtrst}" echo -e "${bldyel}>>> Installing sinatra gem using gem${txtrst}" gem install sinatra || die echo -e "${bldyel}>>> Spawning uWSGI rack app${txtrst}" echo -en "${bldred}" - ./uwsgi --master --plugin 0:$1 --http :8080 --exit-on-reload --touch-reload reload.txt --rack examples/config2.ru --daemonize uwsgi.log + ./uwsgi --master --plugin 0:$1 --http :8080 --exit-on-reload --touch-reload reload.txt --rack $2 --daemonize uwsgi.log echo -en "${txtrst}" http_test "http://localhost:8080/hi" - echo -e "${bldyel}===================== DONE $1 =====================${txtrst}\n\n" + echo -e "${bldyel}===================== DONE $1 $2 =====================${txtrst}\n\n" } while read PV ; do - test_python $PV + for WSGI_FILE in tests/staticfile.py tests/testworkers.py tests/testrpc.py ; do + test_python $PV $WSGI_FILE + done done < <(cat .travis.yml | grep "plugins/python base" | sed s_".*plugins/python base "_""_g) while read RV ; do - test_rack $RV + for RACK in examples/config2.ru ; do + test_rack $RV $RACK + done done < <(cat .travis.yml | grep "plugins/rack base" | sed s_".*plugins/rack base "_""_g) -echo "${bldgre}>>> $SUCCESS SUCCESSFUL PLUGIN(S)${txtrst}" +echo "${bldgre}>>> $SUCCESS SUCCESSFUL TEST(S)${txtrst}" if [ $ERROR -ge 1 ]; then - echo "${bldred}>>> $ERROR FAILED PLUGIN(S)${txtrst}" + echo "${bldred}>>> $ERROR FAILED TEST(S)${txtrst}" exit 1 fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/tests/werkzeug.py new/uwsgi-2.0.19.1/tests/werkzeug.py --- old/uwsgi-2.0.18/tests/werkzeug.py 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/tests/werkzeug.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,5 +0,0 @@ -import uwsgi - -print(uwsgi.opt) -print(uwsgi.magic_table) -from werkzeug.testapp import test_app as application diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/tests/werkzeug_app.py new/uwsgi-2.0.19.1/tests/werkzeug_app.py --- old/uwsgi-2.0.18/tests/werkzeug_app.py 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsgi-2.0.19.1/tests/werkzeug_app.py 2020-06-17 11:03:34.000000000 +0200 @@ -0,0 +1,5 @@ +import uwsgi + +print(uwsgi.opt) +print(uwsgi.magic_table) +from werkzeug.testapp import test_app as application diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/uwsgi.gemspec new/uwsgi-2.0.19.1/uwsgi.gemspec --- old/uwsgi-2.0.18/uwsgi.gemspec 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/uwsgi.gemspec 2020-06-17 11:03:34.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 = '2019-02-09' + s.date = '2020-06-14' 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.18/uwsgi.h new/uwsgi-2.0.19.1/uwsgi.h --- old/uwsgi-2.0.18/uwsgi.h 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/uwsgi.h 2020-06-17 11:03:34.000000000 +0200 @@ -614,6 +614,8 @@ char *chdir; int max_throttle; + + int notifypid; }; struct uwsgi_logger { @@ -1631,6 +1633,8 @@ struct sockaddr_in6 sin6; struct sockaddr_un sun; } client_addr; + + uint8_t websocket_is_fin; }; @@ -2837,6 +2841,13 @@ #ifdef UWSGI_SSL int tlsv1; #endif + + // uWSGI 2.0.19 + int emperor_graceful_shutdown; + int is_chrooted; + struct uwsgi_buffer *websockets_continuation_buffer; + + uint64_t max_worker_lifetime_delta; }; struct uwsgi_rpc { @@ -3380,6 +3391,7 @@ char *uwsgi_num2str(int); char *uwsgi_float2str(float); char *uwsgi_64bit2str(int64_t); +char *uwsgi_size2str(size_t); char *magic_sub(char *, size_t, size_t *, char *[]); void init_magic_table(char *[]); @@ -4405,7 +4417,7 @@ void uwsgi_offload_engines_register_all(void); struct uwsgi_thread *uwsgi_offload_thread_start(void); -int uwsgi_offload_request_sendfile_do(struct wsgi_request *, int, size_t); +int uwsgi_offload_request_sendfile_do(struct wsgi_request *, int, size_t, size_t); int uwsgi_offload_request_net_do(struct wsgi_request *, char *, struct uwsgi_buffer *); int uwsgi_offload_request_memory_do(struct wsgi_request *, char *, size_t); int uwsgi_offload_request_pipe_do(struct wsgi_request *, int, size_t); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsgi-2.0.18/uwsgiconfig.py new/uwsgi-2.0.19.1/uwsgiconfig.py --- old/uwsgi-2.0.18/uwsgiconfig.py 2019-02-09 15:48:07.000000000 +0100 +++ new/uwsgi-2.0.19.1/uwsgiconfig.py 2020-06-17 11:03:34.000000000 +0200 @@ -1,6 +1,6 @@ # uWSGI build system -uwsgi_version = '2.0.18' +uwsgi_version = '2.0.19.1' import os import re @@ -27,6 +27,10 @@ except: import configparser as ConfigParser +try: + from shlex import quote +except ImportError: + from pipes import quote PY3 = sys.version_info[0] == 3 @@ -203,11 +207,12 @@ def spcall3(cmd): p = subprocess.Popen(cmd, shell=True, stdin=open('/dev/null'), stderr=subprocess.PIPE, stdout=subprocess.PIPE) + (out, err) = p.communicate() - if p.wait() == 0: + if p.returncode == 0: if sys.version_info[0] > 2: - return p.stderr.read().rstrip().decode() - return p.stderr.read().rstrip() + return err.rstrip().decode() + return err.rstrip() else: return None @@ -592,7 +597,7 @@ t.join() print("*** uWSGI linking ***") - ldline = "%s -o %s %s %s %s" % (GCC, bin_name, ' '.join(uniq_warnings(ldflags)), + ldline = "%s -o %s %s %s %s" % (GCC, quote(bin_name), ' '.join(uniq_warnings(ldflags)), ' '.join(map(add_o, gcc_list)), ' '.join(uniq_warnings(libs))) print(ldline) ret = os.system(ldline) _______________________________________________ openSUSE Commits mailing list -- [email protected] To unsubscribe, email [email protected] List Netiquette: https://en.opensuse.org/openSUSE:Mailing_list_netiquette List Archives: https://lists.opensuse.org/archives/list/[email protected]
