Compare commits

..
606 Commits
Author SHA1 Message Date
Dimitri John Ledkov a6005624af paste_loader: allow specifying alternative section name to load. 2015-10-09 15:53:52 +01:00
unbit 70198991fe Merge pull request #1045 from Darvame/patch-7
lua_plugin: protected and unprotected __tostring
2015-10-01 07:44:17 +02:00
Darvame Hleran df0c2ca1c8 lua_plugin: cache numbers set/update support 2015-09-29 13:26:48 +03:00
Hleran da60423252 lua_plugin: cache_num, proper error type
- cache_num
and also swiched to wrong type for error status (tested with proper one, than ... "oh wait, we have empty 'i' variable!", later ... "oh sh size_t is uint!")
2015-09-29 00:31:24 +03:00
Hleran 5b9e2b5f39 lua_plugin: counting sid from 1
lua does not like count from 0
2015-09-23 17:07:04 +03:00
Hleran 8185b97030 lua_plugin: protected and unprotected __tostring
- protected and unprotected __tostring (protected outside, unprotected internal, avoid double pcall)
- also check userdata for metafields (non simple type)
- mywid and mysid are functions now
- minor api bump
2015-09-23 14:21:39 +03:00
unbit abac960e62 Merge pull request #1043 from multiSnow/master
also remove all master fifo if vacuum is true
2015-09-21 07:29:29 +02:00
multisnow 8ea8a33d0c also remove all master fifo if vacuum is true 2015-09-21 00:56:06 +08:00
unbit 8939fd5e1b Merge pull request #852 from xtfxme/binary_argc
introduce uwsgi.binary_argc
2015-09-17 19:39:36 +02:00
C Anthony Risinger 849a85b250 Introduce uwsgi.binary_argc
If more than uwsgi.binary_path is needed to make uWSGI self-referential on
reload, plugins can use this field to skip processing of N initial arguments.

eg. if uWSGI is embedded in a host application or interpreter::

    python -B -E -m uwsgi --socket=:8000 --show-config [...]

argv[1:5] are intended for Python, and not for processing by uWSGI, even though
uWSGI might want to manage it (process name). The arguments also cannot just be
ignored because they are crucial for proper reloads.
2015-09-17 04:00:20 -05:00
unbit d08275ea12 Merge pull request #1040 from Darvame/patch-6
lua_plugin: queue segfault
2015-09-16 17:06:45 +02:00
Unbit fb3628d729 attempt to fix http parser 2015-09-16 16:07:45 +02:00
Hleran 52ea02acad Fix 1039: lua_plugin queue segfault
lua stack iterator is not suitable for c arrays
2015-09-16 12:22:25 +03:00
unbit 59a76bb85c Merge pull request #999 from Darvame/patch-5
lua_plugin: new stuff
2015-09-15 07:38:11 +02:00
unbit 26bd4aa489 Merge pull request #522 from ncopa/master
fix building with musl libc
2015-09-15 07:34:34 +02:00
Hleran 7e601d6d8d lua_plugin: cache_exists_multi, no false pls
return nil instead of false
2015-09-13 07:01:12 +03:00
Hleran c2e83fe01d lua_plugin: last
fixes, fixes, removing unnecessary stuff
2015-09-13 06:24:26 +03:00
Unbit 281c1f5427 added Rump unikernel preliminary support 2015-09-10 11:27:43 +02:00
Unbit 33df0dbcc9 attempt to fix #1034 2015-09-10 09:35:53 +02:00
unbit cd24b11369 Merge pull request #1033 from xrmx/solaris11
Fix compilation with solaris 11
2015-09-10 08:34:56 +02:00
Riccardo Magliocchetti bbdf4bbab3 Fix compilation with solaris 11
Based on original patch from Nathan Tamblyn.

Fix #831
2015-09-09 18:28:58 +02:00
Hleran 637ead553a lua_plugin: mule: posible segfault, chunked_read
websocket_send __tostring metatable
2015-09-04 01:55:34 +03:00
Hleran 5ebc399cce lua_plugin: better mules 2015-09-03 00:45:51 +03:00
Unbit e55ac57e07 fixed #1026 2015-09-01 22:25:21 +02:00
Hleran f03f679a5c lua_plugin: mules, cache som fixes 2015-08-31 21:49:13 +03:00
Hleran 72ae69090a lua_plugin: cache_get, cache_get_tmulti
cache_get, cache_get_tmulti
returns key-value table
2015-08-30 02:01:59 +03:00
Hleran 1d595be2d9 lua_plugin: cleanup, more queues, more cache
and loop of nested tables inside headers
2015-08-27 23:15:29 +03:00
unbit 095c75055f Merge pull request #1021 from Ashald/patch-1
Pass LIBDIR to linker in Python plugin
2015-08-27 06:34:36 +02:00
Roberto De Ioris 20a0be1897 worker logger implementation #894 2015-08-27 05:43:04 +02:00
Borys Pierov 637952d048 Pass LIBDIR to linker in python plugin
To make it compile properly when LD_RUN_PATH is ignored.
2015-08-26 19:18:21 -04:00
Hleran a7181572e6 lua_plugin: queues, extend wsapi
dunno why so many additions and deletions
basic queues, remove cache_set_tables (cache_set will do it now)
extend wsapi with 4th argument without breaking it
2015-08-26 19:36:59 +03:00
unbit 920d94c055 Merge pull request #1016 from operasoftware/statsd-dont-send-workers
Add no-workers option to statsd plugin
2015-08-25 18:13:28 +02:00
Marek Wiewiorski 72647fada7 Place check before the lock, and goto to the end of the while block. Instead of strstr use uwsgi_starts_with. 2015-08-25 17:57:57 +02:00
Marek Wiewiorski 82a011e14d Add no-workers option to statsd plugin 2015-08-25 15:58:15 +02:00
Roberto De Ioris 772deaa083 support for single char PATH_INFO, attempt to fix #263 2015-08-25 15:45:25 +02:00
Hleran 94ccb6b030 lua_plugin: mules
separate api, mules
2015-08-22 18:42:41 +03:00
Hleran 01d3133fce lua_plugin: remove atexit, fixes
don't spawn lua_states on workers, if nothing to run
cache multi_set,update,del also returns number of bad keys
remove atexit, does not work as expected
2015-08-21 18:29:04 +03:00
Hleran 377fc2d863 lua_plugin: metric, cache, fixes, cleanups 2015-08-21 01:25:12 +03:00
unbit 59df10466a Merge pull request #1009 from yueyoum/patch-spooler-signal-as-task
Patch spooler signal as task
2015-08-19 17:14:59 +02:00
yueyoum ebb77b55d7 Fix, check spooler_signal_as_task 2015-08-19 17:36:29 +08:00
yueyoum 55c7e653fd fix spooler-signal-as-task 2015-08-19 02:16:54 +08:00
Roberto De Ioris eab664ae8b added -dev to 2.1 version 2015-08-18 19:48:54 +02:00
yueyoum 9a0681a6e0 Merge branch 'test' into patch-spooler-signal-as-task
Introduce a new param: spooler-signal-as-task
In present, the spooler-max-tasks only works for spool tasks
With this patch, the signal based events (cron, timer)
can also be treated as tasks.
When reach the spooler-max-tasks limits,
the spool process will restart.

This helps for alleviate memory leaks
2015-08-19 00:21:40 +08:00
yueyoum cd69e718aa spooler-signal-as-task 2015-08-19 00:19:03 +08:00
Hleran 8d2465db9b lua_plugin: lua_createtable, signals
using prehashed lua_createtable when we can instead of lua_newtable
plugin specific regsiter signal
add_file_monitor, add_timer, add_rb_timer, add_cron, alarm
2015-08-16 15:41:39 +03:00
unbit 69fb3c8426 Merge pull request #1004 from marcan/master
rados plugin: Add username parameter
2015-08-12 16:51:06 +02:00
Hector Martin 7cf499127f rados plugin: Add username parameter 2015-08-12 22:22:42 +09:00
Hleran 6921e8f820 lua_plugin: atexit, lazy signal routing
uwsgi_lua_atexit to commit garbage-collection metamethods
lazy signal routing: empty 'receiver' value on master table
2015-08-07 07:36:13 +03:00
Hleran 37971671cb lua_plugin: own signal ref table in each lua_State 2015-08-07 02:39:44 +03:00
Hleran 271c6aa13b lua_plugin: rpc via uwsgi.rpc_ref table 2015-08-06 19:40:52 +03:00
Hleran c375920c63 lua_plugin: proper uwsgi.log
uwsgi.log like buildin print function
dummy response cfunction
2015-08-06 05:17:20 +03:00
Hleran 8e28051d2e lua_plugin: metatable.__tostring
also can yield and send metatable with __tostring attr;
some cleanups and optimizations;
2015-08-05 23:58:22 +03:00
unbit d5114da3aa Merge pull request #998 from xrmx/systemdfixup
systemd_logger: fix build with recent systemd
2015-08-04 11:19:48 +02:00
Riccardo Magliocchetti 9787f6882c systemd_logger: fix build with recent systemd
Since systemd 209 all the functionalities of libsystemd-* have
been merged in libsystemd.
2015-08-04 11:13:32 +02:00
unbit 7efa3666b7 Merge pull request #820 from xrmx/mimetypedebug
core/static: print mimetype of file in debug print
2015-08-04 10:39:22 +02:00
Natanael Copa 74eb3b282e always define _GNU_SOURCE for linux or GNU libc
We are using various extenstions that the spec say depends on _GNU_SOURCE,
for example unshare, CPU_SET, CPU_ZERO, cpu_set_t. We enable those always
for linux or GNU (kbsd/gnu)

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
2015-08-04 09:16:34 +02:00
Natanael Copa 1b59a46fc0 use portable pthread functions instead of the non-portable
The pthread functions pthread_mutexattr_setrobust and
pthread_mutex_consistent are in posix nowdays. Use those instead of their
non-portable synonyms.

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
2015-08-03 16:37:33 +02:00
Natanael Copa 92672880d7 Check for GNU libc instead of linux for use of execinfo.h
Since execinfo.h is a GNU extension it makes more sense to check for GNU
than to assume that linux is GNU.

This is needed for building on linux with musl libc.

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
2015-08-03 16:37:33 +02:00
Natanael Copa fb9d063e81 define WAIT_ANY if missing
POSIX uses -1 and does not define WAIT_ANY so we need to define it if
needed.

See:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_wait.h.html

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
2015-08-03 16:37:33 +02:00
Roberto De Ioris 1b3799d879 fixed #948 2015-08-02 08:35:53 +02:00
unbit 194f0bf94a Merge pull request #981 from Darvame/patch-4
lua_plugin: --lazy-apps, --threads and other
2015-08-02 08:11:29 +02:00
unbit b68a9d4d04 Merge pull request #986 from yueyoum/gevent-websocket
Allow call uwsgi websocket API in other greenlet. (enhanced)
2015-08-02 08:08:18 +02:00
Roberto De Ioris 5cbe0d078c fixed alarm backlog 2015-08-02 07:46:21 +02:00
Roberto De Ioris 262e370c81 added struct fields for --emperor-trigger-socket 2015-08-02 07:26:50 +02:00
Hleran f3bc21cf2b lua_plugin: no switch in 1st yield; async_id_get()
If coroutine and async, do not switch until first yield of coroutine;
uwsgi.async_id_get() to get 'wsgi_req->async_id' in my app;
2015-07-31 01:03:40 +03:00
Hleran a0dc7fdcf9 lua_plugin: wsapi func ref is constant, threading
correct multithreading support
2015-07-28 19:08:24 +03:00
unbit af17ba5739 Merge pull request #988 from xrmx/coverity2807
A couple of coverity fixes
2015-07-28 12:57:16 +02:00
Riccardo Magliocchetti 0dd07763b2 core/io: cleanup error handling in uwsgi_proxy_nb
Coverity reports a null pointer dereference (CID 1231243) after
check of ub. After auditing the callers it looks like it is always
called with ub defined so add a guard againt it being null at the
top just to be sure.

While at it fixup indentation of the function.
2015-07-28 12:32:08 +02:00
Hleran 1e97a5e8d0 lua_plugin: malloc oversize 2015-07-28 13:04:11 +03:00
Riccardo Magliocchetti 05748c2344 plugins/libffi: fix allocation mismatch
args_type is of type ffi_type** so its memory should be sized
against sizeof(ffy_type*).

Reported by Coverity as CID #1308300
2015-07-28 11:53:13 +02:00
Hleran 4c152b237f lua_plugin: recheck async_status, clean threads
recheck async_status before pcall
keep our thread's stacks empty
2015-07-28 11:24:55 +03:00
yueyoum 1bd624b188 Change uwsgi.input_object() to uwsgi.request_context().
and change the `uwsgi.websocket_send/send_binary/recv/recv_nb`
keyword argument from `uwsgi_input` to `request_context`
2015-07-28 15:11:45 +08:00
yueyoum 41c02ad01a check argument: uwsgi_input 2015-07-28 14:21:59 +08:00
Hleran 97304aded8 lua_plugin: better lazy check 2015-07-27 23:51:43 +03:00
yueyoum 8569450a85 I add this feature for using uwsgi websocket with gevent more easy and
convenient.

Example: tests/websockets_chat_2.py

Add:    add a new API `uwsgi.input_object()` for get `struct wsgi_req *`
in python.

Modify: `uwsgi.websocket_send/send_binary/recv/recv_nb` now has a
kwarg: `uwsgi_input`.

If not provide the `uwsgi_input` keyword argument, The four function's
behavior not changed.

When provide the `uwsgi_input` keyword argument, The four function will
get `wsgi_req` from the argument.

In this way, uwsgi websocket functions can be used in other greenlets.
2015-07-28 03:18:09 +08:00
Hleran fc088d4071 lua_plugin: .post_fork to .init_apps and lazy-apps
yes,  lazy-apps and lazy works fine
2015-07-27 19:51:46 +03:00
Hleran 916924c255 lua_plugin: change default gc mode etc...
- lua gc default is now LUA_GCSTEP instead of LUA_GCCOLLECT, the default value of gc-freq 0 with full collection after each request is really overkill. LUA_GCSTEP with default gc-freq works better. But you can always change gc to full collect via 'lua-gc-full = 1' opt;

- if our coroutine yields unexpected nil while in async mode, we retry the coroutine's call again in order to detect dead coroutine without async switch

- and some cleanup
2015-07-27 13:56:29 +03:00
Hleran cfaeb00a09 lua_plugin: .init_apps to .post_fork
trying to avoid seg_fault on very heavy load; (our workers now alloc memory for states and create it)
also our app can now work without wsapi app, it will just send 500 error code
2015-07-26 00:14:43 +03:00
unbit ca673dfc5f Merge pull request #978 from xrmx/coverity2307
Misc coverity fixes
2015-07-23 18:36:52 +02:00
Riccardo Magliocchetti 0cfec33943 plugins/router_spnego: remove dead code
negotiate is always null when going through forbidden label.

Reported by Coverity as CID #1308280
2015-07-23 16:44:50 +02:00
Riccardo Magliocchetti afedff7589 plugins/webdav: fix memory leak
Reported by Coverity as CID #1308292
2015-07-23 16:44:50 +02:00
Riccardo Magliocchetti ab7caae665 plugins/emperor_amqp: fix memory leak on error path
Reported by Coverity as CID #1308293
2015-07-23 16:44:50 +02:00
Riccardo Magliocchetti af613082c0 plugins/router_radius: fix resource leak on error path
Reported by Coverity as CID #1308294
2015-07-23 16:44:50 +02:00
Riccardo Magliocchetti 1362dcb117 dumbloop: fix memory leak
Reported by Coverity as CID #1308298
2015-07-23 14:47:30 +02:00
unbit 774f732205 Merge pull request #977 from Darvame/patch-3
lua_plugin: lua_newthread instead of new_State
2015-07-22 20:48:19 +02:00
Hleran 6b0a89a117 lua_plugin: lua_newthread instead of new_State
only ONE lua_State per 1 worker, and one lua thread per one worker's core.
so, 4 workers with 8000 async cores will not create 8000 lua_States, only 4, for each worker.
uwsgi table now also has lua_thread collection, and mywid variable.

Know bugs: too many simultaneously running cores (like async = 8000) without proper gc will cause segmentation fault (out of memory)
2015-07-22 21:28:25 +03:00
Unbit 5348d803d6 fixed 963 2015-07-19 08:14:14 +02:00
unbit 078a2c354e Merge pull request #974 from Darvame/patch-2
lua_plugin: rpc uwsgi_malloc and missing free
2015-07-19 07:16:24 +02:00
Hleran 59f6cd5453 lua_plugin: rpc uwsgi_malloc and missing free
I noticed that all cool kids are using uwsgi_malloc instead of malloc;
Also I noticed, that I forgot to free memory last time (while playing on high level languages)
2015-07-18 23:28:12 +03:00
unbit 11cddaf56c Merge pull request #969 from xtfxme/python-mule-from-callable-lazy-apps
move initialization of up.loaders to uwsgi_python_preinit_apps
2015-07-17 06:43:53 +02:00
C Anthony Risinger d01bd639a7 move initialization of up.loaders to uwsgi_python_preinit_apps, fixes #968 2015-07-16 14:29:46 -05:00
unbit f1ef2eecfe Merge pull request #967 from xtfxme/python-mule-from-callable
load python mule from callable, eg. --mule=package.module:callable
2015-07-16 01:21:55 +02:00
unbit c840e4d54e Merge pull request #966 from rrva/master
SOL_TCP is not defined on OSX
2015-07-16 01:19:59 +02:00
C Anthony Risinger 0187247899 load python mule from callable, eg. --mule=package.module:callable 2015-07-15 17:04:25 -05:00
Ragnar Rova b608eb1772 OSX 10.11 supports TCP_FASTOPEN
But does not define SOL_TCP.
IPPROTO_TCP is the equivalent.
2015-07-15 21:54:39 +02:00
unbit 03b86d8414 Merge pull request #957 from xrmx/brownpaper0807
Fix compilation in router_access
2015-07-08 13:14:02 +02:00
Riccardo Magliocchetti da897a36fc Fix compilation in router_access
Typo introduced in 837da66440
2015-07-08 12:42:44 +02:00
unbit a99ee6d09d Merge pull request #909 from xrmx/coverity050515-2
Fishy coverity fixes
2015-07-08 12:37:41 +02:00
unbit fe61e661bd Merge pull request #956 from xrmx/coverity0707-2
A few more coverity fixes
2015-07-07 23:48:14 +02:00
unbit 5926144ebd Merge pull request #955 from xrmx/norouter
More specific error when you are missing a router plugin
2015-07-07 23:45:15 +02:00
Riccardo Magliocchetti 102f7387cb plugins/tuntap: add missing return on error
Reported by Coverity as CID #1308282
2015-07-07 18:32:43 +02:00
Riccardo Magliocchetti 5b56f7c570 plugins/alarm_curl: avoid null dereference
An || may be the intended operator instead of && as equal may be
null and dereferenced a couple of lines later.

Reported by Coverity as CID #1308281
2015-07-07 18:26:33 +02:00
Riccardo Magliocchetti 06e96275d9 plugins/webdav: correct variable reference
We probably want to check againt rlen2 instead of rlen.

Reported by Coverity as CID #1308278
2015-07-07 18:22:12 +02:00
Riccardo Magliocchetti fc1e9407c7 plugins/airbrake: remove dead code
p is checked for null inside a while(p) loop.

Reported by Coveriy as CID #1308279
2015-07-07 18:18:57 +02:00
Riccardo Magliocchetti 837da66440 plugins/router_access: fix copy-paste error
Reported by Coverity as CID #1308276
2015-07-07 18:16:24 +02:00
Riccardo Magliocchetti a2aa5a69a4 More specific error when you are missing a router plugin
The "missing router" bit could help figuring out what's wrong.
2015-07-07 18:13:20 +02:00
unbit 86a5c2ffe1 Merge pull request #954 from xrmx/coverity0707
A few coverity fixes
2015-07-07 16:54:11 +02:00
Riccardo Magliocchetti ffc1c742c0 plugins/emperor_amqp: fix leak on error path
Reported by Coverity as CID #1308287
2015-07-07 16:14:23 +02:00
Riccardo Magliocchetti eb617e225f plugins/emperor_amqp: fix wrong exit point on error
Fixes a memory leak.

Reported by Coverity as CID #1308290
2015-07-07 16:07:13 +02:00
Riccardo Magliocchetti af440aee53 plugins/emperor_amqp: fix leak on error path
Reported by Coverity as CID #1308291
2015-07-07 16:00:18 +02:00
Riccardo Magliocchetti 13e30ffa80 plugins/router_radius: fix memory leak on error path
Reported by Coverity as CID #1308294
2015-07-07 15:55:43 +02:00
Riccardo Magliocchetti 7648109b0c plugins/tuntap: remove self assignment
Reportedy by Coverity as CID #1308283
2015-07-07 15:52:16 +02:00
Riccardo Magliocchetti f674af3972 Don't touch rss if it hasn't been initialized in get_memusage
Followup for Coverity CID 1308302
2015-07-07 15:49:14 +02:00
Riccardo Magliocchetti 9e24385cb1 Avoid usage of uninitialized variable
Reported by Coverity as CID #1308302
2015-07-07 15:44:14 +02:00
Unbit 26babdffb0 added unix signal registration hook 2015-07-06 16:09:55 +02:00
unbit 7a9d281994 Merge pull request #953 from parasyte/feature/pypy-logvar
Add `uwsgi.get_logvar()` and `uwsgi.set_logvar()` support to the PyPy plugin
2015-07-03 12:36:42 +02:00
unbit 4161f9b4e2 Merge pull request #952 from parasyte/bug/fix-pypy-setup-osx
Fix pypy-setup on OSX
2015-07-03 12:36:02 +02:00
Jay Oster bfbc254108 Use getsectiondata as a fallback to the dlsym method
- Mirrors the method of adding the resource; `-sectcreate` is used as a fallback to `ld -b binary`
2015-07-03 02:48:34 -07:00
Jay Oster 36e045c4f7 Add uwsgi.get_logvar() and uwsgi.set_logvar() support to the PyPy plugin 2015-07-03 01:16:44 -07:00
Jay Oster f07e6db7af Fix pypy-setup on OSX
- `ld` on OSX does not support the `-b` flag, so use `-sectcreate` to embed the Python resource in the executable
- Mach-o section names are truncated to 16 characters, so remove the `_uwsgi_` prefix
- Use `getsectiondata()` to load the Python resource from the new section
- Compile the CFFI lib with hooks declared `extern` to ensure the correct pointers are referenced from the Python script
2015-07-03 00:29:23 -07:00
Unbit fa73189f11 fixed #918 2015-07-01 08:35:16 +02:00
unbit 39a4389fd0 Merge pull request #951 from fabzzap/master
Check whether *value is indeed an SvRV before casting it
2015-07-01 06:11:49 +02:00
Fabrizio Gennari 2c9bcd0605 Check whether *value is indeed an SvRV before casting it 2015-06-30 23:54:40 +02:00
unbit 4f64b97ba2 Merge pull request #950 from jimfunk/master
Fix version detection for gcc 5
2015-06-30 08:00:29 +02:00
James Oakley e7b79a07b4 Fix version detection for gcc 5 2015-06-28 12:36:40 -07:00
Unbit 056417303c ensure the mem_collector does not receive signals 2015-06-16 18:29:23 +02:00
unbit c13ceb4a0c Merge pull request #944 from methane/cheaper-spare2
Add spare2 cheaper algorithm for larger workload
2015-06-16 10:11:53 +02:00
INADA Naoki f3bd8a9fab Add spare2 cheaper algorithm for larger workload 2015-06-16 16:17:22 +09:00
unbit df22643654 Merge pull request #942 from nopjmp/master
add content_encoding to router_redis
2015-06-15 07:48:55 +02:00
nopjmp 0439cfb5ba add content_encoding to router_redis 2015-06-13 21:50:57 -05:00
unbit 1ee961382d Merge pull request #940 from methane/cheaper-spare-faster-spawn
When cheaper_overload=1, decheap worker for every 1 sec
2015-06-12 07:26:58 +02:00
INADA Naoki 58c99abc38 When cheaper_overload=1, decheap worker for every 1 sec 2015-06-11 18:59:48 +09:00
unbit b03791785c Merge pull request #936 from Darvame/patch-1
some features
2015-06-08 11:22:02 +02:00
Roberto De Ioris 40c31f4601 added fixpathinfo routing action 2015-06-07 19:36:29 +02:00
Hleran 993fd384f1 some features
- rpc calls from my lua app ('local str = uwsgi.rpc(node, func_name, arg1, arg2, ...);')
- global "uwsgi.req_input_read" alias of local "env.input.read" function
- can yield numbers as well
- can return nil instead of header's table (same as {})
- can return nil or string (or number) instead of coroutine
2015-06-07 15:37:39 +03:00
Roberto De Ioris 3de97b9f7e fixed shared sockets for gateways 2015-06-03 07:23:48 +02:00
unbit 1b90727e31 Merge pull request #932 from protoCall7/fix-psgi-type-conflict
Changed abs to labs because offset is declared as a long
2015-06-02 09:03:12 +02:00
unbit d972ae9eca Merge pull request #934 from parasyte/bug/fix-for-pypy-plugin
Add null terminator to uwsgi_get_dot_h() and uwsgi_config_py()
2015-06-02 08:59:25 +02:00
Jay Oster fb7f9f228a Add null terminator to uwsgi_get_dot_h() and uwsgi_config_py()
- Fixes #933
2015-06-01 17:43:48 -07:00
protoCall7 8a1f6c440a Changed abs to labs because offset is declared as a long 2015-06-01 16:50:20 -07:00
Unbit 3e5493259e added sor and micros routing vars 2015-05-28 12:24:22 +02:00
Roberto De Ioris c92a0a3857 fixed #649 2015-05-23 05:16:02 +02:00
unbit 25893678fc Merge pull request #929 from hulu/wait-init-thread-last
Wait for initial thread last.
2015-05-23 05:05:32 +02:00
Kevin Xu b0f62cfccd Wait for initial thread last.
Since after calling pthread_cancel() and pthread_join() on initial
thread, the worker process will appear to be a zombie, which prevents
worker process to report its own memory stat, and if one of the spawned
threads hangs, the worker process will hang forever since
evil-reload-on-rss won't work when memory stat is missing.
2015-05-22 16:14:44 -07:00
unbit ff3f7f3d2f Merge pull request #907 from xrmx/050515
Update coverity build profile
2015-05-21 10:18:13 +02:00
unbit 5399b083d6 Merge pull request #905 from xrmx/coveritybuildflags
Don't define UWSGI_CFLAGS for coverity build profile
2015-05-21 10:10:48 +02:00
unbit cd4bfb27e4 Merge pull request #928 from WeirdCarrotMonster/master
Added replica set support to emperor_mongodb and fixed uwsgi_instance attribute setup
2015-05-21 10:10:20 +02:00
Евгений Протозанов 3a7bcb46dc Added replica set support 2015-05-21 11:14:03 +04:00
Евгений Протозанов 7b461838e0 Added mongo::client::initialize() call to default mongodb monitor init 2015-05-21 10:22:28 +04:00
Евгений Протозанов c8fb572647 Fixed segfault on loading default values 2015-05-21 10:19:43 +04:00
Евгений Протозанов c0634013c4 Added -lboost_system to avoid import errors 2015-05-21 10:18:56 +04:00
Евгений Протозанов ea9f95b19f Releasing attrs memory when it's needed 2015-05-21 07:38:32 +04:00
Евгений Протозанов f3688a34ec Added deallocating function for uwsgi_dyn_dict 2015-05-21 07:37:11 +04:00
Евгений Протозанов 3119a0ad77 Added mongo::client::initialize() call and default value support to emperor_mongodb monitor 2015-05-21 00:17:00 +04:00
Евгений Протозанов 9f696030a2 Rewrote uwsgi_emperor_simple_do_with_attrs to set instance attributes before starting it 2015-05-21 00:11:29 +04:00
Roberto De Ioris aaca4ef236 added memory collector 2015-05-17 05:52:27 +02:00
Unbit c73f11bc8d attempt to fix a bug spotted by funkybob on irc 2015-05-15 06:45:47 +02:00
unbit 0a765f9fb4 Merge pull request #908 from xrmx/coverity050515
Some coverity fixes
2015-05-14 06:20:31 +02:00
Unbit be01eacb6e added bigranges sharedarea tests 2015-05-13 15:42:41 +02:00
Unbit 9640312e22 fixed #922 2015-05-13 15:08:17 +02:00
unbit 26a6a8506b Merge pull request #921 from Algy/issue-920-mmap-error
Fix error handling for mmap()
2015-05-13 12:56:38 +02:00
Alchan Kim 0bfbf7613b plugin/ugreen: Fix error handling for mmap() 2015-05-13 19:42:31 +09:00
Roberto De Ioris f514134293 fixed #914 2015-05-12 06:27:42 +02:00
Roberto De Ioris d595faa624 fixed zero size gzip chunks 2015-05-08 06:57:36 +02:00
Roberto De Ioris 84374ba4f9 implementation of #904 2015-05-06 09:11:35 +02:00
Roberto De Ioris a358816dc7 added Vladimir Didenko to CONTRIBUTORS and report CA errors only on ssl-verbose mode 2015-05-06 07:24:11 +02:00
unbit e9013e0079 Merge pull request #910 from vladimir-didenko/client-cert
Fix client certificate validation. Log verification errors
2015-05-06 07:22:30 +02:00
Vladimir Didenko c444baef22 Extract verification details only in error case 2015-05-05 19:15:44 +03:00
Vladimir Didenko e60430a826 Fix client certificate validation. Log validation errors 2015-05-05 16:20:59 +03:00
Riccardo Magliocchetti 2d732d229e core/utils: remove unused assignment
Reported by Coverity as CID #1231250
2015-05-05 15:19:25 +02:00
Riccardo Magliocchetti 10c0c1d0c5 plugins/xslt: remove unused assignment
Reported by Coverity as CID #1231252
2015-05-05 15:17:01 +02:00
Riccardo Magliocchetti 752f5aada6 core/cache: remove ignored assignment
key_len value gets reassigned few lines below.
Reported by Coverity as CID #1231251
2015-05-05 15:14:26 +02:00
Riccardo Magliocchetti 3dfbf879d9 Fix resource leak in uwsgi_zerg_attach
Reported by Coverity as CID #1296717
2015-05-05 14:31:44 +02:00
Riccardo Magliocchetti a2b6d33c8f core/emperor: fix a few memory leaks
Reported by Coverity as CID #1296718, #1296719, #1296720
2015-05-05 14:27:22 +02:00
Riccardo Magliocchetti 7151bf4480 fix memoery leak in uwsgi_setns
Reported by Coverity as CID #1296721
2015-05-05 14:21:27 +02:00
Riccardo Magliocchetti 42ac14449c core/legion: fix use of uninitialized value
Rework conditionals so that best_uuid is always initialized.
Reported by Coverity as CID #1296722
2015-05-05 14:18:30 +02:00
Riccardo Magliocchetti 8c04b3d960 plugins/cgi: fix use after free
Reported by Coverity as CID #1296723
2015-05-05 14:12:33 +02:00
Riccardo Magliocchetti e2e23a92d9 Update coverity profile
Aka the kitchen sink profile
2015-05-05 12:37:43 +02:00
Riccardo Magliocchetti 5b49e179f7 Use unsigned long long type for uwsgi_libtcc_counter
Fix compilation here, no functional change.
2015-05-05 12:37:35 +02:00
Riccardo Magliocchetti d5dd694481 Don't define UWSGI_CFLAGS for coverity build profile
coverity cli tools have supposedly a fixed buffer to contain each
compiler invocation. The embedding of UWSGI_CFLAGS of course breaks
that limit. The issue has been reported for more than a year and they
have not fixed that. So add this hack to make sure we don't define
UWSGI_CFLAGS if the build profile ends with 'coverity.ini'.
2015-05-05 11:45:16 +02:00
Riccardo Magliocchetti 0c159cb8e5 Revert "emperor: use fchmod instead of chmod to avoid TOCTOU race"
Using fchmod on sockets is not portable.
This reverts commit 9e163df897.
2015-05-01 14:25:30 +02:00
Riccardo Magliocchetti 2906df547a Revert "master: use fchmod instead of chmod to avoid TOCTOU race"
Using fchmod on sockets is not portable.
This reverts commit 7aee33d402.
2015-05-01 14:25:18 +02:00
Riccardo Magliocchetti a0386be0a8 Revert "socket: use fchmod to avoid chmod TOCTOU race"
Using fchmod on sockets is not portable
This reverts commit 00e7c54f7c.
2015-05-01 14:24:38 +02:00
Roberto De Ioris c6789af0f7 added wait-for-socket 2015-05-01 13:24:51 +02:00
unbit 81eb1b6b70 Merge pull request #902 from xrmx/toctou-chmod
Covert most chmod users to fchmod
2015-04-30 20:04:53 +02:00
Riccardo Magliocchetti 00e7c54f7c socket: use fchmod to avoid chmod TOCTOU race
Reported by flawfinder
2015-04-30 18:53:43 +02:00
Riccardo Magliocchetti 7aee33d402 master: use fchmod instead of chmod to avoid TOCTOU race
Reported by flawfinder
2015-04-30 15:38:45 +02:00
Riccardo Magliocchetti 39bea1de5d logging: use fchmod instead of chmod to avoid TOCTOU race
Reported by flawfinder
2015-04-30 15:38:45 +02:00
Riccardo Magliocchetti 9e163df897 emperor: use fchmod instead of chmod to avoid TOCTOU race
As reported by flawfinder
2015-04-30 15:38:45 +02:00
unbit 2f830d2e23 Merge pull request #848 from funkybob/master
Don't try to compress empty responses.
2015-04-30 13:07:41 +02:00
Curtis Maloney 1d00912c39 Free the utgz structure before exit. 2015-04-30 21:04:12 +10:00
unbit f935f138f4 Merge pull request #891 from JRaspass/master
plugins/psgi - refactor env population
2015-04-18 07:44:00 +02:00
James Raspass 0389748d4a plugins/psgi - use PL_sv_{yes,no} in env
Use PL_sv_yes & PL_sv_no instead of newSViv(1) & newSViv(0) for bools
as they're interpreter globals that don't need to be created everytime.

Added a test and refactored the tests that were added with a1e30157,
all .t files in t/perl are now ran under all major perl versions with
and without threading when t/perl/run is invoked.

On my box, psgi_plugin.o went from 62,296 bytes to 62,208 bytes. Not a
huge saving I'll grant you, but every little helps :-)
2015-04-17 08:50:05 +01:00
Roberto De Ioris ddc3972d98 added die_on_no_workers, fixes #889 2015-04-16 07:41:11 +02:00
Roberto De Ioris 1054b60040 --reuse-port can be used on linux too 2015-04-14 06:17:47 +02:00
Roberto De Ioris 22eaf96ffe mention WeirdCarrotMonster as contributor for gridfs 2015-04-14 06:16:32 +02:00
Roberto De Ioris 17cb520643 Merge branch 'WeirdCarrotMonster-master' 2015-04-14 06:14:05 +02:00
Roberto De Ioris 200de606bb merged new gridfs plugin 2015-04-14 06:13:40 +02:00
Roberto De Ioris bcf9c851dd added Curtis Maloney to CONTRIBUTORS 2015-04-13 06:53:49 +02:00
Roberto De Ioris 7020840bdc fixed remote plugins embedding 2015-04-13 06:48:24 +02:00
unbit 334baa8050 Merge pull request #886 from funkybob/feature/cleanup
Tidy with flake8
2015-04-13 06:42:03 +02:00
Roberto De Ioris 6c2f3f1214 added James Raspass to CONTRIBUTORS 2015-04-13 06:40:52 +02:00
unbit d456f49796 Merge pull request #881 from JRaspass/master
plugins/psgi - remove the need for Scalar::Util
2015-04-13 06:40:12 +02:00
James Raspass a1e3015783 plugins/psgi - remove the need for Scalar::Util
Commit ff9bab4b fixed support for sending IO like handles or GLOBs
via sendfile by first calling fileno on them. This was checked
by calling Scalar::Util::reftype on the reference first, as per
https://metacpan.org/pod/PSGI#Body . This may be sane in pure
perl, but there are better methods in XS/C than string evalling
some Perl, which will eventually also call some XS/C.

This commit introduces more robust checking of whether we have a
"real" filehandle, and also introduces a test that chucks a bunch
of different scalars and references at uWSGI to make sure it doesn't
choke. I wasn't sure how to hook this test up to travis, or wether
that's even desireable, so just left the test in what I believe to
be the right directories.

Because this commit massively simplifies the code, it also had an
effect on object size, on my machine (x64, GCC 4.9), psgi_plugin.o
went from 63360 bytes to 62296 bytes.

The indentation level of the ->getline for loop has been left at
its original level, which is now incorrect, to make the diff
easier to read. A whitespace cleanup commit could follow.

In related news, does anyone know the purpose of the three other
use lines in psgi_loader.c, two of them were added back in 2011
by cf08972e, but I can't work out what their inclusion has to do
with memleak hunting.

Basically I would love to remove these lines as I don't believe
they're needed for uWSGI to function, and if apps running under
uWSGI need them, they should load them themselves.

Also related, would more PSGI refactorings be welcome? I get the
impression that Perl is a bit of a second class citizen in uWSGI
these days, and as both an avid user of uWSGI+PSGI and a hobby XS
developer, I'd love to clean up more of the PSGI plugin.
2015-04-11 23:16:27 +01:00
Curtis 057cfe761f Tidy with flake8 2015-04-11 22:50:11 +10:00
Евгений Протозанов d873bdecaf Passing timeout argument to MongoDB connection 2015-04-10 23:38:38 +04:00
Евгений Протозанов de28a705d8 Fixed server list parsing 2015-04-10 23:07:41 +04:00
Евгений Протозанов 777d7184c5 Updated GridFS plugin to work with legacy mongo-cxx-driver version 1.0.0 2015-04-10 22:56:59 +04:00
Unbit f6e5db93d8 fixed #883 2015-04-10 15:54:11 +02:00
Unbit 89ed5a26aa fixed typo 2015-03-25 09:41:31 +01:00
unbit 152771dfcd Merge pull request #870 from sammko/sammko-patch
Fix grammar
2015-03-16 21:05:52 +01:00
Samuel Čavoj 83acb83075 Fix grammar.
Grammar is important!
2015-03-16 20:54:53 +01:00
Unbit 498b1e49c4 added support for UNIX sockets to rsyslog 2015-03-09 11:20:29 +01:00
Unbit 32e0c7de99 revert syslog patch 2015-03-09 11:16:34 +01:00
Unbit 08e846ff0d attempt to fix #866 2015-03-08 13:14:08 +01:00
unbit da3067e9ae Merge pull request #839 from ikruglov/master
psgi_loader: fix a one off bug in XS_input_seek()
2015-03-03 15:39:34 +01:00
Curtis Maloney 47a15480da Don't try to compress empty responses. 2015-02-20 13:44:42 +11:00
Unbit b60d9822e6 fixed #846 2015-02-19 06:54:01 +01:00
Unbit 913e7e42fc Merge branch 'master' of https://github.com/unbit/uwsgi 2015-02-19 06:53:34 +01:00
unbit c4e17a081d Merge pull request #840 from xtfxme/uwsgi_route_var_upper
new routing func: ${upper[REQUEST_URI]}
2015-02-14 09:37:17 +01:00
C Anthony Risinger c0b651f39b new routing func: ${lower[REQUEST_URI]} 2015-02-14 01:17:55 -06:00
C Anthony Risinger 696be4bc76 new routing func: ${upper[REQUEST_URI]} 2015-02-14 01:11:46 -06:00
Ivan Kruglov d7158ccb23 psgi_loader: make sure that at least two params are passed to XS_input_seek() 2015-02-13 14:20:19 +01:00
Ivan Kruglov 933d7e7cba psgi_loader: fix a one off bug in XS_input_seek() 2015-02-13 13:11:02 +01:00
Unbit 11b0e431f4 attempt to fix #833 2015-02-11 11:37:54 +01:00
Roberto De Ioris 18ddfae5ca fixed emperor wrapper 2015-02-10 20:35:42 +01:00
Roberto De Ioris c90c5b7a92 fixed emperor wrappers logs 2015-02-10 20:31:25 +01:00
Roberto De Ioris 6339e9bdc1 added --emperor-wrapper-override and --emperor-wrapper-fallback 2015-02-10 20:25:35 +01:00
Roberto De Ioris 0768122d90 added safeexec hook 2015-02-10 20:10:43 +01:00
Unbit 28dffb5ce2 fixed scandir 2015-02-08 17:35:36 +01:00
Unbit c6182dd539 fix return value for hv_store in uwsgi::opt 2015-02-08 17:34:06 +01:00
Roberto De Ioris faffe75a53 typo 2015-01-28 07:10:07 +01:00
Roberto De Ioris c74428a3aa fixed exception handler for arguments 2015-01-28 06:49:56 +01:00
Riccardo Magliocchetti 5e9e07c64f core/static: print mimetype of file on debug print 2015-01-23 11:54:39 +01:00
unbit 6ab2095c3c Merge pull request #808 from methane/python34
Drop Python 3.1 and Add 3.4.
2015-01-16 14:57:50 +01:00
unbit 68bff97f36 Merge pull request #814 from xrmx/coverity150114-3
More coverity fixes
2015-01-16 10:55:07 +01:00
Riccardo Magliocchetti 9d70f39272 core/cache: avoid possible null dereference
The check at line 426 implies uc->name may be null.

Reported by Coverity as CId #990168
2015-01-14 22:12:31 +01:00
Riccardo Magliocchetti 9b8390f602 core/io: avoid integer overflow
Reported by coverity as CID #1100806
2015-01-14 22:08:09 +01:00
Riccardo Magliocchetti 428461838e proto/http: add missing check for getsockname return value
Reported by Coverity as CID #1264340
2015-01-14 21:54:42 +01:00
Riccardo Magliocchetti 236fe6d01a core/master_utils: add missing unlock
As reported by Coverity as CID #1264342
2015-01-14 21:49:59 +01:00
Riccardo Magliocchetti 421b0bae1a core/fork_server: fix memory leak
Reported by Coverity as CID #1264348
2015-01-14 21:45:09 +01:00
Riccardo Magliocchetti d24f7371fc core/utils: fix memory leak
Reported by Coverity as CID #971042
2015-01-14 21:28:38 +01:00
Riccardo Magliocchetti bad0edfc10 core/alarm: fix memory leak
Reported by Coverity as CID #971006
2015-01-14 21:19:24 +01:00
unbit b7e6e081ed Merge pull request #813 from xrmx/coverity150114-2
A couple more fixlets
2015-01-14 18:35:37 +01:00
Riccardo Magliocchetti d5392483d2 core/webdav: fix copy&paste error
Reported by Coverity as CID #1264341
2015-01-14 18:10:43 +01:00
Riccardo Magliocchetti 4cd0f4eede proto/puwsgi: remove double assignment
Reported by Coverity as CID #1264343
2015-01-14 18:07:04 +01:00
unbit 0eccf24ff9 Merge pull request #811 from xrmx/coverity150114
Some coverity fixes
2015-01-14 16:20:31 +01:00
Riccardo Magliocchetti 4998a10578 subscription: fix memory leak
Reported by CID as #1264346
2015-01-14 15:32:48 +01:00
Riccardo Magliocchetti 2cd5d51ca9 core/hooks: fix a couple of leaks
Reported by Coverity as CID #1264345, #1264347
2015-01-14 15:27:25 +01:00
Riccardo Magliocchetti 4b9627950d router_memcached: fix a few memory leaks
Reported by Coverity as CID #1264350, #1264349
2015-01-14 15:25:26 +01:00
Riccardo Magliocchetti cd115371b0 router_static: fix a couple of memory leaks
Reported by Coverity as CID #1264352, #1264351
2015-01-14 15:18:57 +01:00
Riccardo Magliocchetti 0ac92e1ad1 router_static: fix memory leak
Reported by Coverity as CID #1264353
2015-01-14 15:15:43 +01:00
Riccardo Magliocchetti 5432b7930c router_redis: fix memory leak
Reported by Coverity as CID #1264354
2015-01-14 15:14:25 +01:00
Riccardo Magliocchetti 61d8ce0a87 router_static: fix memory leak
Reported by Coverity as CID #1264355
2015-01-14 15:12:11 +01:00
Riccardo Magliocchetti 9f060d05f6 router_redis: fix memory leak
Reported by Coverity as CID #1264356
2015-01-14 14:58:39 +01:00
Riccardo Magliocchetti 3f4ef483a2 Fix double free in rpc plugin
Reported by Coverity as CID #1264357
2015-01-14 14:55:54 +01:00
unbit aa5e2a2e6f Merge pull request #810 from tsuyo/patch-1
Add :use_ssl=>true to extconf.rb
2015-01-14 06:55:36 +01:00
Tsuyoshi Miyake 0276d2a7b1 Add :use_ssl=>true to extconf.rb
It seems installer is on https://uwsgi.it/install (as of Jan 14, 2015). Without this change, "gem install uwsgi" do almost nothing.
2015-01-14 13:16:44 +09:00
INADA Naoki c3f3b37c51 Drop Python 3.1 and Add 3.4.
Travis-CI now uses pyenv for Python versions.
It supports 2.6, 2.7, 3.2~.
2015-01-13 17:02:31 +09:00
Unbit b752d74a9e increased goodbye_cruel_world reason stack size 2015-01-07 12:48:19 +01:00
unbit 795caf9543 Merge pull request #805 from akx/reasons
Add reasons to worker self-shutdown messages.
2015-01-08 09:01:01 +01:00
Aarni Koskela 2417acf80a Allow floating-point values for 'megabytes' options. 2015-01-08 09:49:32 +02:00
Aarni Koskela 91a04dd461 Add reasons to worker self-shutdown messages.
This should make it easier to understand why a worker is shutting down.

* Modify `goodbye_cruel_world` to accept a `reason` format string and
  varargs.
* Modify calls to the above function to include a verbose reason string.
* Modify the `gbcw_hook` used by the Gevent plugin to adhere to the new
  API.
2015-01-08 09:44:03 +02:00
Unbit a7e286b174 it's 2015 2015-01-05 20:29:18 +01:00
Unbit 165d7201ec another range header improvement 2015-01-05 13:53:33 +01:00
Unbit 606dc8bb1f fixed range 2015-01-04 15:03:17 +01:00
Unbit b380ca3ace support for fastrouter in-memory post-buffering 2014-12-27 13:24:53 +01:00
unbit 74990eef01 Merge pull request #802 from xrmx/compilefix
Fix fastrouter compilation
2014-12-27 12:50:34 +01:00
Riccardo Magliocchetti b543b0bad8 Fix fastrouter compilation
After 6a8f18a9bb

Fix #801
2014-12-27 12:41:00 +01:00
Roberto De Ioris 6a8f18a9bb re-implemented post-buffering in fastrouter 2014-12-24 09:08:45 +01:00
unbit bc629a1985 Merge pull request #800 from janos/master
Write pidfile and pidfile2 only after successful start
2014-12-24 06:24:26 +01:00
Janos Guljas 7eebcf3246 Move safe_pidfile and safe_pidfile2 at the end of uwsgi_server struct 2014-12-23 19:32:33 +01:00
Janos Guljas 54ff63e280 Implement safe-pidfile and safe-pidfile2 2014-12-23 19:13:51 +01:00
Janos Guljas 789f32fcb6 Python 3 compatibility 2014-12-23 17:38:01 +01:00
Janos Guljas 197c8d1f3d Python 3 compatibility 2014-12-23 17:34:02 +01:00
Janos Guljas 78a59ca2e8 Python 3 compatibility 2014-12-23 17:17:28 +01:00
Janos Guljas 40fa1579e6 Fix inconsistent use of tabs and spaces in indentation 2014-12-23 17:06:17 +01:00
Janos Guljas 7a057f144a Fix inconsistent use of tabs and spaces in indentation 2014-12-23 17:04:16 +01:00
Janos Guljas d79eeefe97 Write pidfile and pidfile2 only after successful start 2014-12-23 15:39:19 +01:00
Roberto De Ioris b59294db89 implemented uwsgi::opt in perl 2014-12-12 07:01:08 +01:00
Roberto De Ioris 69e2da54ef implemented --pull-header 2014-12-11 15:53:44 +01:00
unbit 17223e25e5 Merge pull request #792 from m0sia/master
Fixing build against uclibc
2014-12-10 12:18:30 +01:00
Dmitry Moiseev 5e6c3c40ff Merge branch 'master' of https://github.com/unbit/uwsgi 2014-12-10 16:12:43 +05:00
Dmitry Moiseev b912ae0a48 Fixing build against uClibc 2014-12-10 16:08:55 +05:00
Unbit 3f8c585d76 Merge branch 'master' of ssh://github.com/unbit/uwsgi 2014-12-10 10:44:32 +01:00
Unbit 5e29359422 another check for mod_proxy_uwsgi 2014-12-10 10:44:16 +01:00
Roberto De Ioris 69be96ba76 fixed master-fifo + cheaper 2014-12-09 09:54:04 +01:00
unbit 2ef4070cb0 Merge pull request #791 from xrmx/cppcheck812
Fix leak on error in bind_to_unix
2014-12-08 17:23:26 +01:00
Riccardo Magliocchetti b82c64db86 Fix leak on error in bind_to_unix
Spotted by cppcheck.
2014-12-08 16:55:10 +01:00
Unbit 6e556eff7c fix #785 2014-12-05 15:23:12 +01:00
Unbit e6f4e7108f another attempt at fixing mod_proxy_uwsgi 2014-12-05 15:08:18 +01:00
Unbit 2d5b89d8eb fixed #787 2014-12-05 09:11:33 +01:00
Unbit 70b95828c7 improved mono plugin 2014-12-04 20:55:25 +01:00
Unbit e0aa4b9d0a goodbye insane SIGTERM management 2014-12-04 20:20:00 +01:00
Roberto De Ioris c93b7f8fbf fixed #776 2014-12-06 10:38:57 +01:00
Unbit 70324ade1b fixed #680 2014-12-06 09:13:55 +01:00
Unbit 81858efe6e attempt to fix #774 2014-12-06 08:19:29 +01:00
Unbit d74d76d7ae Merge branch 'master' of ssh://github.com/unbit/uwsgi 2014-11-28 14:49:16 +01:00
Unbit 87bd5ee34f detect modern pypy 2014-11-28 14:48:54 +01:00
Unbit 353cbb9ab2 fixed SERVER_NAME in http router 2014-11-22 13:35:27 +01:00
Unbit 68a17d0b51 ported peer name fixes 2014-11-22 13:33:14 +01:00
Unbit 96a5ef488c fix peer name in corerouters [2] 2014-11-22 13:28:32 +01:00
Roberto De Ioris e46b75924c fix http for merging 2014-11-22 13:28:30 +01:00
Unbit f42294c0a3 fix #778 2014-11-21 08:36:14 +01:00
Roberto De Ioris 59119498d8 attempt to fix #340 2014-11-21 04:09:21 +01:00
unbit 63e9d0ce0f Merge pull request #767 from comel/master
Daemon touch kill failback.
2014-11-19 10:29:54 +01:00
Unbit 63b93aaddd another round of ssl fixes 2014-11-18 19:22:14 +01:00
Unbit 81d2eccc75 try to improve ssl management 2014-11-18 19:21:59 +01:00
Roberto De Ioris 2b24f7b885 fixed destruction 2014-11-16 21:00:35 +01:00
Unbit 14702977a4 added active-workers signal target, aimed at improving #58 2014-11-16 18:48:12 +01:00
Unbit 7a20c4974f fixed python3 --py-auto-reload-ignore 2014-11-15 13:21:28 +01:00
Unbit ffd7487e48 fixed modifers usage in corerouters 2014-11-15 13:21:01 +01:00
Unbit c9c1ff676f ported 2.0.9 improvements 2014-11-14 15:43:47 +01:00
Roberto De Ioris 80c3d6528b support yajl brew 2014-11-14 06:02:10 +01:00
Unbit 71b441358f less strict http generator 2014-11-13 11:57:51 +01:00
unbit beebc2981f Merge pull request #772 from avar/avar/psgi-call-DESTROY-also-on-harakiri
psgi: Ensure that we call any DESTROY hooks on psgix.harakiri.commit
2014-11-11 17:11:45 +01:00
Ævar Arnfjörð Bjarmason e0e8bb1932 psgi: Don't free the wsgi_req->async_environ atexit, only in request context
The atexit hooks can be called outside of the request context. See the
discussion at https://github.com/unbit/uwsgi/pull/772
2014-11-11 16:03:00 +00:00
Ævar Arnfjörð Bjarmason 0a27a334cb psgi: Remove the check for the async mode in uwsgi_perl_atexit
According to Roberto this is just copy/pasted from the Python code, see
1.0.1-289-gd7e8523.
2014-11-11 16:00:49 +00:00
Ævar Arnfjörð Bjarmason 1dcdb72054 psgi: Move the destruction of the perl interpreter to the atexit hook + more bugfixes
My previous commit ensured that we called the DESTROY hook but we
wouldn't properly call the atexit hook. Now when you start uWSGI as
instructed in that commit you'll get this:

 * localhost:1234?0:

   $$: Calling DESTROY

 * localhost:1234?1:

   *** psgix.harakiri.commit requested ***
   ...The work of process 523 is done. Seeya!
   523: Calling the atexit hook
   523: Calling DESTROY

 * Ctrl+C (or stop):

   ^CSIGINT/SIGQUIT received...killing workers...
   696: Calling the atexit hook

Before this change we wouldn't call the atexit hook when
psgix.harakiri.commit was requested by calling localhost:1234?1.

To make this work I removed the "if busy do not run atexit hooks"
condition added in 1.4-rc2-246-g499202e. Of course uWSGI is going to
think the worker is "busy", it's busy being destroyed, that doesn't mean
we should skip running the atexit hooks.

We'll still skip them under the "if hijacked do not run atexit hooks"
condition added in that commit, and the "managing atexit in async mode
is a real pain" condition added in 1.0.1-289-gd7e8523. Maybe those are
further bugs that need to be solved, but I don't know how to test those
modes.

Now we'll also call PERL_SET_CONTEXT() and PERL_SYS_TERM() appropriately
during destruction. Note that the latter should only be called once even
if you have multiple interpreters.
2014-11-11 13:09:05 +00:00
Ævar Arnfjörð Bjarmason 7ef33950c5 psgi: Ensure that we call any DESTROY hooks on psgix.harakiri.commit
Before this we'd just exit(0) and let the OS clean up after us, but
e.g. with post-buffering=1 we'll end up with a temporary file in /tmp
that we won't clean up when we exit unless DESTROY is called.

This resulted in us leaking files in /tmp if we ever had a request where
the last request before a harakiri was a POST request with a body we'd
buffer to /tmp.

We'd have similar leaks in any user-defined code that required DESTROY
to run.

Aside from this I'm still not very comfortable with what this whole code
here in psgi_plugin.c and psgi_loader.c is doing when managing the
interpreter(s). It:

 * Doesn't consistently call PERL_SET_CONTEXT() as described in "perldoc
   perlembed".

 * Nothing calls PERL_SYS_TERM() either.

 * Should we be calling uwsgi_perl_free_stashes() here too?

To test this:

    UWSGI_PROFILE=psgi python uwsgiconfig.py --build
    ./uwsgi --master --http-socket localhost:1234 --psgi t/perl/test_harakiri.psgi

Then elsewhere:

    curl 'localhost:1234?0'
    curl 'localhost:1234?1'

Both of those should emit "Calling DESTROY".
2014-11-10 18:57:52 +00:00
unbit dd0688ee84 Merge pull request #770 from xrmx/printformat
systemd_logger: fix compilation with -Werror=format-security
2014-11-06 12:00:27 +01:00
Riccardo Magliocchetti 2ab6c94da6 systemdlogger: fix compilation with -Werror=format-security 2014-11-06 11:00:32 +01:00
Unbit 09ab2a3d39 fixed unmasked websocket 2014-11-06 09:02:45 +01:00
unbit 36a9a96a90 Merge pull request #759 from xrmx/formatsec
Don't lower security standards with recent gcc
2014-11-05 16:47:33 +01:00
Riccardo Magliocchetti 35acf3793d Don't lower security standards with gcc 4.9
For some reason since e4d65c07ce
we started compiling -Wno-format, possibly because of plugins
dependencies not compiling.
Fedora (and Debian to some degrees) are starting to default to
-Wformat -Werror=format-security which is something sensible for
uwsgi. So let the distro handle the situation when a very recent
gcc version is encountered since they probably know better.
2014-11-05 16:23:02 +01:00
unbit 8f0b01e482 Merge pull request #761 from ykhalyavin/fix_pass_arguments
Fix invalid 'args' and 'kwargs' decoding in python3
2014-11-03 15:39:26 +01:00
Andjelko Horvat 5405e31a49 Daemon touch kill failback. 2014-11-02 20:33:41 +01:00
Unbit d0cb981cc9 fix php ZTS 2014-11-02 10:53:45 +01:00
Roberto De Ioris 48314cb903 use uwsgi_buffer for send_ack in #760 2014-11-02 09:32:50 +01:00
Roberto De Ioris 1964c9758b fixed #760 2014-11-02 06:43:17 +01:00
unbit 1123654b15 Merge pull request #765 from mbarbon/master
Fix latent refcounting error in the PSGI plugin
2014-11-02 06:09:16 +01:00
Mattia Barbon c6f6171910 Fix latent refcounting bug
It can be reproduced by enabling the Perl debugger inside a PSGI application:

    {
        package DB;

        sub DB { }
        sub sub { &$sub }
    }

    $^P = 0x73f;

    sub { [200, ['Content-Type' => 'text/plain'], ['Hello World']] }

For every request the following warnings are emitted:

    Attempt to free unreferenced scalar: SV 0xfea6e8, Perl interpreter: 0xd534a0.
    Attempt to free unreferenced scalar: SV 0xfea718, Perl interpreter: 0xd534a0.

where the unreferenced scalars are the uwsgi::input/uwsgi::error instances
created in build_psgi_env.

The calling convention for Perl subroutines is that the values pushed on the
stack must be mortalized in the callee, and if the caller wants to retain them,
it must do a SvREFCNT_inc to undo the effect of the mortalization.

Before this patch XS_input/XS_error were not mortalizing the value, and
uwsgi_perl_obj_new was not incrementing the reference count, so the two bugs
balanced each other.

When running under debugger, Perl forwards all function/method calls to
DB::sub, which causes a mortal copy of the return value of
uwsgi::input/error::new to be pushed on the stack. The value is cleared by the
FREETMPS at the end of uwsgi_perl_obj_new, and the freed value is added to the
environment hash. The warning is emitted at the end of the request when the
environment hash is freed and Perl notices that some of the values has been
already freed.
2014-11-01 21:05:54 +01:00
Mattia Barbon cdf2a24aa5 Remove unnecessary mortalization
newRV(sv_newmortal()) is equivalent to newRV_noinc(newSV(0)): the former
creates a new SV with refcount 1, schedules a decrement "soon" (the
mortalization) and increments the refcount, the net result is a refcount of 1,
which is what the latter does.
2014-11-01 20:43:37 +01:00
unbit 49415a5203 Merge pull request #764 from jonathanherbst/master
uwsgi_lock_fast_init fails on Linux 3.14 on BeagleBone Black
2014-11-01 06:16:49 +01:00
Jonathan Herbst 1c7e67f67a Fixed: uwsgi_lock_fast_init fails on Linux 3.14 on BeagleBone Black 2014-10-31 17:40:26 -04:00
unbit 614c820368 Merge pull request #763 from xrmx/configcleanup
Cleanup plugin build machinery
2014-10-31 16:08:01 +01:00
Yury Khalyavin fe68884ea4 Fix invalid 'args' and 'kwargs' decoding in python3
When we set pass_arguments=True, we should unpickle
'args' and 'kwargs' first.

Without it '_decode_from_spooler' will fail on 'decoding' their
packed by pickle data, because pickled data has 'bytes' type.
2014-10-30 18:00:56 +03:00
Riccardo Magliocchetti 5180c5c82e uwsgiconfig: cleanup plugin configuration a bit
Unify embedded and external plugins configuration so that we don't
duplicate code and bugs. While at it fix remote plugin compilation
when the repo uri ends with .git (c&p from github).

Tested compilation with plain make, external git plugin (uwsgi-realtime)
and internal plugin with --plugin switch.
2014-10-27 22:06:31 +01:00
Riccardo Magliocchetti b99ca43a12 uwsgiconfig: cleanup external plugin cflags / ldflags blacklist 2014-10-27 22:05:25 +01:00
Riccardo Magliocchetti 2e02114003 uwsgiconfig: move comment where it is supposed to be 2014-10-27 22:03:05 +01:00
Riccardo Magliocchetti 287b7a6069 uwsgiconfig: cleanup plugin cflags blacklist 2014-10-27 22:02:56 +01:00
unbit afeeecbb86 Merge pull request #758 from xrmx/ptyfix
Fixup pty plugin compilation on hurd
2014-10-27 12:11:21 +01:00
Riccardo Magliocchetti ca8ab125b4 Fixup forkpty ifdefery for dragonfly / freebsd
They are negated so we should AND them
2014-10-27 11:51:07 +01:00
Riccardo Magliocchetti afcb3e1001 Fixup pty compilation on hurd / dragonflybsd
Fix #756
2014-10-27 11:48:16 +01:00
unbit 01f0b06bbc Merge pull request #757 from didrix/master
Missing header for 'KERN_PROC_PID'
2014-10-27 06:46:21 +01:00
didrix 9b67cd4588 Remove duplicate include.
Remove duplicate include of <sys/sysctl.h>.
2014-10-26 21:35:51 +01:00
didrix 1da0bac8c8 Added missing header for 'KERN_PROC_PID'
<sys/sysctl.h> is needed for ‘KERN_PROC_PID’ on (at least) OpenBSD.
2014-10-26 20:16:04 +01:00
unbit da73d0ba6a Merge pull request #755 from aldur/manage_script_name_fix
manage_script_name fix for tricky resources
2014-10-24 17:18:43 +02:00
Unbit 8053bb4cab ABI compatibility fixes 2014-10-24 17:14:27 +02:00
Aldur c6d85b9dc2 avoid bad memory access if mountpoint_len equal to 0 2014-10-24 16:36:26 +02:00
Aldur 59da3211ab faboulous positioning of logic operators 2014-10-24 15:37:07 +02:00
Aldur f1de545623 refactor manage_script_name mountpoint selection (readability) 2014-10-24 14:53:12 +02:00
Aldur a89e8d2b53 add manage_script_name tests 2014-10-24 14:17:10 +02:00
Aldur 92153ec691 fix mountpoint / scriptname management
If the mountpoint is /foo or /foo/ then the following URIs should be managed:
* /foo
* /foo/
* /foo/anything

And, on the other side, should be ignored:
* /fooanything
* etc.
2014-10-24 14:17:02 +02:00
Unbit a976e36a7a added --hook-post-fork 2014-10-24 12:05:01 +02:00
Unbit 00e0dcaa71 ABI compatibility with 2.0 2014-10-24 12:01:31 +02:00
Unbit 5953573c3b fix ssl shutdown management 2014-10-24 11:43:18 +02:00
unbit 568348e746 Merge pull request #753 from trashnroll/feature-gridfs-bucket-option
Add gridfs bucket option.
2014-10-23 04:41:21 +02:00
trashnroll 7740edb604 Add gridfs bucket option. 2014-10-23 02:54:20 +04:00
Unbit bd07f82227 better management of rtsp requests 2014-10-21 09:01:59 +02:00
Roberto De Ioris 732ed3eb67 added automatic management of chunked input in http router 2014-10-19 12:52:11 +02:00
unbit 34b45d15cc Merge pull request #752 from comel/master
Add emperor-tyrant-initgroups option
2014-10-19 11:35:51 +02:00
Andjelko Horvat 57a51f48bf Merge remote-tracking branch 'upstream/master' 2014-10-18 21:21:31 +02:00
Andjelko Horvat 04c9439e2c emperor_tyrant_initgroups: ensure ABI compatibility. 2014-10-18 21:21:08 +02:00
Unbit 7a2d5d9661 Merge remote-tracking branch 'origin/uwsgi-2.0-cache-lazy-expire' into uwsgi-2.0 2014-10-18 04:32:05 +02:00
Unbit 04ad72ef44 fixed php SCRIPT_NAME usage when --php-app is in place 2014-10-18 04:20:21 +02:00
Andjelko Horvat ab50662658 Add emperor-tyrant-initgroups option: add additional groups set via initgroups() in Tyrant mode. 2014-10-18 00:08:08 +02:00
Unbit 19c2e22d37 allow appendn hook without second argument 2014-10-17 13:15:50 +02:00
Unbit 635b37fea4 try to load trollius on python2 2014-10-17 13:04:17 +02:00
unbit ff5a648103 Merge pull request #750 from querymetrics/carbonfix
fix heap corruption in carbon plugin
2014-10-17 05:15:59 +02:00
Nigel Heron 0aae7bdd73 fix heap corruption in carbon plugin 2014-10-16 17:31:32 -04:00
Roberto De Ioris ff36c8a779 fixed #749 2014-10-16 20:54:19 +02:00
Roberto De Ioris cc726c769f fixed #748 2014-10-16 08:25:42 +02:00
Unbit 0e8a30929e fixed #746 2014-10-15 10:07:16 +02:00
Unbit d33fa75d17 disable SSLv3 by default and allow setting raw ssl options 2014-10-15 09:02:34 +02:00
unbit 00f76aeb3f Merge pull request #740 from querymetrics/buffix
buffer over-read fix in magic_sub
2014-10-10 18:10:35 +02:00
Nigel Heron a9177d3a6b buffer over-read fix in magic_sub 2014-10-10 10:32:58 -04:00
Unbit 3d1425bf09 added define UWSGI_HAS_OFFLOAD_UBUFS 2014-10-10 10:57:55 +02:00
Unbit 9951b7536e added --wait-for-mountpoint 2014-10-07 06:52:30 +02:00
unbit e313825598 Merge pull request #736 from gdahlm/master
use _full write methods in rados plugin to truncate PUT request objects
2014-10-07 09:03:54 +02:00
Greg Dahlman 3cd3559399 use _full write methods in rados plugin to truncate PUT request objects 2014-10-06 23:32:29 -07:00
Unbit 332afafcde Merge branch 'master' of github.com:unbit/uwsgi 2014-10-06 10:35:47 +02:00
Unbit 5fe38ddda3 allows building external plugins as embedded 2014-10-06 10:35:39 +02:00
Unbit 8886336fb7 avoid edge-trigered mode when offloaded 2014-10-04 07:14:27 +02:00
Roberto De Ioris 69677193bd fixed REMOTE_ADDR in HTTP/1.1 mode 2014-10-04 12:06:16 +02:00
Roberto De Ioris 34d254fe21 added http11 protocol support 2014-10-04 11:45:29 +02:00
Roberto De Ioris 10a4aa2a76 destroy the whole instance on Emperor error 2014-10-03 10:58:19 +02:00
Roberto De Ioris e021bdf5ef exit on Emperor error 2014-10-03 10:54:35 +02:00
Unbit 8e3c127e09 attempt to fix #732 2014-10-03 05:24:16 +02:00
Unbit 73cc2f0a3a improved offload api 2014-10-01 01:35:09 +02:00
Unbit f37043679c Merge branch 'master' of ssh://github.com/unbit/uwsgi 2014-09-30 07:59:21 +02:00
Unbit b6a2d64bef expose uwsgi_parse_http_date() api function 2014-09-30 07:59:07 +02:00
Unbit 63e32f5d2b added 8 uwsgi_buffer and 8 custom fields to offload request 2014-09-30 02:45:14 +02:00
Roberto De Ioris ffeefea93b preliminary support for RTSP 2014-09-29 11:56:11 +02:00
Roberto De Ioris a27f995438 attempt to fix #729 2014-09-28 12:18:03 +02:00
unbit 386375e75e Merge pull request #727 from cxmcc/fix_message
Fix a log message.
2014-09-25 07:11:43 +02:00
Xiuming Chen c4ed2dfffe Fix a log message. 2014-09-24 13:40:21 -07:00
Unbit 794ae0018d truly fixed #726 2014-09-23 12:14:23 +02:00
Unbit 1b3a0363e0 Merge branch 'aldur-spooler-tests' 2014-09-23 12:07:38 +02:00
Unbit 9aab77bcc3 attempt to merge #726 2014-09-23 12:07:15 +02:00
Unbit d857d78048 Merge branch 'master' of github.com:unbit/uwsgi 2014-09-23 11:59:13 +02:00
Aldur 365a117aff make uwsgidecorators python3 compatibile (fix issue #676) 2014-09-23 11:46:47 +02:00
Aldur ca0ab5887e make uwsgidecorators pep8 friendly 2014-09-23 11:44:56 +02:00
Aldur ee01a0f763 add spooler_decorator tests 2014-09-23 11:44:56 +02:00
Aldur d8fb5a9a3b reorganize spooler_priority tests 2014-09-23 11:44:09 +02:00
Unbit 202dc45519 getting rid of plugins still using ->pktsize 2014-09-21 08:49:04 +02:00
Unbit 72a4a6738d support old plugins ABI 2014-09-21 08:31:33 +02:00
Unbit ed2ca5d333 request buffer_size is now 64bit (except for uwsgi protocol) 2014-09-21 08:26:20 +02:00
Unbit e2a29ee135 more robust asyncio 2014-09-20 09:07:13 +02:00
Unbit 98690c4add prototyping Zeus mode 2014-09-20 07:15:17 +02:00
Aldur 051627d9e6 Fix issue #704 2014-09-19 11:45:31 +02:00
Unbit 26c9d2c618 fixed #701 2014-09-19 11:42:43 +02:00
Roberto De Ioris 6e41b7e972 fixed useless debug 2014-09-18 16:20:23 +02:00
Roberto De Ioris 8d847a628f fixed glob support in emperor 2014-09-18 16:13:36 +02:00
unbit 1d5b1f7480 Merge pull request #724 from aldur/check_emperor_docker
fix check_emperor issue while using docker_plugin without docker_socket
2014-09-18 11:57:16 +02:00
Aldur b2d57b683a fix check_emperor issue while using docker_plugin without docker_socket 2014-09-18 11:54:26 +02:00
Roberto De Ioris 7858781012 added Adriano to CONTRIBUTORS 2014-09-18 07:18:15 +02:00
Roberto De Ioris a287d5f129 ensure ABI compatibility 2014-09-18 07:16:20 +02:00
unbit 35542f2a35 Merge pull request #723 from vine/gevent_dont_spin_on_async_exhaustion
Don't spin if we exhaust the async worker pool.
2014-09-18 07:13:22 +02:00
Mike Kaplinskiy 949d74b516 Make it compile on more stringent compilers. 2014-09-17 13:27:44 -04:00
Mike Kaplinskiy f87a719d66 Fix exhaustion code when using multiple sockets. 2014-09-17 13:06:05 -04:00
Mike Kaplinskiy 8099dbd9e2 Don't spin if we exhaust the async worker pool. 2014-09-17 13:06:05 -04:00
Unbit c4bb654455 fixed sun support in spooler 2014-09-16 18:23:11 +02:00
unbit ba608de378 Merge pull request #719 from aldur/spooler-priority-test
Improve spooler tests
2014-09-16 16:49:04 +02:00
Aldur 2e565a502e Improve spooled test 2014-09-16 16:25:35 +02:00
Unbit 83bb70dc8b fixed tcsetattr 2014-09-16 15:48:36 +02:00
Unbit 80f2e5d20f try to address kevent issue with spooler 2014-09-16 15:32:21 +02:00
unbit b1e342f19c Merge pull request #718 from aldur/master
(Feature Add) Spooler priority in NOT Linux OSs
2014-09-16 15:08:51 +02:00
Aldur 1da300a71b add test regarding spooler and related task priority 2014-09-16 15:03:48 +02:00
Aldur c8a1ba3716 Feature added: priority in not Linux OSs. 2014-09-16 15:02:52 +02:00
Unbit 1c0b996116 applied #674 2014-09-16 07:27:48 +02:00
Unbit 68bc194624 ensure PSGI response headers are in the right format [2] 2014-09-15 06:47:22 +02:00
Unbit 5bc5b7e01f ensure PSGI response headers are in the right format 2014-09-15 06:38:59 +02:00
Unbit 5937678613 fixed socketname detection 2014-09-15 06:31:22 +02:00
Unbit d6d52cde1a fixed emperor proxy [2] 2014-09-15 06:17:46 +02:00
Unbit 930e5f97ef fixed emperor proxy 2014-09-15 06:16:13 +02:00
Unbit 4eef332850 allow passing a socket via emperor proxy 2014-09-15 06:04:22 +02:00
Unbit f4d04b2777 allow passing a socket via emperor proxy 2014-09-15 05:48:28 +02:00
Unbit 293464f54e revert emperor check for fd0 2014-09-15 05:23:16 +02:00
Unbit 697dd95337 added vassal_attr_get_multi 2014-09-14 12:07:30 +02:00
Unbit b1a40107d3 added config pipe support for dir imperial monitor 2014-09-13 16:50:31 +02:00
unbit d37a1d3615 Merge pull request #698 from xrmx/debarchs
Fix forkptyrouter plugin compilation on Hurd
2014-09-12 10:14:02 +02:00
Roberto De Ioris 0b9393a93e fixed uwsgi.h garbage after merge 2014-09-12 06:51:56 +02:00
Roberto De Ioris 50e7b84fb5 uwsgi-2.1 merged to master 2014-09-12 06:47:41 +02:00
Unbit d9bdb8e093 attempt to fix #713 2014-09-11 08:20:36 +02:00
Unbit 32db48410b report chdir() 2014-09-10 07:44:58 +02:00
Unbit c26b065a85 attempt to fix #611 2014-09-09 07:49:35 +02:00
Unbit 03467ece6c automatically manage HTTP_X_FORWARDED_PROTO 2014-09-05 17:36:49 +02:00
Unbit a70c35e4b6 fixed #702 2014-08-31 21:09:30 +02:00
Roberto De Ioris 7888036155 fix for #703, waiting for confirmation 2014-08-30 08:36:23 +02:00
Unbit 18ca48dd63 new broodlord modes 2014-08-29 07:58:11 +02:00
Unbit 9a56d5c7bc fixed vassal_before_exec 2014-08-28 18:58:54 +02:00
Unbit 5d5c0edb25 exposed vassal_attr_get() 2014-08-28 18:44:50 +02:00
Unbit 11d8968e35 UWSGI_PLUGIN_API is 2 2014-08-28 18:11:15 +02:00
Unbit b48ea217c8 fixed stats vacuum 2014-08-26 09:44:22 +02:00
Unbit f762001b73 fixed #644 2014-08-26 07:42:03 +02:00
Unbit fce15b7ab5 fixed #693 2014-08-26 07:25:25 +02:00
Unbit 59a999af7b fix multiple python mountpoints with multiple threads in cow mode 2014-08-26 07:11:21 +02:00
Riccardo Magliocchetti e04e19aca4 Fix forkptyrouter plugin compilation on Hurd
While at it add missing linkage to libutil on other platforms
and fix compilation on DragonFlyBSD

Possibly Fix #694
2014-08-20 16:35:29 +02:00
Unbit 92bd4122cc added Mike Kaplinskiy to CONTRIBUTORS 2014-08-17 19:29:01 +02:00
unbit c08d030ece Merge pull request #690 from vine/async_1_2.1
Allow --async 1 (i.e. sync mode, but with a different loop engine)
2014-08-17 19:28:09 +02:00
Mike Kaplinskiy 1a4f333912 Allow --async 1 (i.e. sync mode, but with a different loop engine) 2014-08-17 13:13:17 -04:00
unbit f1cdf2890f Merge pull request #689 from xrmx/rcpclean21
2.1: Rpc coverity fixes and plugin cleanup
2014-08-16 22:28:49 +02:00
Riccardo Magliocchetti 89bdb35ebc plugins/rpc: cleanup duplicated code
Introduce a couple of helpers to reduce duplicated code.

Before:
   text	   data	    bss	    dec	    hex	filename
   9742	    180	      0	   9922	   26c2	plugins/rpc/rpc_plugin.o

After:
   text	   data	    bss	    dec	    hex	filename
   9230	    180	      0	   9410	   24c2	plugins/rpc/rpc_plugin.o

My compiler inlines so uwsgi_rpc_get_remote it does make difference
in practice still it makes the code prettier.
2014-08-16 18:54:04 +02:00
Riccardo Magliocchetti b94727ef26 plugins/rpc: fix a couple of memory leaks
Always free response, in the worst case we are freeing NULL which
is a NOP.
Reported by Coverity as CID #1231246, #1231245
2014-08-16 18:53:42 +02:00
Riccardo Magliocchetti b6b943038a core/rpc: avoid double close
Reported by coverity as CID #1231253
2014-08-16 18:53:35 +02:00
Roberto De Ioris 9e934153a0 attempt to fix solaris/smartos events with emperor 2014-08-16 16:24:56 +02:00
Roberto De Ioris 8da55942ca fixed fastcgi and scgi protocols with out of buffer 2014-08-15 19:07:02 +02:00
Roberto De Ioris 69034d2774 fixed mono on osx 2014-08-15 06:06:36 +02:00
Unbit 9537a45358 fixed #683 2014-08-12 13:12:03 +02:00
Unbit c6d90f3c42 fixed #669 2014-08-12 13:11:54 +02:00
Unbit fc6f125d17 added hook_as_emperor_setns 2014-08-11 10:14:49 +02:00
Unbit 33f463284c skel for uwsgi_hooks_setns_run 2014-08-11 09:13:16 +02:00
Unbit 532bee6916 added wait_for_fs infrastructure 2014-08-11 08:05:05 +02:00
Unbit cb302fc05d added --hook-as-emperor-before-vassal and --hook-as-vassal-before-drop 2014-08-11 07:38:04 +02:00
Unbit 2210f907db fixed uwsgi.rpc 2014-08-08 22:14:46 +02:00
Unbit 522fb09b68 added fastrouter-force-key 2014-08-08 21:32:24 +02:00
Unbit eeef5b10c9 attempt to ignore user namespace in setns 2014-08-08 13:22:18 +02:00
Roberto De Ioris 3a0f83c0d0 fixed #666 2014-08-05 20:13:15 +02:00
Riccardo Magliocchetti 6f5bd07fc4 Merge pull request #678 from xrmx/uwsgi-2.1
Update Riccardo's entry in CONTRIBUTORS
2014-08-01 16:25:43 +02:00
Riccardo Magliocchetti 62d72f3213 Update Riccardo's entry in CONTRIBUTORS 2014-08-01 16:22:31 +02:00
Unbit e315c604fe allow calling the spooler from every cpython context 2014-08-01 12:43:42 +02:00
Unbit 7a7391a6c6 attempt to fix #667 2014-07-24 09:09:37 +02:00
Unbit d6f0be74f9 fixed #668 2014-07-24 08:56:43 +02:00
Unbit d04f15285a added fallback for mountpoint mode 2014-07-12 11:19:30 +02:00
Unbit 50f41da7ec added support for mountpoints in subscription system 2014-07-12 11:05:14 +02:00
Unbit 6cf62fb0d2 added iphash subscription algo 2014-07-12 10:12:17 +02:00
Unbit eb4ee8226a added backup_level to lrc algos 2014-07-12 09:20:10 +02:00
Unbit baec7aadc5 added backup support to wrr algo 2014-07-12 09:12:54 +02:00
Unbit d121b23fd4 fixed per-subscription protocol support 2014-07-12 08:48:29 +02:00
Unbit ddc737627e refactored httprouter parser to be in 2 steps 2014-07-12 08:04:01 +02:00
Unbit 736be4b3c5 report the used algo in realtime 2014-07-11 12:04:51 +02:00
Unbit 90b6512d52 pluggable subscription algos 2014-07-11 11:46:23 +02:00
Unbit df43bd6e9d preliminary support for backup,algo and proto subscription keys 2014-07-11 09:40:24 +02:00
Unbit 2add2aab04 fixed #661 2014-07-11 08:58:08 +02:00
Unbit c6eaa18efe added patch by Mathieu Dupuy for uwsgi_str_contains and uwsgi_startswith (#661) 2014-07-11 08:53:00 +02:00
Unbit 9c23e1ac97 added Mathieu Dupuy to CONTRIBUTORS 2014-07-11 08:48:02 +02:00
Unbit 987da3ecdd added note about uwsgi_calloc_shared, as noted in #661 2014-07-11 08:47:20 +02:00
Unbit 540a3dbf33 first round from ticket #661 2014-07-11 08:42:18 +02:00
Joshua C. Forest fecb1af811 send data as a counter, m has no meaning in statsd 2014-07-09 08:33:14 +02:00
Roberto De Ioris 60eae2d69f added if-hostname 2014-07-01 06:58:30 +02:00
Unbit 9146055a3c fixed wrongly nulled filename in rados 2014-06-30 11:58:09 +02:00
Unbit 7f15c9df33 mapping GET to PROPFIND is stupid in rados 2014-06-28 10:05:44 +02:00
Unbit 5f24912c94 fixed webdav xml 2014-06-28 09:51:45 +02:00
Unbit 37ccff581d completed virtual propfind support in rados 2014-06-28 09:40:05 +02:00
Unbit f8685eee3e added xml buffer escaper 2014-06-28 08:35:15 +02:00
Roberto De Ioris 913384131c improved buffer json escaping 2014-06-28 08:14:47 +02:00
Unbit 31c5412405 first commit for webdav support 2014-06-28 08:14:20 +02:00
Unbit f879d32408 implemented OPTIONS in rados 2014-06-28 07:32:16 +02:00
Unbit 70eeaec0c0 added mkcol to rados 2014-06-28 07:32:02 +02:00
Unbit 5ddf69ab33 added uwsgi[rsize] routing var 2014-06-28 07:31:52 +02:00
Unbit 221e62f4ea the Rados plugin is no more based on the GlusterFS one 2014-06-28 07:31:41 +02:00
Unbit 9ed5a65ef9 fixed sync rados behaviour 2014-06-28 07:31:26 +02:00
Unbit ae87d0850d first attempt in improving rados multithreading 2014-06-28 07:30:53 +02:00
Unbit 7ff6a239e2 improved timeout 2014-06-28 07:30:40 +02:00
Unbit f84b67c51c implemented PUT and DELETE methods for rados 2014-06-28 07:30:27 +02:00
Unbit aeeea6915a fixed rados async support 2014-06-28 07:30:14 +02:00
Unbit 4c015a30f8 try to fix SCRIPT_NAME and PATH_TRANSLATED in php plugin 2014-06-28 07:29:59 +02:00
Unbit fbe5a038e3 added early-pythonpath support 2014-06-25 10:02:46 +02:00
Unbit c7bacc6fbe first round for implementing cpython fork-server 2014-06-25 09:51:52 +02:00
Marko Tiikkaja c9771d091a Remove the old FIFO socket from the event queue when recreating it
The previous code had two problems:
  1) It never removed the old fd from the event loop, which meant that
if the new fd received a different index, the old fd would keeping
waking up the master process repeatedly.
  2) If the new fd got the same index but the master loop went back to
epoll_wait() fast enough, Linux would claim that the socket is ready for
reading, but read() would return 0 again, which would cause the FIFO to
be recreated again, etc.

Fix by removing the old fd from the event queue before recreating it.
2014-06-25 09:10:13 +02:00
Unbit c532210d79 added fastrouter-fallback-on-no-key 2014-06-24 09:48:27 +02:00
Unbit 5fb86e92f8 better harakiri announce 2014-06-23 13:48:14 +02:00
Unbit daa1882921 improved harakiri for signal handlers 2014-06-23 13:42:55 +02:00
Unbit 17ec600146 implemented total harakiri 2014-06-23 12:39:58 +02:00
Unbit 2e14da983a first attempt in implementing per-core harakiri 2014-06-23 12:37:22 +02:00
Unbit 782171866a added fork-server support for php 2014-06-19 13:43:01 +02:00
Unbit 848cfb4fbb added support for unix socket in apache mod_proxy_uwsgi 2014-06-19 05:55:35 +02:00
Unbit 1f28940c08 another attempt at fixing mod_proxy_uwsgi for apache2.2/2.4 2014-06-19 04:38:33 +02:00
Unbit 90b07a2f83 fixed #648 2014-06-17 17:14:32 +02:00
Unbit 2e9cfabf7b added callint scheme 2014-06-12 11:26:25 +02:00
Unbit ef0a404364 another attempt in improving chain reloading 2014-06-11 18:33:21 +02:00
Unbit 8ba4c80ee0 fixed SSL build 2014-06-11 11:32:20 +02:00
Unbit 792231d7d8 fixed #649 2014-06-11 11:31:11 +02:00
Unbit 7361796d3c fixed shortcut for ssl-socket 2014-06-08 06:35:44 +02:00
Unbit 2e13abc774 allow hacking the php sapi name 2014-06-08 06:21:52 +02:00
Unbit 8721af946c added chdir to attach-daemon2 2014-06-06 15:06:25 +02:00
Roberto De Ioris 1986f2ddd9 added support for http backend nodes in httprouter 2014-06-06 06:00:20 +02:00
Roberto De Ioris 9b35215edc fixed a memory leak with subscriptions 2014-06-06 04:21:11 +02:00
Roberto De Ioris 31112919cd Merge branch 'uwsgi-2.1' of github.com:unbit/uwsgi into uwsgi-2.1 2014-06-05 06:40:27 +02:00
Unbit c6f3fc8620 fixed #645 2014-06-05 06:40:04 +02:00
Unbit 6213d4d6fc another attempt for #645 2014-06-05 06:39:54 +02:00
Unbit 69fba94647 attempt to fix #645 2014-06-05 06:39:35 +02:00
Roberto De Ioris 22245055ef fixed #642 2014-06-02 06:54:56 +02:00
Roberto De Ioris 7fa0955083 fixed http-manage-source type 2014-06-01 06:48:03 +02:00
Roberto De Ioris 6a390e2d17 fixed #641 2014-05-31 07:44:33 +02:00
Roberto De Ioris 3ea2033f57 merged intellisurvey branch in 2.1 2014-05-31 06:51:13 +02:00
Roberto De Ioris 3a6887082e implemented UWSGI_HOOK_CONTEXT 2014-05-30 06:50:00 +02:00
Roberto De Ioris 6179f889e9 implementation of emperor attributes for .ini files 2014-05-30 06:43:15 +02:00
unbit b6495c4fdc Merge pull request #639 from xtfxme/as-cpyext-intellisurvey
Support building as a proper [C]Python extension, and/or by distutils [intellisurvey]
2014-05-29 07:55:06 +02:00
C Anthony Risinger 5a17557954 Support alternate build as proper CPython extension, and/or by distutils
uWSGI will instruct setuptools to generate a console_scripts entry_point as
bin/uwsgi, and will in general behave more like a normal extension.
Also exports uwsgi.ORIG_ARGV and uwsgi.NEW_ARGV... ex. usage:

    # python -i -c \
        'import uwsgi as u; u.setup().worker_id()==1 or u.run()' \
        --master --workers=1 --enable-threads --honour-stdin \
        --auto-procname --http :8000

Relies on new_argc/new_argv support in 2.1
2014-05-28 13:17:20 -05:00
C Anthony Risinger c5e1ead065 add alternate setup.py impl 2014-05-28 13:17:12 -05:00
C Anthony Risinger 65d25a0fc2 add build products to .gitignore 2014-05-28 12:51:58 -05:00
Roberto De Ioris 8d3e6cd3f3 added fix for older linux systems 2014-05-28 06:55:53 +02:00
Roberto De Ioris 657bc57885 added emperor-subreaper option and hook-as-on-demand-vassal 2014-05-28 06:45:30 +02:00
Unbit 7b1138e5ef added perl low-level hook 2014-05-26 14:59:33 +02:00
Unbit 567395f6c4 ready for fork-server heavy tests 2014-05-16 09:58:50 +02:00
Unbit ec28cca229 completed support for attributes in mongodb imperial monitor 2014-05-16 07:13:48 +02:00
Unbit 1cf169ebe0 implemented fork-server and wrapper vassal's attributes 2014-05-16 05:50:23 +02:00
Unbit 4d6daded29 implemented attributes in mongodb imperial monitor 2014-05-16 05:35:15 +02:00
Unbit ef8d9d6145 added api for emperor attributes 2014-05-16 05:27:52 +02:00
Unbit e61c2699f6 generic vassal's attributes logic 2014-05-16 05:11:04 +02:00
Unbit f56f16788b prepare for vassal's attributes 2014-05-14 18:39:10 +02:00
Unbit cb110260c3 inform user about UWSGI_GO_CHEAP_CODE 2014-05-14 16:38:44 +02:00
Unbit 1bb0f8fcb8 inform user about UWSGI_GO_CHEAP 2014-05-14 16:38:33 +02:00
Unbit 34349c39fe added UWSGI_GO_CHEAP 2014-05-14 16:38:22 +02:00
Unbit 154d17ec2b correctly manage 64bit sharedarea numbers on 32bit systems 2014-05-14 16:38:11 +02:00
Unbit 0dffa344b4 various sharedarea improvements 2014-05-14 16:37:59 +02:00
Unbit 7681a40d88 fixed #622 2014-05-13 19:37:56 +02:00
Unbit 47d00e2d11 Merge branch 'intellisurvey' of ssh://github.com/unbit/uwsgi into intellisurvey 2014-05-13 13:28:01 +02:00
Unbit cfbb213e6d fixed #623 2014-05-13 13:26:33 +02:00
Unbit 5871146519 ensure SIGPIPE is ignored in gevent mode 2014-05-13 12:52:00 +02:00
Roberto De Ioris f7fa4f760a added anot for TODO impkementations in the fork server 2014-05-12 03:13:21 +02:00
Roberto De Ioris 9e618ee105 implemented (early) shared per interpreter 2014-05-12 03:05:33 +02:00
Roberto De Ioris 9e7ba11228 avoid registering rpc functions too early 2014-05-12 02:38:36 +02:00
Roberto De Ioris c94aa42a02 added support for emperor protocol in the fork server 2014-05-12 02:33:41 +02:00
Unbit c01d6242ad ansure stdc++ is linked for emperor_mongodb 2014-05-08 09:10:31 +02:00
Unbit eac016a416 force processname in fork-server mode 2014-05-08 09:06:30 +02:00
Roberto De Ioris 5ffd5f9bb9 preapre for psgi early-exec 2014-05-08 07:26:31 +02:00
Roberto De Ioris 7c1bd05dd2 fixed #620 2014-05-08 07:02:37 +02:00
Unbit 066ef55766 allow variables in uwsgi router 2014-05-08 07:02:32 +02:00
Unbit e43a8fe8c5 improved icecast2 management 2014-05-08 07:02:27 +02:00
Unbit a7297782ab implement a form of virtualhosting for http/1.0 icecast2 source requests 2014-05-08 07:02:23 +02:00
Unbit 3a1c5b4ad5 another refactor for on_demand socket management 2014-05-07 06:22:41 +02:00
Unbit 50cbb016b5 refactored push pipe config 2014-05-07 06:17:05 +02:00
Unbit d3de54ac3f correctly set pipes to -1 in emperor mode 2 2014-05-07 06:12:58 +02:00
Unbit da335692a0 ported SOURCE management from 2.0.5 2014-05-07 06:08:49 +02:00
Unbit cf8580775a exit_on_reload on by default in fork-server mode 2014-05-06 18:32:01 +02:00
Unbit 472ac2dd9d fixed double-free 2014-05-06 18:28:40 +02:00
Unbit 246e106d85 added support for on_demand and config pipe in fork-server mode 2014-05-06 17:57:37 +02:00
Unbit e983fae9a4 it looks like SUBREAPER works great 2014-05-06 17:46:44 +02:00
Unbit 1219f6fc30 added adopted-vassals concept 2014-05-06 17:28:39 +02:00
Unbit 338700e950 completed prototype for Emperor fork-client 2014-05-06 14:22:02 +02:00
Unbit c63bb224fb reindented emperor 2014-05-06 14:06:06 +02:00
Unbit 119889584a fork server (step3) 2014-05-06 13:59:23 +02:00
Unbit 7ff5083e09 fork server (step2) 2014-05-06 12:43:50 +02:00
Unbit 8b8e3dbd89 fork server (step1) 2014-05-06 12:17:51 +02:00
Unbit f2bd61991f try with a frequency of 1 seconds for vassals fast restart 2014-05-06 07:51:14 +02:00
Unbit 6102a3add5 Merge branch 'master' of ssh://github.com/unbit/uwsgi into intellisurvey 2014-05-05 18:21:30 +02:00
Unbit ad37f66b51 Merge branch 'master' of ssh://github.com/unbit/uwsgi into intellisurvey 2014-05-05 17:42:36 +02:00
Unbit fe82772c37 add some comment to the fork server system 2014-05-05 16:30:13 +02:00
Unbit 9d98b3b4ef better to mark it as 2.1, we can merge to master later 2014-05-05 15:58:36 +02:00
Unbit 9a70753680 merged with master 2014-05-05 12:19:04 +02:00
Unbit be2dea3c51 preparing for fork server connection 2014-05-03 12:53:04 +02:00
Unbit fa269b8838 start investigating argc/argv implications 2014-05-03 11:44:24 +02:00
Unbit 8b8b57769e first prototype of a fork server 2014-05-03 10:17:27 +02:00
368 changed files with 10920 additions and 3493 deletions
+4
View File
@@ -22,3 +22,7 @@ core/dot_h.c
+# coverity
+/cov-int/
+uwsgi.tar.xz
/build/
/dist/
/uWSGI.egg-info/
+4 -5
View File
@@ -13,15 +13,15 @@ script:
- echo -e "\n\n>>> Building python27 plugin"
- /usr/bin/python2.7 -V
- /usr/bin/python2.7 uwsgiconfig.py --plugin plugins/python base python27
- echo -e "\n\n>>> Building python31 plugin"
- /usr/bin/python3.1 -V
- /usr/bin/python3.1 uwsgiconfig.py --plugin plugins/python base python31
- echo -e "\n\n>>> Building python32 plugin"
- /usr/bin/python3.2 -V
- /usr/bin/python3.2 uwsgiconfig.py --plugin plugins/python base python32
- echo -e "\n\n>>> Building python33 plugin"
- /usr/bin/python3.3 -V
- /usr/bin/python3.3 uwsgiconfig.py --plugin plugins/python base python33
- echo -e "\n\n>>> Building python34 plugin"
- /usr/bin/python3.4 -V
- /usr/bin/python3.4 uwsgiconfig.py --plugin plugins/python base python34
- echo -e "\n\n>>> Building rack 1.8.7 plugin"
- /usr/bin/ruby1.8 -v
- UWSGICONFIG_RUBYPATH=/usr/bin/ruby1.8 /usr/bin/python uwsgiconfig.py --plugin plugins/rack base rack187
@@ -36,9 +36,8 @@ script:
- ./tests/travis.sh
before_install:
- sudo add-apt-repository -y ppa:fkrull/deadsnakes
- sudo apt-get update -qq
- sudo apt-get install -qqyf python2.6-dev python2.7-dev python3.1-dev python3.2-dev python3.3-dev rubygems1.8 ruby1.8-dev ruby1.9.1-dev
- sudo apt-get install -qqyf rubygems1.8 ruby1.8-dev ruby1.9.1-dev
- sudo apt-get install -qqyf libxml2-dev libpcre3-dev libcap2-dev
- sudo apt-get install -qqyf curl
+4
View File
@@ -29,4 +29,8 @@ Danila Shtan <danila@shtan.ru>
Ævar Arnfjörð Bjarmason
Yu Zhao (getcwd)
Mathieu Dupuy
Mike Kaplinskiy
Adriano Di Luzio (adriano@unbit.it)
James Raspass
Curtis Maloney
Vladimir Didenko
+14 -4
View File
@@ -365,12 +365,13 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
ap_set_content_type(r, apr_pstrdup(r->pool, buf));
}
for(;;) {
int finish = 0;
while(!finish) {
rv = ap_get_brigade(rp->input_filters, bb,
AP_MODE_READBYTES, mode,
conf->io_buffer_size);
if (mode == APR_NONBLOCK_READ && (APR_STATUS_IS_EAGAIN(rv)
|| (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)))) {
if (APR_STATUS_IS_EAGAIN(rv)
|| (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) ) {
e = apr_bucket_flush_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
if (ap_pass_brigade(r->output_filters, bb) || c->aborted) {
@@ -401,7 +402,16 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
ap_proxy_buckets_lifetime_transform(r, bb, pass_bb);
ap_pass_brigade(r->output_filters, pass_bb);
// found the last brigade?
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) finish = 1;
// do not pass chunk if it is zero_sized
apr_brigade_length(pass_bb, 0, &readbytes);
if ((readbytes > 0 && ap_pass_brigade(r->output_filters, pass_bb) != APR_SUCCESS) || c->aborted) {
finish = 1;
}
apr_brigade_cleanup(bb);
apr_brigade_cleanup(pass_bb);
}
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados,pypy,zabbix,curl_cron,tornado,tuntap,pty,mongrel2,alarm_curl,router_radius,airbrake
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados,pypy,zabbix,curl_cron,tornado,tuntap,pty,mongrel2,alarm_curl,router_radius,airbrake,gridfs
inherit = base
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
main_plugin = psgi,rack,lua,python,gevent,php,cgi,glusterfs,pty,xslt,msgpack,geoip,v8,pam,ldap,mono,jvm,ring,jwsgi,servlet,rados,coroae,pypy,gccgo
main_plugin = psgi,rack,lua,python,gevent,php,cgi,gccgo,glusterfs,pty,xslt,msgpack,geoip,v8,pam,ldap,mono,jvm,ring,jwsgi,servlet,rados,coroae,pypy,airbrake,alarm_curl,alarm_xmpp,asyncio,cheaper_backlog2,clock_monotonic,clock_realtime,cplusplus,curl_cron,dumbloop,dummy,echo,emperor_amqp,emperor_pg,emperor_zeromq,example,exception_log,fiber,forkptyrouter,graylog2,legion_cache_fetch,libffi,logcrypto,libtcc,logpipe,logzmq,matheval,notfound,pyuwsgi,rbthreads,router_access,router_radius,router_spnego,router_xmldir,sqlite3,ssi,stats_pusher_file,stats_pusher_statsd,systemd_logger,tornado,transformation_toupper,tuntap,webdav,xattr,zabbix
inherit = base
+1
View File
@@ -15,6 +15,7 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
CARBON_SERVER = "127.0.0.1:2003"
def update_carbon(signum):
# connect to the carbon server
carbon_fd = uwsgi.connect(CARBON_SERVER)
+7 -4
View File
@@ -12,13 +12,15 @@ import greenlet
uwsgi_pypy_greenlets = {}
def uwsgi_pypy_greenlet_wrapper():
lib.async_schedule_to_req_green()
@ffi.callback("void()")
def uwsgi_pypy_greenlet_schedule():
id = lib.uwsgi.wsgi_req.async_id
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1
# generate a new greenlet
if not lib.uwsgi.wsgi_req.suspended:
@@ -36,10 +38,11 @@ def uwsgi_pypy_greenlet_schedule():
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(ffi.NULL)
@ffi.callback("void(struct wsgi_request *)")
def uwsgi_pypy_greenlet_switch(wsgi_req):
id = wsgi_req.async_id
modifier1 = wsgi_req.uh.modifier1;
wsgi_req.async_id
modifier1 = wsgi_req.uh.modifier1
# this is called in the current greenlet
if lib.uwsgi.p[modifier1].suspend:
@@ -54,7 +57,7 @@ def uwsgi_pypy_greenlet_switch(wsgi_req):
# update current running greenlet
lib.uwsgi.wsgi_req = wsgi_req
if lib.uwsgi.async <= 1:
if lib.uwsgi.async < 1:
raise Exception("pypy greenlets require async mode !!!")
lib.uwsgi.schedule_to_main = uwsgi_pypy_greenlet_switch
lib.uwsgi.schedule_to_req = uwsgi_pypy_greenlet_schedule
+1 -1
View File
@@ -11,7 +11,7 @@ uwsgi_args = []
for arg in sys.argv[2:]:
uwsgi_args.append(arg)
#pyuwsgi.run('welcome.ini')
# pyuwsgi.run('welcome.ini')
pyuwsgi.run(uwsgi_args)
# if you are here uWSGI has been reloaded
+5 -4
View File
@@ -4,6 +4,7 @@ from django.conf import settings
import os
import sys
class Command(BaseCommand):
help = "Runs this project as a uWSGI application. Requires the uwsgi binary in system path."
@@ -12,10 +13,10 @@ class Command(BaseCommand):
def handle(self, *args, **options):
for arg in args:
k,v = arg.split('=')
k, v = arg.split('=')
if k == 'http':
if self.http_port:
self.http_port = v
self.http_port = v
elif k == 'socket':
self.http_port = None
self.socket_addr = v
@@ -40,8 +41,8 @@ class Command(BaseCommand):
elif self.socket_addr:
os.environ['UWSGI_SOCKET'] = self.socket_addr
# map admin static files
os.environ['UWSGI_STATIC_MAP'] = '%s=%s' % (settings.ADMIN_MEDIA_PREFIX, os.path.join(django.__path__[0], 'contrib', 'admin', 'media'))
# map admin static files
os.environ['UWSGI_STATIC_MAP'] = '%s=%s' % (settings.ADMIN_MEDIA_PREFIX, os.path.join(django.__path__[0], 'contrib', 'admin', 'media'))
# remove sockets/pidfile at exit
os.environ['UWSGI_VACUUM'] = '1'
# retrieve/set the PythonHome
+2 -3
View File
@@ -1,11 +1,10 @@
from tasksconsumer import enqueue
def application(env, sr):
sr('200 OK', [('Content-Type','text/html')])
sr('200 OK', [('Content-Type', 'text/html')])
enqueue(queue='fast', pippo='pluto')
return "Task enqueued"
+3 -1
View File
@@ -1,9 +1,11 @@
from tasksconsumer import *
from tasksconsumer import queueconsumer
@queueconsumer('fast', 4)
def fast_queue(arguments):
print "fast", arguments
@queueconsumer('slow')
def slow_queue(arguments):
print "foobar", arguments
+15 -14
View File
@@ -1,35 +1,36 @@
from uwsgidecorators import *
from uwsgidecorators import spool
import Queue
from threading import Thread
queues = {}
class queueconsumer(object):
def __init__(self, name, num=1, **kwargs):
self.name = name
self.num = num
self.num = num
self.queue = Queue.Queue()
self.threads = []
self.func = None
queues[self.name] = self
self.threads = []
self.func = None
queues[self.name] = self
@staticmethod
def consumer(self):
while True:
req = self.queue.get()
req = self.queue.get()
print req
self.func(req)
self.queue.task_done()
self.func(req)
self.queue.task_done()
def __call__(self, f):
self.func = f
for i in range(self.num):
t = Thread(target=self.consumer,args=(self,))
self.threads.append(t)
t.daemon = True
t.start()
for i in range(self.num):
t = Thread(target=self.consumer, args=(self,))
self.threads.append(t)
t.daemon = True
t.start()
@spool
def spooler_enqueuer(arguments):
+51 -52
View File
@@ -1,22 +1,22 @@
from twisted.internet import defer, protocol, reactor
from twisted.protocols import basic
from twisted.web2 import server, http, resource, responsecode, stream, channel
from twisted.application import service, strports
from twisted.web2 import http, resource, responsecode, stream
import struct
class uWSGIClientResource(resource.LeafResource):
def __init__(self,app='', port=3030, host='localhost'):
def __init__(self, app='', port=3030, host='localhost'):
resource.LeafResource.__init__(self)
self.host = host
self.port = port
self.app = app
self.app = app
def renderHTTP(self, request):
return uWSGI(request, self.app, self.host, self.port)
def uWSGI(request, app, host, port):
if request.stream.length is None:
return http.Response(responsecode.LENGTH_REQUIRED)
@@ -25,60 +25,59 @@ def uWSGI(request, app, host, port):
factory = uWSGIClientProtocolFactory(request)
reactor.connectTCP(host, port, factory)
return factory.deferred
class uWSGIClientProtocol(basic.LineReceiver):
def __init__(self, request, deferred):
self.request = request
self.deferred = deferred
self.stream = stream.ProducerStream()
self.response = http.Response(stream=self.stream)
self.status_parsed = None
self.status_parsed = None
def build_uwsgi_var(self,key,value):
return struct.pack('<H',len(key)) + key + struct.pack('<H',len(value)) + value
def build_uwsgi_var(self, key, value):
return struct.pack('<H', len(key)) + key + struct.pack('<H', len(value)) + value
def connectionMade(self):
print self.request.__dict__
# reset response parser
self.status_parsed = None
# build header and vars
vars = ''
print(self.request.__dict__)
# reset response parser
self.status_parsed = None
# build header and vars
vars = ''
if self.request.stream.length:
vars += self.build_uwsgi_var('CONTENT_LENGTH',str(self.request.stream.length))
if self.request.stream.length:
vars += self.build_uwsgi_var('CONTENT_LENGTH', str(self.request.stream.length))
for hkey, hval in self.request.headers.getAllRawHeaders():
# use a list, probably it will be extended
if hkey.lower() not in ('content-type'):
vars += self.build_uwsgi_var('HTTP_'+hkey.upper().replace('-','_'),','.join(hval))
else:
vars += self.build_uwsgi_var(hkey.upper().replace('-','_'),','.join(hval))
for hkey, hval in self.request.headers.getAllRawHeaders():
# use a list, probably it will be extended
if hkey.lower() not in ('content-type'):
vars += self.build_uwsgi_var('HTTP_' + hkey.upper().replace('-', '_'), ','.join(hval))
else:
vars += self.build_uwsgi_var(hkey.upper().replace('-', '_'), ','.join(hval))
vars += self.build_uwsgi_var('REQUEST_METHOD', self.request.method)
vars += self.build_uwsgi_var('SCRIPT_NAME', self.request.uwsgi_app)
vars += self.build_uwsgi_var('PATH_INFO', self.request.path[len(self.request.uwsgi_app):])
vars += self.build_uwsgi_var('QUERY_STRING', self.request.querystring)
vars += self.build_uwsgi_var('SERVER_NAME', self.request.host)
vars += self.build_uwsgi_var('SERVER_PORT', str(self.request.port))
vars += self.build_uwsgi_var('SERVER_PROTOCOL', self.request.scheme.upper()+'/'+str(self.request.clientproto[0]) +'.'+str(self.request.clientproto[1]))
vars += self.build_uwsgi_var('REQUEST_METHOD', self.request.method)
vars += self.build_uwsgi_var('SCRIPT_NAME', self.request.uwsgi_app)
vars += self.build_uwsgi_var('PATH_INFO', self.request.path[len(self.request.uwsgi_app):])
vars += self.build_uwsgi_var('QUERY_STRING', self.request.querystring)
vars += self.build_uwsgi_var('SERVER_NAME', self.request.host)
vars += self.build_uwsgi_var('SERVER_PORT', str(self.request.port))
vars += self.build_uwsgi_var('SERVER_PROTOCOL', self.request.scheme.upper() + '/' + str(self.request.clientproto[0]) + '.' + str(self.request.clientproto[1]))
vars += self.build_uwsgi_var('REQUEST_URI', self.request.uri)
vars += self.build_uwsgi_var('REMOTE_ADDR', self.request.remoteAddr.host)
vars += self.build_uwsgi_var('REQUEST_URI', self.request.uri)
vars += self.build_uwsgi_var('REMOTE_ADDR', self.request.remoteAddr.host)
self.transport.write(struct.pack('<BHB', 0, len(vars), 0))
self.transport.write(vars)
self.transport.write(struct.pack('<BHB',0, len(vars),0))
self.transport.write(vars)
# send request data
# send request data
stream.StreamProducer(self.request.stream).beginProducing(self.transport)
def lineReceived(self, line):
if self.status_parsed is None:
self.response.code = line.split(' ',2)[1]
self.status_parsed = True
return
if self.status_parsed is None:
self.response.code = line.split(' ', 2)[1]
self.status_parsed = True
return
# end of headers
if line == '':
@@ -87,33 +86,33 @@ class uWSGIClientProtocol(basic.LineReceiver):
self.response = None
return
name, value = line.split(':',1)
name, value = line.split(':', 1)
value = value.strip()
self.response.headers.addRawHeader(name, value)
def rawDataReceived(self, data):
self.stream.write(data)
def connectionLost(self, reason):
self.stream.finish()
class uWSGIClientProtocolFactory(protocol.ClientFactory):
protocol = uWSGIClientProtocol
noisy = False # Make Factory shut up
noisy = False # Make Factory shut up
def __init__(self, request):
self.request = request
self.deferred = defer.Deferred()
def buildProtocol(self, addr):
return self.protocol(self.request, self.deferred)
def clientConnectionFailed(self, connector, reason):
self.sendFailureResponse(reason)
def sendFailureResponse(self, reason):
response = http.Response(code=responsecode.BAD_GATEWAY, stream=str(reason.value))
self.deferred.callback(response)
+48 -26
View File
@@ -6,6 +6,7 @@ import time
import sys
from optparse import OptionParser
class Cache:
def __init__(self, filename, cache_slots, block_size=65536, sample_sleep=1):
@@ -41,7 +42,7 @@ class Cache:
fields = struct.unpack_from('@HHIQQQQQ2048c', buf)
key = array.array('c', fields[8:self.key_size+8]).tostring().rstrip('\x00')
if [x for x in key if x!= '\x00']:
if [x for x in key if x != '\x00']:
buf = self.store_read_item_block(position)
value = array.array('c', buf).tostring().rstrip('\x00')
else:
@@ -55,7 +56,7 @@ class Cache:
if self.sample_sleep:
time.sleep(self.sample_sleep)
return data
def update_stats(self, data):
# data is a list of (position, key, value, len(value)) tuples
items = len([1 for x in data if x[3] > 0])
@@ -68,54 +69,75 @@ class Cache:
self.samples += 1
block_sizes = sum([x[3] for x in data])
self.block_sizes += block_sizes
self.history.append({'full': full, 'empty': empty, 'data': data, \
'items': items, 'block_sizes': block_sizes})
self.history.append({
'full': full,
'empty': empty,
'data': data,
'items': items,
'block_sizes': block_sizes
})
def dump(self):
return {
'samples': self.samples,
'history': self.history,
'cache_slots': self.cache_slots,
'sample_sleep': self.sample_sleep,
'sample_sleep': self.sample_sleep,
'cache_empty': self.cache_empty,
'cache_full': self.cache_full,
'cache_items': self.cache_items,
'block_sizes': self.block_sizes,
}
}
def show_dump(self):
d = self.dump()
print
print "Recorded %d samples (%d second(s) sleep between samples)" % \
(d['samples'], d['sample_sleep'])
print "Cache empty %d times, full %d times, %.2f items on average" % \
(d['cache_empty'], d['cache_full'], d['cache_items'] / d['samples'])
print "Block size average size: %d bytes" % \
(d['block_sizes'] / d['cache_items'] * 8)
print "Data in cache average: %d bytes" % \
(d['block_sizes'] / d['samples'] * 8)
print()
print("Recorded %d samples (%d second(s) sleep between samples)" % (
d['samples'],
d['sample_sleep']
))
print("Cache empty %d times, full %d times, %.2f items on average" % (
d['cache_empty'],
d['cache_full'],
d['cache_items'] / d['samples']
))
print("Block size average size: %d bytes" % (
d['block_sizes'] / d['cache_items'] * 8
))
print("Data in cache average: %d bytes" % (
d['block_sizes'] / d['samples'] * 8
))
def main(options):
cache = Cache(options.cache_store, options.cache_slots, options.block_size,
options.sleep_time)
print "Recording..."
options.sleep_time)
print("Recording...")
while True:
try:
data = cache.read()
cache.read()
except KeyboardInterrupt:
cache.show_dump()
sys.exit(0)
if __name__ == '__main__':
parser = OptionParser()
parser.add_option("-s", "--cache-slots", dest="cache_slots", type="int",
help="Slots available in the cache, uwsgi cache option")
parser.add_option("-c", "--cache-store", dest="cache_store", default="uwsgi.cache",
help="The filename of the cache store, uwsgi cache-store option. Default: uwsgi.cache")
parser.add_option("-b", "--block-size", dest="block_size", default=65536, type="int",
help="The size of the cache block, uwsgi cache-blocksize option. Default: 65536")
parser.add_option("-t", "--sleep-time", dest="sleep_time", default=1, type="int",
help="The time to sleep between each sample. Default: 1")
parser.add_option(
"-s", "--cache-slots", dest="cache_slots", type="int",
help="Slots available in the cache, uwsgi cache option"
)
parser.add_option(
"-c", "--cache-store", dest="cache_store", default="uwsgi.cache",
help="The filename of the cache store, uwsgi cache-store option. Default: uwsgi.cache"
)
parser.add_option(
"-b", "--block-size", dest="block_size", default=65536, type="int",
help="The size of the cache block, uwsgi cache-blocksize option. Default: 65536"
)
parser.add_option(
"-t", "--sleep-time", dest="sleep_time", default=1, type="int",
help="The time to sleep between each sample. Default: 1"
)
(options, args) = parser.parse_args()
if not options.cache_slots:
+1
View File
@@ -171,6 +171,7 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
ual = uwsgi_calloc(sizeof(struct uwsgi_alarm_log));
if (uwsgi_regexp_build(regexp, &ual->pattern, &ual->pattern_extra)) {
free(ual);
return -1;
}
ual->negate = negate;
+12 -8
View File
@@ -21,7 +21,7 @@ extern struct uwsgi_server uwsgi;
// this is called whenever a new connection is ready, but there are no cores to handle it
void uwsgi_async_queue_is_full(time_t now) {
if (now > uwsgi.async_queue_is_full) {
if (now > uwsgi.async_queue_is_full && uwsgi.async_warn_if_queue_full) {
uwsgi_log_verbose("[DANGER] async queue is full !!!\n");
uwsgi.async_queue_is_full = now;
}
@@ -165,7 +165,7 @@ static void async_expire_timeouts(uint64_t now) {
int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table){
if (uwsgi.async < 1 || !uwsgi.async_waiting_fd_table){
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return -1;
}
@@ -257,7 +257,7 @@ static int async_wait_fd_read2(int fd0, int fd1, int timeout, int *fd) {
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
if (uwsgi.async < 2 || !uwsgi.rb_async_timeouts) {
if (uwsgi.async < 1 || !uwsgi.rb_async_timeouts) {
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return;
}
@@ -272,7 +272,7 @@ void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table) {
if (uwsgi.async < 1 || !uwsgi.async_waiting_fd_table) {
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return -1;
}
@@ -370,7 +370,7 @@ void async_schedule_to_req_green(void) {
}
// switch after each yield
if (uwsgi.schedule_to_main)
uwsgi.schedule_to_main(wsgi_req);
uwsgi.schedule_to_main(wsgi_req);
}
#ifdef UWSGI_ROUTING
@@ -385,7 +385,6 @@ end:
wsgi_req->async_status = UWSGI_OK;
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req;
}
static int uwsgi_async_wait_milliseconds_hook(int timeout) {
@@ -407,7 +406,7 @@ static int uwsgi_async_wait_milliseconds_hook(int timeout) {
void async_loop() {
if (uwsgi.async < 2) {
if (uwsgi.async < 1) {
uwsgi_log("the async loop engine requires async mode (--async <n>)\n");
exit(1);
}
@@ -482,7 +481,12 @@ void async_loop() {
// signals are executed in the main stack... in the future we could have dedicated stacks for them
if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
uwsgi_async_queue_is_full((time_t)now);
continue;
}
uwsgi_receive_signal(uwsgi.wsgi_req, interesting_fd, "worker", uwsgi.mywid);
continue;
}
+33
View File
@@ -150,6 +150,32 @@ int uwsgi_buffer_append_json(struct uwsgi_buffer *ub, char *buf, size_t len) {
return 0;
}
int uwsgi_buffer_append_xml(struct uwsgi_buffer *ub, char *buf, size_t len) {
// need to escape \ and "
size_t i;
for(i=0;i<len;i++) {
if (buf[i] == '"') {
if (uwsgi_buffer_append(ub, "&quot;", 6)) return -1;
}
else if (buf[i] == '\'') {
if (uwsgi_buffer_append(ub, "&apos;", 6)) return -1;
}
else if (buf[i] == '<') {
if (uwsgi_buffer_append(ub, "&lt;", 4)) return -1;
}
else if (buf[i] == '>') {
if (uwsgi_buffer_append(ub, "&gt;", 4)) return -1;
}
else if (buf[i] == '&') {
if (uwsgi_buffer_append(ub, "&amp;", 5)) return -1;
}
else {
if (uwsgi_buffer_append(ub, buf+i, 1)) return -1;
}
}
return 0;
}
int uwsgi_buffer_u16le(struct uwsgi_buffer *ub, uint16_t num) {
uint8_t buf[2];
buf[0] = (uint8_t) (num & 0xff);
@@ -418,3 +444,10 @@ void uwsgi_buffer_map(struct uwsgi_buffer *ub, char *buf, size_t len) {
ub->pos = len;
ub->len = len;
}
int uwsgi_buffer_httpdate(struct uwsgi_buffer *ub, time_t t) {
char http_last_modified[49];
int size = uwsgi_http_date(t, http_last_modified);
if (size <= 0) return -1;
return uwsgi_buffer_append(ub, http_last_modified, size);
}
+3 -4
View File
@@ -242,7 +242,6 @@ static void uwsgi_cache_add_items(struct uwsgi_cache *uc) {
goto next;
}
key = space+1;
key_len = usl->len - ((space-usl->value)+1);
}
char *value = strchr(key, '=');
if (!value) {
@@ -972,7 +971,7 @@ static void cache_send_udp_command(struct uwsgi_cache *uc, char *key, uint16_t k
iov[2].iov_base = key;
iov[2].iov_len = keylen;
uh.pktsize = 2 + keylen;
uh._pktsize = 2 + keylen;
if (cmd == 10) {
u_v[0] = (uint8_t) (vallen16 & 0xff);
@@ -996,7 +995,7 @@ static void cache_send_udp_command(struct uwsgi_cache *uc, char *key, uint16_t k
iov[6].iov_base = es;
iov[6].iov_len = es_size;
uh.pktsize += 2 + vallen16 + 2 + es_size;
uh._pktsize += 2 + vallen16 + 2 + es_size;
}
uh.modifier1 = 111;
@@ -2042,7 +2041,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
ub->pos = 4;
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
if (uc->name && uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
+591 -161
View File
File diff suppressed because it is too large Load Diff
+3 -4
View File
@@ -46,7 +46,7 @@ extern struct uwsgi_server uwsgi;
struct uwsgi_buffer *uwsgi_exception_handler_object(struct wsgi_request *wsgi_req) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
if (uwsgi_buffer_append_keyval(ub, "vars", 4, wsgi_req->buffer,wsgi_req->uh->pktsize)) goto error;
if (uwsgi_buffer_append_keyval(ub, "vars", 4, wsgi_req->buffer, wsgi_req->len)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->backtrace) {
struct uwsgi_buffer *bt = uwsgi.p[wsgi_req->uh->modifier1]->backtrace(wsgi_req);
if (bt) {
@@ -280,7 +280,7 @@ notavail4:
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
if (uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->pktsize, append_vars_to_ubuf, ub)) {
if (uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->len, append_vars_to_ubuf, ub)) {
goto error;
}
@@ -464,6 +464,7 @@ void uwsgi_exception_setup_handlers() {
struct uwsgi_string_list *usl = uwsgi.exception_handlers_instance;
while(usl) {
// do not free handler !!!
char *handler = uwsgi_str(usl->value);
char *colon = strchr(handler, ':');
if (colon) {
@@ -472,10 +473,8 @@ void uwsgi_exception_setup_handlers() {
struct uwsgi_exception_handler *ueh = uwsgi_exception_handler_by_name(handler);
if (!ueh) {
uwsgi_log("unable to find exception handler: %s\n", handler);
free(handler);
exit(1);
}
free(handler);
struct uwsgi_exception_handler_instance *uehi = uwsgi_calloc(sizeof(struct uwsgi_exception_handler_instance));
uehi->handler = ueh;
+227
View File
@@ -0,0 +1,227 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
on connection retrieve the uid,gid and pid of the connecting process, in addition to up to 3
file descriptors (emperor pipe, emperor pipe_config, on_demand socket dup()'ed to 0)
if authorized, double fork, get the pid of the second child and exit()
its parent (this will force the Emperor to became its subreaper).
from now on, we can consider the new child as a full-featured vassal
*/
#define VASSAL_HAS_CONFIG 0x02
#define VASSAL_HAS_ON_DEMAND 0x04
static void parse_argv_hook(uint16_t item, char *value, uint16_t vlen, void *data) {
struct uwsgi_string_list **usl = (struct uwsgi_string_list **) data;
uwsgi_string_new_list(usl, uwsgi_concat2n(value, vlen, "", 0));
}
void uwsgi_fork_server(char *socket) {
// map fd 0 to /dev/null to avoid mess
uwsgi_remap_fd(0, "/dev/null");
int fd = bind_to_unix(socket, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
if (fd < 0) exit(1);
// automatically receive credentials (TODO make something useful with them, like checking the pid is from the Emperor)
if (uwsgi_socket_passcred(fd)) exit(1);
// initialize the event queue
int eq = event_queue_init();
if (uwsgi.has_emperor) {
event_queue_add_fd_read(eq, uwsgi.emperor_fd);
}
event_queue_add_fd_read(eq, fd);
// now start waiting for connections
for(;;) {
int interesting_fd = -1;
int rlen = event_queue_wait(eq, -1, &interesting_fd);
if (rlen <= 0) continue;
if (uwsgi.has_emperor && interesting_fd == uwsgi.emperor_fd) {
char byte;
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
if (rlen > 0) {
uwsgi_log_verbose("received message %d from emperor\n", byte);
}
exit(0);
}
if (interesting_fd != fd) continue;
struct sockaddr_un client_src;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("uwsgi_fork_server()/accept()");
continue;
}
char hbuf[4];
pid_t ppid = -1;
uid_t uid = -1;
gid_t gid = -1;
int fds_count = 8;
size_t remains = 4;
// we can receive upto 8 fds (generally from 1 to 3)
int fds[8];
// we only read 4 bytes header
ssize_t len = uwsgi_recv_cred_and_fds(client_fd, hbuf, remains, &ppid, &uid, &gid, fds, &fds_count);
uwsgi_log_verbose("[uwsgi-fork-server] connection from pid: %d uid: %d gid:%d fds:%d\n", ppid, uid, gid, fds_count);
if (len <= 0 || fds_count < 1) {
uwsgi_error("uwsgi_fork_server()/recvmsg()");
goto end;
}
remains -= len;
if (uwsgi_read_nb(client_fd, hbuf + (4-remains), remains, uwsgi.socket_timeout)) {
uwsgi_error("uwsgi_fork_server()/uwsgi_read_nb()");
goto end;
}
struct uwsgi_header *uh = (struct uwsgi_header *) hbuf;
// this memory area must be freed in the right place !!!
char *body_argv = uwsgi_malloc(uh->_pktsize);
if (uwsgi_read_nb(client_fd, body_argv, uh->_pktsize, uwsgi.socket_timeout)) {
free(body_argv);
uwsgi_error("uwsgi_fork_server()/uwsgi_read_nb()");
goto end;
}
pid_t pid = fork();
if (pid < 0) {
free(body_argv);
int i;
for(i=0;i<fds_count;i++) close(fds[i]);
// error on fork()
uwsgi_error("uwsgi_fork_server()/fork()");
goto end;
}
else if (pid > 0) {
free(body_argv);
// close inherited decriptors
int i;
for(i=0;i<fds_count;i++) close(fds[i]);
// wait for child death...
waitpid(pid, NULL, 0);
goto end;
}
else {
// close Emperor channels
// we do not close others file desctiptor as lot
// of funny tricks could be accomplished with them
if (uwsgi.has_emperor) {
close(uwsgi.emperor_fd);
if (uwsgi.emperor_fd_config > -1) close(uwsgi.emperor_fd_config);
}
// set EMPEROR_FD and FD_CONFIG env vars
char *uef = uwsgi_num2str(fds[0]);
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
uwsgi_error("uwsgi_fork_server()/setenv()");
exit(1);
}
free(uef);
int pipe_config = -1;
int on_demand = -1;
if (uh->modifier2 & VASSAL_HAS_CONFIG && fds_count > 1) {
pipe_config = fds[1];
char *uef = uwsgi_num2str(pipe_config);
if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
uwsgi_error("uwsgi_fork_server()/setenv()");
exit(1);
}
free(uef);
}
if (uh->modifier2 & VASSAL_HAS_ON_DEMAND && fds_count > 1) {
if (pipe_config > -1) {
if (fds_count > 2) {
on_demand = fds[2];
}
}
else {
on_demand = fds[1];
}
}
// dup the on_demand socket to 0 and close it
if (on_demand > -1) {
if (dup2(on_demand, 0) < 0) {
uwsgi_error("uwsgi_fork_server()/dup2()");
exit(1);
}
close(on_demand);
}
// now fork again and die
pid_t new_pid = fork();
if (new_pid < 0) {
uwsgi_error("uwsgi_fork_server()/fork()");
exit(1);
}
else if (new_pid > 0) {
exit(0);
}
else {
// send the pid to the client_fd and close it
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
// leave space for header
ub->pos = 4;
if (uwsgi_buffer_append_keynum(ub, "pid", 3, getpid())) exit(1);
// fix uwsgi header
if (uwsgi_buffer_set_uh(ub, 35, 0)) goto end;
// send_pid()
if (uwsgi_write_nb(client_fd, ub->buf, ub->pos, uwsgi.socket_timeout)) exit(1);
close(client_fd);
uwsgi_log("double fork() and reparenting successfull (new pid: %d)\n", getpid());
uwsgi_buffer_destroy(ub);
// now parse the uwsgi packet array and build the argv
struct uwsgi_string_list *usl = NULL, *usl_argv = NULL;
uwsgi_hooked_parse_array(body_argv, uh->_pktsize, parse_argv_hook, &usl_argv);
free(body_argv);
// build new argc/argv
uwsgi.new_argc = 0;
size_t procname_len = 1;
uwsgi_foreach(usl, usl_argv) {
uwsgi.new_argc++;
procname_len += usl->len + 1;
}
char *new_procname = uwsgi_calloc(procname_len);
uwsgi.new_argv = uwsgi_calloc(sizeof(char *) * (uwsgi.new_argc + 1));
int counter = 0;
uwsgi_foreach(usl, usl_argv) {
uwsgi.new_argv[counter] = usl->value;
strcat(new_procname, usl->value);
strcat(new_procname, " ");
counter++;
}
// fix process name
uwsgi_set_processname(new_procname);
free(new_procname);
// this is the only step required to have a consistent environment
uwsgi.fork_socket = NULL;
// this avoids the process to re-exec itself
uwsgi.exit_on_reload = 1;
// fixup the Emperor communication
uwsgi_check_emperor();
// continue with uWSGI startup
return;
}
}
end:
close(client_fd);
}
}
+3 -10
View File
@@ -61,16 +61,9 @@ static void fsmon_reload(struct uwsgi_fsmon *fs) {
}
static void fsmon_brutal_reload(struct uwsgi_fsmon *fs) {
if (uwsgi.die_on_term) {
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
else {
uwsgi_block_signal(SIGTERM);
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
static void fsmon_signal(struct uwsgi_fsmon *fs) {
+1 -1
View File
@@ -72,7 +72,7 @@ void gateway_respawn(int id) {
if (gw_pid == 0) {
uwsgi_fixup_fds(0, 0, ug);
uwsgi_close_all_sockets();
uwsgi_close_all_unshared_sockets();
if (uwsgi.master_as_root)
uwsgi_as_root();
#ifdef __linux__
+213 -43
View File
@@ -91,6 +91,14 @@ static int uwsgi_hook_exec(char *arg) {
return ret;
}
static int uwsgi_hook_safeexec(char *arg) {
int ret = uwsgi_run_command_and_wait(NULL, arg);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", arg, ret);
}
return 0;
}
static int uwsgi_hook_exit(char *arg) {
int exit_code = 0;
if (strlen(arg) > 1) {
@@ -388,9 +396,10 @@ static int uwsgi_hook_chown2(char *arg) {
}
#ifdef __sun__
#if defined(UWSGI_SUNOS_EXTERN_SETHOSTNAME)
extern int sethostname(char *, int);
#endif
static int uwsgi_hook_hostname(char *arg) {
#ifdef __CYGWIN__
return -1;
@@ -399,6 +408,24 @@ static int uwsgi_hook_hostname(char *arg) {
#endif
}
static int uwsgi_hook_unix_signal(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid unix_signal syntax, must be <signum> <func>\n");
return -1;
}
*space = 0;
int signum = atoi(arg);
*space = ' ';
void (*func)(int) = dlsym(RTLD_DEFAULT, space+1);
if (!func) {
uwsgi_log("unable to find function \"%s\"\n", space+1);
return -1;
}
uwsgi_unix_signal(signum, func);
return 0;
}
static int uwsgi_hook_callint(char *arg) {
char *space = strchr(arg, ' ');
@@ -549,6 +576,22 @@ static int uwsgi_hook_retryrpc(char *arg) {
return 0;
}
static int uwsgi_hook_wait_for_fs(char *arg) {
return uwsgi_wait_for_fs(arg, 0);
}
static int uwsgi_hook_wait_for_file(char *arg) {
return uwsgi_wait_for_fs(arg, 1);
}
static int uwsgi_hook_wait_for_dir(char *arg) {
return uwsgi_wait_for_fs(arg, 2);
}
static int uwsgi_hook_wait_for_socket(char *arg) {
return uwsgi_wait_for_socket(arg);
}
void uwsgi_register_base_hooks() {
uwsgi_register_hook("cd", uwsgi_hook_chdir);
uwsgi_register_hook("chdir", uwsgi_hook_chdir);
@@ -562,6 +605,7 @@ void uwsgi_register_base_hooks() {
uwsgi_register_hook("sticky", uwsgi_hook_sticky);
uwsgi_register_hook("exec", uwsgi_hook_exec);
uwsgi_register_hook("safeexec", uwsgi_hook_safeexec);
uwsgi_register_hook("create", uwsgi_hook_creat);
uwsgi_register_hook("creat", uwsgi_hook_creat);
@@ -589,61 +633,187 @@ void uwsgi_register_base_hooks() {
uwsgi_register_hook("rpc", uwsgi_hook_rpc);
uwsgi_register_hook("retryrpc", uwsgi_hook_retryrpc);
uwsgi_register_hook("wait_for_fs", uwsgi_hook_wait_for_fs);
uwsgi_register_hook("wait_for_file", uwsgi_hook_wait_for_file);
uwsgi_register_hook("wait_for_dir", uwsgi_hook_wait_for_dir);
uwsgi_register_hook("wait_for_socket", uwsgi_hook_wait_for_socket);
uwsgi_register_hook("unix_signal", uwsgi_hook_unix_signal);
// for testing
uwsgi_register_hook("exit", uwsgi_hook_exit);
uwsgi_register_hook("print", uwsgi_hook_print);
uwsgi_register_hook("log", uwsgi_hook_print);
}
int uwsgi_hooks_run_and_return(struct uwsgi_string_list *l, char *phase, char *context, int fatal) {
int final_ret = 0;
struct uwsgi_string_list *usl = NULL;
if (context) {
if (setenv("UWSGI_HOOK_CONTEXT", context, 1)) {
uwsgi_error("uwsgi_hooks_run_and_return()/setenv()");
return -1;
}
}
uwsgi_foreach(usl, l) {
char *colon = strchr(usl->value, ':');
if (!colon) {
uwsgi_log("invalid hook syntax, must be hook:args\n");
exit(1);
}
*colon = 0;
int private = 0;
char *action = usl->value;
// private hook ?
if (action[0] == '!') {
action++;
private = 1;
}
struct uwsgi_hook *uh = uwsgi_hook_by_name(action);
if (!uh) {
uwsgi_log("hook action not found: %s\n", action);
exit(1);
}
*colon = ':';
if (private) {
uwsgi_log("running --- PRIVATE HOOK --- (%s)...\n", phase);
}
else {
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
}
int ret = uh->func(colon+1);
if (ret != 0) {
if (fatal) {
if (context) {
unsetenv("UWSGI_HOOK_CONTEXT");
}
return ret;
}
final_ret = ret;
}
}
if (context) {
unsetenv("UWSGI_HOOK_CONTEXT");
}
return final_ret;
}
void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
int ret = uwsgi_hooks_run_and_return(l, phase, NULL, fatal);
if (fatal && ret != 0) {
uwsgi_log_verbose("FATAL hook failed, destroying instance\n");
if (uwsgi.master_process) {
if (uwsgi.workers) {
if (uwsgi.workers[0].pid == getpid()) {
kill_them_all(0);
return;
}
else {
if (kill(uwsgi.workers[0].pid, SIGINT)) {
uwsgi_error("uwsgi_hooks_run()/kill()");
exit(1);
}
return;
}
}
}
exit(1);
}
}
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
/*
this is a special hook, allowing the Emperor to enter a vassal
namespace and call hooks in its namespace context.
*/
void uwsgi_hooks_setns_run(struct uwsgi_string_list *l, pid_t pid, uid_t uid, gid_t gid) {
int (*u_setns) (int, int) = (int (*)(int, int)) dlsym(RTLD_DEFAULT, "setns");
if (!u_setns) {
uwsgi_log("your system misses setns() syscall !!!\n");
return;
}
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, l) {
char *colon = strchr(usl->value, ':');
if (!colon) {
uwsgi_log("invalid hook syntax, must be hook:args\n");
exit(1);
// fist of all fork() the current process
pid_t new_pid = fork();
if (new_pid > 0) {
// wait for its death
int status;
if (waitpid(new_pid, &status, 0) < 0) {
uwsgi_error("uwsgi_hooks_setns_run()/waitpid()");
}
}
*colon = 0;
int private = 0;
char *action = usl->value;
// private hook ?
if (action[0] == '!') {
action++;
private = 1;
}
struct uwsgi_hook *uh = uwsgi_hook_by_name(action);
if (!uh) {
uwsgi_log("hook action not found: %s\n", action);
exit(1);
}
*colon = ':';
else if (new_pid == 0) {
// from now on, freeing memory is useless
// now split args to know which namespaces to join
char *action = strchr(usl->value, ' ');
if (!action) {
uwsgi_log("invalid setns hook syntax, must be \"namespaces_list action:...\"\n");
exit(1);
}
char *pidstr = uwsgi_num2str(pid);
char *uidstr = uwsgi_num2str(uid);
char *gidstr = uwsgi_num2str(gid);
if (private) {
uwsgi_log("running --- PRIVATE HOOK --- (%s)...\n", phase);
char *namespaces = uwsgi_concat2n(usl->value, action-usl->value, "", 0);
char *p, *ctx = NULL;
uwsgi_foreach_token(namespaces, ",", p, ctx) {
char *procfile = uwsgi_concat4("/proc/", pidstr, "/ns/", p);
int fd = open(procfile, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(procfile);
exit(1);
}
if (u_setns(fd, 0) < 0){
uwsgi_error("uwsgi_hooks_setns_run()/setns()");
exit(1);
}
close(fd);
free(procfile);
}
if (setenv("UWSGI_VASSAL_PID", pidstr, 1)) {
uwsgi_error("uwsgi_hooks_setns_run()/setenv()");
exit(1);
}
if (setenv("UWSGI_VASSAL_UID", uidstr, 1)) {
uwsgi_error("uwsgi_hooks_setns_run()/setenv()");
exit(1);
}
if (setenv("UWSGI_VASSAL_GID", gidstr, 1)) {
uwsgi_error("uwsgi_hooks_setns_run()/setenv()");
exit(1);
}
// now run the action and then exit
action++;
char *colon = strchr(action, ':');
if (!colon) {
uwsgi_log("invalid hook syntax must be action:arg\n");
exit(1);
}
*colon = 0;
struct uwsgi_hook *uh = uwsgi_hook_by_name(action);
if (!uh) {
uwsgi_log("hook action not found: %s\n", action);
exit(1);
}
*colon = ':';
uwsgi_log("running \"%s\" (setns)...\n", usl->value);
exit(uh->func(colon+1));
}
else {
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
}
int ret = uh->func(colon+1);
if (fatal && ret != 0) {
uwsgi_log_verbose("FATAL hook failed, destroying instance\n");
if (uwsgi.master_process) {
if (uwsgi.workers) {
if (uwsgi.workers[0].pid == getpid()) {
kill_them_all(0);
return;
}
else {
if (kill(uwsgi.workers[0].pid, SIGINT)) {
uwsgi_error("uwsgi_hooks_run()/kill()");
exit(1);
}
return;
}
}
}
exit(1);
uwsgi_error("uwsgi_hooks_setns_run()/fork()");
}
}
}
#endif
+57 -4
View File
@@ -9,7 +9,7 @@ extern struct uwsgi_server uwsgi;
static char *last_file = NULL;
void ini_rstrip(char *line) {
static void ini_rstrip(char *line) {
off_t i;
@@ -22,7 +22,7 @@ void ini_rstrip(char *line) {
}
}
char *ini_lstrip(char *line) {
static char *ini_lstrip(char *line) {
off_t i;
char *ptr = line;
@@ -38,7 +38,7 @@ char *ini_lstrip(char *line) {
return ptr;
}
char *ini_get_key(char *key) {
static char *ini_get_key(char *key) {
off_t i;
char *ptr = key;
@@ -54,7 +54,7 @@ char *ini_get_key(char *key) {
return ptr;
}
char *ini_get_line(char *ini, size_t size) {
static char *ini_get_line(char *ini, size_t size) {
size_t i;
char *ptr = ini;
@@ -171,5 +171,58 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
colon[0] = ':';
}
}
void uwsgi_emperor_ini_attrs(char *filename, char *section_asked, struct uwsgi_dyn_dict **attrs) {
if (!section_asked) section_asked = "emperor";
char *ini = uwsgi_simple_file_read(filename);
if (!ini) return;
char *orig_ini = ini;
size_t len = strlen(ini);
char *section = "";
char *key, *val, *ini_line;
while (len) {
ini_line = ini_get_line(ini, len);
if (ini_line == NULL) {
break;
}
// skip empty line
key = ini_lstrip(ini);
ini_rstrip(key);
if (key[0] != 0) {
if (key[0] == '[') {
section = key + 1;
section[strlen(section) - 1] = 0;
}
else if (key[0] == ';' || key[0] == '#') {
// this is a comment
}
else {
// val is always valid, but (obviously) can be ignored
val = ini_get_key(key);
if (!strcmp(section, section_asked)) {
ini_rstrip(key);
struct uwsgi_string_list *usl = uwsgi_string_list_has_item(uwsgi.emperor_collect_attributes, key, strlen(key));
if (usl) {
val = ini_lstrip(val);
ini_rstrip(val);
char *value = uwsgi_str(val);
uwsgi_dyn_dict_new(attrs, usl->value, usl->len, value, strlen(value));
}
}
}
}
len -= (ini_line - ini);
ini += (ini_line - ini);
}
free(orig_ini);
}
+51 -7
View File
@@ -61,6 +61,8 @@ struct http_status_codes hsc[] = {
void uwsgi_init_default() {
uwsgi.cpus = 1;
uwsgi.new_argc = -1;
uwsgi.binary_argc = 1;
uwsgi.backtrace_depth = 64;
uwsgi.max_apps = 64;
@@ -105,10 +107,12 @@ void uwsgi_init_default() {
uwsgi.forkbomb_delay = 2;
uwsgi.async = 1;
uwsgi.async = 0;
uwsgi.async_warn_if_queue_full = 1;
uwsgi.listen_queue = 100;
uwsgi.cheaper_overload = 3;
uwsgi.cheaper_idle = 10;
uwsgi.log_master_bufsize = 8192;
@@ -252,9 +256,42 @@ void uwsgi_commandline_config() {
int i;
uwsgi.option_index = -1;
// required in case we want to call getopt_long from the beginning
optind = 0;
int argc = uwsgi.argc;
char **argv = uwsgi.argv;
// we might want to ignore some arguments not meant for us
char binary_argv0_pretty[256] = {'\0'};
char *binary_argv0_actual = NULL;
if (uwsgi.new_argc > -1 && uwsgi.new_argv) {
argc = uwsgi.new_argc;
argv = uwsgi.new_argv;
}
if (uwsgi.binary_argc > 1 && argc >= uwsgi.binary_argc) {
char *pretty = (char *)binary_argv0_pretty;
strncat(pretty, argv[0], 255);
for (i = 1; i < uwsgi.binary_argc; i++) {
if (strlen(pretty) + 1 + strlen(argv[i]) + 1 > 256)
break;
strcat(pretty, " ");
strcat(pretty, argv[i]);
}
argc -= uwsgi.binary_argc - 1;
argv += uwsgi.binary_argc - 1;
binary_argv0_actual = argv[0];
argv[0] = (char *)binary_argv0_pretty;
}
char *optname;
while ((i = getopt_long(uwsgi.argc, uwsgi.argv, uwsgi.short_options, uwsgi.long_options, &uwsgi.option_index)) != -1) {
while ((i = getopt_long(argc, argv, uwsgi.short_options, uwsgi.long_options, &uwsgi.option_index)) != -1) {
if (i == '?') {
uwsgi_log("getopt_long() error\n");
@@ -275,14 +312,16 @@ void uwsgi_commandline_config() {
add_exported_option(optname, optarg, 0);
}
if (binary_argv0_actual != NULL)
argv[0] = binary_argv0_actual;
#ifdef UWSGI_DEBUG
uwsgi_log("optind:%d argc:%d\n", optind, uwsgi.argc);
#endif
if (optind < uwsgi.argc) {
for (i = optind; i < uwsgi.argc; i++) {
char *lazy = uwsgi.argv[i];
if (optind < argc) {
for (i = optind; i < argc; i++) {
char *lazy = argv[i];
if (lazy[0] != '[') {
uwsgi_opt_load(NULL, lazy, NULL);
// manage magic mountpoint
@@ -399,7 +438,8 @@ pid_t uwsgi_daemonize2() {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
if (uwsgi.log_master) uwsgi_setup_log_master();
if (uwsgi.log_master)
uwsgi_setup_log_master();
return uwsgi.mypid;
}
@@ -407,7 +447,7 @@ pid_t uwsgi_daemonize2() {
// fix/check related options
void sanitize_args() {
if (uwsgi.async > 1) {
if (uwsgi.async > 0) {
uwsgi.cores = uwsgi.async;
}
@@ -471,6 +511,10 @@ void sanitize_args() {
exit(1);
}
if (uwsgi.evil_reload_on_rss || uwsgi.evil_reload_on_as) {
if (!uwsgi.mem_collector_freq) uwsgi.mem_collector_freq = 3;
}
/* here we try to choose if thunder lock is a good thing */
#ifdef UNBIT
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
+178 -46
View File
@@ -90,7 +90,7 @@ char *uwsgi_simple_file_read(char *filename) {
}
if (fstat(fd, &sb)) {
uwsgi_error("fstat()");
uwsgi_error("uwsgi_simple_file_read()/fstat()");
close(fd);
goto end;
}
@@ -99,7 +99,7 @@ char *uwsgi_simple_file_read(char *filename) {
len = read(fd, buffer, sb.st_size);
if (len != sb.st_size) {
uwsgi_error("read()");
uwsgi_error("uwsgi_simple_file_read()/read()");
free(buffer);
close(fd);
goto end;
@@ -112,7 +112,7 @@ char *uwsgi_simple_file_read(char *filename) {
buffer[sb.st_size] = 0;
return buffer;
end:
return (char *) "";
return NULL;
}
@@ -277,7 +277,7 @@ static char *uwsgi_scheme_emperor(char *url, size_t *size, int add_zero) {
remains-=rlen;
}
remains = uh.pktsize;
remains = uh._pktsize;
if (!remains) {
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
exit(1);
@@ -300,7 +300,7 @@ static char *uwsgi_scheme_emperor(char *url, size_t *size, int add_zero) {
remains-=rlen;
}
*size = uh.pktsize + add_zero;
*size = uh._pktsize + add_zero;
return buffer;
}
@@ -342,6 +342,10 @@ static char *uwsgi_scheme_data(char *url, size_t *size, int add_zero) {
uwsgi_log("0 size binary data !!!\n");
exit(1);
}
if (datasize > SIZE_MAX) {
uwsgi_log("size binary data bigger than SIZE_MAX !!!\n");
exit(1);
}
fo = lseek(fd, -(datasize + 8), SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
@@ -1063,7 +1067,7 @@ readok:
}
struct uwsgi_header *uh = (struct uwsgi_header *) buf;
uint16_t pktsize = uh->pktsize;
uint16_t pktsize = uh->_pktsize;
if (modifier1)
*modifier1 = uh->modifier1;
if (modifier2)
@@ -1119,46 +1123,48 @@ int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffe
struct uwsgi_buffer *headers = NULL;
int fd = uwsgi_connect(addr, 0, 1);
if (fd < 0) {
if (!ub) {
return -1;
}
int ret = uwsgi.wait_write_hook(fd, timeout);
if (ret <= 0) {
goto end;
}
// send the request (+ remaining data)
if (ub) {
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) {
goto end;
}
}
// send the body
while(remains > 0) {
ssize_t rlen = 0;
char *buf = uwsgi_request_body_read(wsgi_req, 8192, &rlen);
if (!buf) {
goto end;
}
if (buf == uwsgi.empty) break;
// write data to the node
if (uwsgi_write_true_nb(fd, buf, rlen, timeout)) {
goto end;
}
remains -= rlen;
}
int fd = uwsgi_connect(addr, 0, 1);
if (fd < 0) {
return -1;
}
// read the response
int ret = uwsgi.wait_write_hook(fd, timeout);
if (ret <= 0) {
goto end;
}
// send the request (+ remaining data)
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) {
goto end;
}
// send the body
while(remains > 0) {
ssize_t rlen = 0;
char *buf = uwsgi_request_body_read(wsgi_req, 8192, &rlen);
if (!buf) {
goto end;
}
if (buf == uwsgi.empty) break;
// write data to the node
if (uwsgi_write_true_nb(fd, buf, rlen, timeout)) {
goto end;
}
remains -= rlen;
}
// read the response
headers = uwsgi_buffer_new(8192);
// max 64k headers
ub->limit = UMAX16;
for(;;) {
char buf[8192];
ssize_t rlen = uwsgi_read_true_nb(fd, buf, 8192, timeout);
if (rlen > 0) {
for(;;) {
char buf[8192];
ssize_t rlen = uwsgi_read_true_nb(fd, buf, 8192, timeout);
if (rlen > 0) {
if (headers) {
if (uwsgi_buffer_append(headers, buf, rlen)) {
goto end;
@@ -1172,14 +1178,14 @@ int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffe
}
}
else {
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
break;
}
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
break;
}
}
continue;
}
break;
}
continue;
}
break;
}
if (headers) uwsgi_buffer_destroy(headers);
close(fd);
@@ -1502,3 +1508,129 @@ clear:
#endif
}
ssize_t uwsgi_recv_cred_and_fds(int fd, char *buf, size_t buf_len, pid_t *pid, uid_t *uid, gid_t *gid, int *fds, int *fds_count) {
#if defined(SCM_CREDENTIALS) && defined(SCM_RIGHTS)
ssize_t ret = -1;
size_t msg_len = CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int) * (*fds_count));
// allocate space for credentials and file descriptors
void *msg_control = uwsgi_calloc(msg_len);
// read into buf
struct iovec iov;
iov.iov_base = buf;
iov.iov_len = buf_len;
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
// set cmsg
msg.msg_control = msg_control;
msg.msg_controllen = msg_len;
ssize_t len = recvmsg(fd, &msg, 0);
if (len <= 0) {
uwsgi_error("uwsgi_recv_cred_and_fds()/recvmsg()");
goto clear;
}
// reset the number of fds
*fds_count = 0;
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
while(cmsg) {
if (cmsg->cmsg_level != SOL_SOCKET) goto next;
if (cmsg->cmsg_type == SCM_RIGHTS) {
size_t fds_len = cmsg->cmsg_len - ((char *) CMSG_DATA(cmsg) - (char *) cmsg);
memcpy(fds, CMSG_DATA(cmsg), fds_len);
*fds_count = fds_len/sizeof(int);
}
else if (cmsg->cmsg_type == SCM_CREDENTIALS) {
struct ucred *u = (struct ucred *) CMSG_DATA(cmsg);
*pid = u->pid;
*uid = u->uid;
*gid = u->gid;
}
next:
cmsg=CMSG_NXTHDR(&msg,cmsg);
}
ret = len;
clear:
free(msg_control);
return ret;
#else
return -1;
#endif
}
int uwsgi_send_fds_and_body(int fd, int *fds, int fds_count, char *body, size_t len) {
int ret = -1;
struct msghdr msg;
void *msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * fds_count));
struct iovec iov;
struct cmsghdr *cmsg;
iov.iov_base = body;
iov.iov_len = len;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
msg.msg_control = msg_control;
msg.msg_controllen = CMSG_SPACE(sizeof(int) * fds_count);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fds_count);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
unsigned char *fd_ptr = CMSG_DATA(cmsg);
memcpy(fd_ptr, fds, sizeof(int) * fds_count);
ssize_t rlen = sendmsg(fd, &msg, 0);
if (rlen <= 0) {
uwsgi_error("uwsgi_send_fds_and_body()/sendmsg()");
goto end;
}
else {
size_t remains = len - rlen;
while(remains > 0) {
char *buf = body + rlen;
ssize_t wlen = write(fd, buf, remains);
if (wlen == 0) goto end;
if (wlen < 0) {
if (uwsgi_is_again()) {
// wait for write
continue;
}
uwsgi_error("uwsgi_send_fds_and_body()/write()");
goto end;
}
rlen += wlen;
remains -= wlen;
}
}
ret = 0;
end:
free(msg_control);
return ret;
}
+7 -9
View File
@@ -277,14 +277,12 @@ static void legions_check_nodes_step2() {
memcpy(best_uuid, node->uuid, 36);
}
// go on if i am not an arbiter
else if (ul->valor > 0) {
// no potential Lord is available, i will propose myself
// but only if i am not suspended...
if (uwsgi_now() > ul->suspended_til) {
best_valor = ul->valor;
memcpy(best_uuid, ul->uuid, 36);
i_am_the_best = 1;
}
// no potential Lord is available, i will propose myself
// but only if i am not suspended...
else if (ul->valor > 0 && uwsgi_now() > ul->suspended_til) {
best_valor = ul->valor;
memcpy(best_uuid, ul->uuid, 36);
i_am_the_best = 1;
}
else {
// empty lord
@@ -572,7 +570,7 @@ static void *legion_loop(void *foobar) {
d_len += d2_len;
if (d_len != uh->pktsize) {
if (d_len != uh->_pktsize) {
uwsgi_log("[uwsgi-legion] invalid packet size\n");
continue;
}
+20 -6
View File
@@ -94,12 +94,12 @@ retry:
#ifndef PTHREAD_MUTEX_ROBUST
#define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP
#endif
if (pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) {
uwsgi_log("unable to set PTHREAD_PRIO_INHERIT\n");
exit(1);
}
if (uwsgi_pthread_robust_mutexes_enabled) {
if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST)) {
if (pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) {
uwsgi_log("unable to set PTHREAD_PRIO_INHERIT\n");
exit(1);
}
if (pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST)) {
uwsgi_log("unable to make the mutex 'robust'\n");
exit(1);
}
@@ -161,7 +161,7 @@ void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
#ifdef EOWNERDEAD
if (pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr) == EOWNERDEAD) {
uwsgi_log("[deadlock-detector] a process holding a robust mutex died. recovering...\n");
pthread_mutex_consistent_np((pthread_mutex_t *) uli->lock_ptr);
pthread_mutex_consistent((pthread_mutex_t *) uli->lock_ptr);
}
#else
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
@@ -476,6 +476,20 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
#endif
#ifdef __RUMP__
int semctl(int _0, int _1, int _2, ...) {
return 0;
}
int semget(key_t _0, int _1, int _2) {
return 0;
}
int semop(int _0, struct sembuf * _1, size_t _2) {
return 0;
}
#undef UWSGI_LOCK_ENGINE_NAME
#define UWSGI_LOCK_ENGINE_NAME "fake"
#endif
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
// used by ftok
+22 -10
View File
@@ -3,6 +3,7 @@
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
#include <sys/user.h>
#include <sys/sysctl.h>
#include <kvm.h>
#elif defined(__sun__)
/* Terrible Hack !!! */
@@ -13,10 +14,6 @@
#define _FILE_OFFSET_BITS 64
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#endif
#ifdef __DragonFly__
#include <uwsgi.h>
#endif
@@ -294,8 +291,8 @@ void logto(char *logfile) {
uwsgi.logfile = logfile;
if (uwsgi.chmod_logfile_value) {
if (chmod(uwsgi.logfile, uwsgi.chmod_logfile_value)) {
uwsgi_error("chmod()");
if (fchmod(fd, uwsgi.chmod_logfile_value)) {
uwsgi_error("fchmod()");
}
}
}
@@ -715,12 +712,12 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
}
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %llu %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh->pktsize,
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %llu bytes} [%.*s] %.*s %.*s => generated %llu bytes in %llu %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, (unsigned long long) wsgi_req->len,
24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
// not enough space for logging the request, just log a (safe) minimal message
if (rlen > 4096) {
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] 0.0.0.0 () {%d vars in %d bytes} [%.*s] - - => generated %llu bytes in %llu %s%s(- %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->var_cnt, wsgi_req->uh->pktsize,
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] 0.0.0.0 () {%d vars in %llu bytes} [%.*s] - - => generated %llu bytes in %llu %s%s(- %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->var_cnt, (unsigned long long) wsgi_req->len,
24, time_request, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
// argh, last resort, truncate it
if (rlen > 4096) {
@@ -751,10 +748,11 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
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;
@@ -1215,7 +1213,7 @@ static ssize_t uwsgi_lf_rssM(struct wsgi_request * wsgi_req, char **buf) {
}
static ssize_t uwsgi_lf_pktsize(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->uh->pktsize);
*buf = uwsgi_num2str(wsgi_req->len);
return strlen(*buf);
}
@@ -1514,6 +1512,7 @@ static void *logger_thread_loop(void *noarg) {
if (uwsgi.req_log_master) {
logpoll[1].events = POLLIN;
logpoll[1].fd = uwsgi.shared->worker_req_log_pipe[0];
logpolls++;
}
@@ -1553,6 +1552,19 @@ void uwsgi_threaded_logger_spawn() {
}
}
void uwsgi_threaded_logger_worker_spawn() {
pthread_t logger_thread;
pthread_mutex_init(&uwsgi.threaded_logger_lock, NULL);
uwsgi.log_master_buf = uwsgi_malloc(uwsgi.log_master_bufsize);
if (pthread_create(&logger_thread, NULL, logger_thread_loop, NULL)) {
uwsgi_error_safe("uwsgi_threaded_logger_worker_spawn()/pthread_create()");
exit(1);
}
}
void uwsgi_register_log_encoder(char *name, char *(*func)(struct uwsgi_log_encoder *, char *, size_t, size_t *)) {
struct uwsgi_log_encoder *old_ule = NULL, *ule = uwsgi.log_encoders;
+56 -18
View File
@@ -2,6 +2,33 @@
extern struct uwsgi_server uwsgi;
static void master_check_processes() {
// run the function, only if required
if (!uwsgi.die_on_no_workers) return;
int alive_processes = 0;
int dead_processes = 0;
int i;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
alive_processes++;
}
else {
dead_processes++;
}
}
if (uwsgi.die_on_no_workers) {
if (!alive_processes) {
uwsgi_log_verbose("no more processes running, auto-killing ...\n");
exit(1);
// never here;
}
}
}
void uwsgi_update_load_counters() {
int i;
@@ -258,17 +285,18 @@ static void master_check_listen_queue() {
if (uwsgi_sock->queue > backlog) {
backlog = uwsgi_sock->queue;
}
if (uwsgi_sock->queue > 0 && uwsgi_sock->queue >= uwsgi_sock->max_queue) {
uwsgi_log_verbose("*** uWSGI listen queue of socket \"%s\" (fd: %d) full !!! (%llu/%llu) ***\n", uwsgi_sock->name, uwsgi_sock->fd, (unsigned long long) uwsgi_sock->queue, (unsigned long long) uwsgi_sock->max_queue);
}
if (uwsgi.alarm_backlog) {
char buf[1024];
int ret = snprintf(buf, 1024, "listen queue of socket \"%s\" (fd: %d) full !!! (%llu/%llu)", uwsgi_sock->name, uwsgi_sock->fd, (unsigned long long) uwsgi_sock->queue, (unsigned long long) uwsgi_sock->max_queue);
if (ret > 0 && ret < 1024) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.alarm_backlog) {
uwsgi_alarm_trigger(usl->value, buf, ret);
if (uwsgi.alarm_backlog) {
char buf[1024];
int ret = snprintf(buf, 1024, "listen queue of socket \"%s\" (fd: %d) full !!! (%llu/%llu)", uwsgi_sock->name, uwsgi_sock->fd, (unsigned long long) uwsgi_sock->queue, (unsigned long long) uwsgi_sock->max_queue);
if (ret > 0 && ret < 1024) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.alarm_backlog) {
uwsgi_alarm_trigger(usl->value, buf, ret);
}
}
}
}
@@ -333,14 +361,10 @@ int master_loop(char **argv, char **environ) {
uwsgi_unix_signal(SIGTSTP, suspend_resume_them_all);
uwsgi_unix_signal(SIGHUP, grace_them_all);
if (uwsgi.die_on_term) {
uwsgi_unix_signal(SIGTERM, kill_them_all);
uwsgi_unix_signal(SIGQUIT, reap_them_all);
}
else {
uwsgi_unix_signal(SIGTERM, reap_them_all);
uwsgi_unix_signal(SIGQUIT, kill_them_all);
}
uwsgi_unix_signal(SIGTERM, kill_them_all);
uwsgi_unix_signal(SIGQUIT, reap_them_all);
uwsgi_unix_signal(SIGINT, kill_them_all);
uwsgi_unix_signal(SIGUSR1, stats);
@@ -646,6 +670,13 @@ int master_loop(char **argv, char **environ) {
return 0;
}
// spooler cheap management
if (uwsgi.spooler_cheap) {
if ((uwsgi.master_cycles % uwsgi.spooler_frequency) == 0) {
uwsgi_spooler_cheap_check();
}
}
// check if someone is dead
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
@@ -731,6 +762,8 @@ int master_loop(char **argv, char **environ) {
// update load counter
uwsgi_update_load_counters();
master_check_processes();
// check uwsgi-cron table
if (ushared->cron_cnt) {
@@ -861,7 +894,10 @@ int master_loop(char **argv, char **environ) {
if (touched) {
uwsgi_log_verbose("*** %s has been touched... reloading daemon \"%s\" (pid: %d) !!! ***\n", touched, ud->command, (int) ud->pid);
if (kill(-ud->pid, ud->stop_signal)) {
uwsgi_error("[uwsgi-daemon/touch] kill()");
// killing process group failed, try to kill by process id
if (kill(ud->pid, ud->stop_signal)) {
uwsgi_error("[uwsgi-daemon/touch] kill()");
}
}
}
}
@@ -964,7 +1000,9 @@ next:
// ok a worker died...
uwsgi.workers[thewid].pid = 0;
// only to be safe :P
uwsgi.workers[thewid].harakiri = 0;
for(i=0;i<uwsgi.cores;i++) {
uwsgi.workers[thewid].cores[i].harakiri = 0;
}
// ok, if we are reloading or dying, just continue the master loop
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
+48 -16
View File
@@ -39,6 +39,8 @@ int uwsgi_master_check_reload(char **argv) {
// check for chain reload
void uwsgi_master_check_chain() {
static time_t last_check = 0;
if (!uwsgi.status.chain_reloading) return;
// we need to ensure the previous worker (if alive) is accepting new requests
@@ -49,7 +51,11 @@ void uwsgi_master_check_chain() {
if (previous_worker->pid > 0 && !previous_worker->cheaped) {
// the worker has been respawned but it is still not ready
if (previous_worker->accepting == 0) {
uwsgi_log_verbose("chain is still waiting for worker %d...\n", uwsgi.status.chain_reloading-1);
time_t now = uwsgi_now();
if (now != last_check) {
uwsgi_log_verbose("chain is still waiting for worker %d...\n", uwsgi.status.chain_reloading-1);
last_check = now;
}
return;
}
}
@@ -138,12 +144,25 @@ void uwsgi_master_check_idle() {
uwsgi.workers[i].cheaped = 1;
if (uwsgi.workers[i].pid == 0)
continue;
// first send SIGINT
kill(uwsgi.workers[i].pid, SIGINT);
// and start waiting upto 3 seconds
int j;
for(j=0;j<3;j++) {
sleep(1);
int ret = waitpid(uwsgi.workers[i].pid, &waitpid_status, WNOHANG);
if (ret == 0) continue;
if (ret == (int) uwsgi.workers[i].pid) goto done;
// on error, directly send SIGKILL
break;
}
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
if (errno != ECHILD)
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
}
else {
done:
uwsgi.workers[i].pid = 0;
uwsgi.workers[i].rss_size = 0;
uwsgi.workers[i].vsz_size = 0;
@@ -157,21 +176,27 @@ void uwsgi_master_check_idle() {
}
int uwsgi_master_check_workers_deadline() {
int i;
int i,j;
int ret = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
/* first check for harakiri */
if (uwsgi.workers[i].harakiri > 0) {
if (uwsgi.workers[i].harakiri < (time_t) uwsgi.current_time) {
trigger_harakiri(i);
ret = 1;
for(j=0;j<uwsgi.cores;j++) {
/* first check for harakiri */
if (uwsgi.workers[i].cores[j].harakiri > 0) {
if (uwsgi.workers[i].cores[j].harakiri < (time_t) uwsgi.current_time) {
uwsgi_log_verbose("HARAKIRI triggered by worker %d core %d !!!\n", i, j);
trigger_harakiri(i);
ret = 1;
break;
}
}
}
/* then user-defined harakiri */
if (uwsgi.workers[i].user_harakiri > 0) {
if (uwsgi.workers[i].user_harakiri < (time_t) uwsgi.current_time) {
trigger_harakiri(i);
ret = 1;
/* then user-defined harakiri */
if (uwsgi.workers[i].cores[j].user_harakiri > 0) {
uwsgi_log_verbose("HARAKIRI (user) triggered by worker %d core %d !!!\n", i, j);
if (uwsgi.workers[i].cores[j].user_harakiri < (time_t) uwsgi.current_time) {
trigger_harakiri(i);
ret = 1;
break;
}
}
}
// then for evil memory checkers
@@ -283,9 +308,15 @@ int uwsgi_master_check_spoolers_death(int diedpid) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
if (uspool->pid > 0 && diedpid == uspool->pid) {
uwsgi_log("OOOPS the spooler is no more...trying respawn...\n");
uspool->respawned++;
uspool->pid = spooler_start(uspool);
if (uwsgi.spooler_cheap) {
uwsgi_log_verbose("spooler %s ended\n", uspool->dir);
uspool->pid = 0;
}
else {
uwsgi_log("OOOPS the spooler is no more...trying respawn...\n");
uspool->respawned++;
uspool->pid = spooler_start(uspool);
}
return -1;
}
uspool = uspool->next;
@@ -335,6 +366,7 @@ int uwsgi_master_check_daemons_death(int diedpid) {
int uwsgi_worker_is_busy(int wid) {
int i;
if (uwsgi.workers[uwsgi.mywid].sig) return 1;
for(i=0;i<uwsgi.cores;i++) {
if (uwsgi.workers[wid].cores[i].in_request) {
return 1;
+4 -11
View File
@@ -45,7 +45,7 @@ int uwsgi_master_manage_events(int interesting_fd) {
// emperor event ?
if (uwsgi.has_emperor) {
if (uwsgi.emperor_fd_proxy > -1 && interesting_fd == uwsgi.emperor_fd_proxy) {
uwsgi_master_manage_emperor_proxy();
uwsgi_master_manage_emperor_proxy(uwsgi.emperor_fd_proxy, uwsgi.emperor_fd, uwsgi.emperor_fd_config, -1);
return 0;
}
@@ -118,16 +118,9 @@ int uwsgi_master_manage_events(int interesting_fd) {
else {
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
}
if (uwsgi.die_on_term) {
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
else {
uwsgi_block_signal(SIGTERM);
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
if (usl->custom2 > 8) free(tmp);
return 0;
}
+84 -7
View File
@@ -162,6 +162,7 @@ int uwsgi_calc_cheaper(void) {
ignore_algo = 1;
}
uwsgi.cheaper_fifo_delta = 0;
goto safe;
}
// if cheaper limits wants to change worker count, then skip cheaper algo
@@ -172,6 +173,7 @@ int uwsgi_calc_cheaper(void) {
needed_workers = 0;
}
safe:
if (needed_workers > 0) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
@@ -219,7 +221,7 @@ int uwsgi_cheaper_algo_manual(int can_spawn) {
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
when all of the workers are busy, the overload_count is incremented.
as soon as overload_count is higher than uwsgi.cheaper_overload (--cheaper-overload options)
as soon as overload_count reaches to uwsgi.cheaper_overload (--cheaper-overload options)
at most cheaper_step (default to 1) new workers are spawned.
when at least one worker is free, the overload_count is decremented and the idle_count is incremented.
@@ -273,7 +275,7 @@ int uwsgi_cheaper_algo_spare(int can_spawn) {
healthy:
// are we overloaded ?
if (can_spawn && overload_count > uwsgi.cheaper_overload) {
if (can_spawn && overload_count >= uwsgi.cheaper_overload) {
#ifdef UWSGI_DEBUG
uwsgi_log("overloaded !!!\n");
@@ -331,6 +333,72 @@ healthy:
}
/*
-- Cheaper, spare2 algorithm, for large workload --
This algorithm is very similar to spare, but more suited for higher workload.
This algorithm increase workers *before* overloaded, and decrease workers slowly.
This algorithm uses these options: chaper, cheaper-initial, cheaper-step and cheaper-idle.
* When number of idle workers is smaller than cheaper count, increase
min(cheaper-step, cheaper - idle workers) workers.
* When number of idle workers is larger than cheaper count, increase idle_count.
* When idle_count >= cheaper-idle, decrease worker.
*/
int uwsgi_cheaper_algo_spare2(int can_spawn) {
static int idle_count = 0;
int i, idle_workers, busy_workers, cheaped_workers;
// count the number of idle and busy workers
idle_workers = busy_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
if (uwsgi_worker_is_busy(i) == 1) {
busy_workers++;
} else {
idle_workers++;
}
}
}
cheaped_workers = uwsgi.numproc - (idle_workers + busy_workers);
#ifdef UWSGI_DEBUG
uwsgi_log("cheaper-spare2: idle=%d, busy=%d, cheaped=%d, idle_count=%d\n",
idle_workers, busy_workers, cheaped_workers, idle_count);
#endif
// should we increase workers?
if (idle_workers < uwsgi.cheaper_count) {
int spawn;
idle_count = 0;
if (!can_spawn)
return 0;
spawn = uwsgi.cheaper_count - idle_workers;
if (spawn > cheaped_workers)
spawn = cheaped_workers;
if (spawn > uwsgi.cheaper_step)
spawn = uwsgi.cheaper_step;
return spawn;
}
if (idle_workers == uwsgi.cheaper_count) {
idle_count = 0;
return 0;
}
// decrease workers
idle_count++;
if (idle_count < uwsgi.cheaper_idle)
return 0;
idle_count = 0;
return -1;
}
/*
@@ -388,6 +456,8 @@ void uwsgi_reload(char **argv) {
int i;
int waitpid_status;
if (uwsgi.new_argv) argv = uwsgi.new_argv;
if (!uwsgi.master_is_reforked) {
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
@@ -630,7 +700,7 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
}
int uwsgi_respawn_worker(int wid) {
int i;
int respawns = uwsgi.workers[wid].respawn_count;
// the workers is not accepting (obviously)
uwsgi.workers[wid].accepting = 0;
@@ -639,8 +709,10 @@ int uwsgi_respawn_worker(int wid) {
// ... same for update time
uwsgi.workers[wid].last_spawn = uwsgi.current_time;
// ... and memory/harakiri
uwsgi.workers[wid].harakiri = 0;
uwsgi.workers[wid].user_harakiri = 0;
for(i=0;i<uwsgi.cores;i++) {
uwsgi.workers[wid].cores[i].harakiri = 0;
uwsgi.workers[wid].cores[i].user_harakiri = 0;
}
uwsgi.workers[wid].pending_harakiri = 0;
uwsgi.workers[wid].rss_size = 0;
uwsgi.workers[wid].vsz_size = 0;
@@ -658,8 +730,6 @@ int uwsgi_respawn_worker(int wid) {
// this is required for various checks
uwsgi.workers[wid].delta_requests = 0;
int i;
if (uwsgi.threaded_logger) {
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
}
@@ -702,6 +772,7 @@ int uwsgi_respawn_worker(int wid) {
for(i=0;i<uwsgi.cores;i++) {
uwsgi.workers[uwsgi.mywid].cores[i].in_request = 0;
memset(&uwsgi.workers[uwsgi.mywid].cores[i].req, 0, sizeof(struct wsgi_request));
memset(uwsgi.workers[uwsgi.mywid].cores[i].buffer, 0, sizeof(struct uwsgi_header));
}
uwsgi_fixup_fds(wid, 0, NULL);
@@ -718,6 +789,10 @@ int uwsgi_respawn_worker(int wid) {
}
}
if (uwsgi.threaded_logger) {
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
}
return 1;
}
else if (pid < 1) {
@@ -1861,3 +1936,5 @@ void uwsgi_dump_worker(int wid, char *msg) {
}
uwsgi_log_verbose("%s !!! end of worker %d status !!!\n",msg, wid);
}
/* vim: set ts=8 sts=0 sw=0 noexpandtab : */
+2 -2
View File
@@ -198,7 +198,7 @@ void uwsgi_mule_handler() {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
if (uwsgi_signal_handler(NULL, uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
}
}
@@ -362,7 +362,7 @@ retry:
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
if (uwsgi_signal_handler(NULL, uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
}
// set the error condition
+3
View File
@@ -613,6 +613,9 @@ int uwsgi_offload_run(struct wsgi_request *wsgi_req, struct uwsgi_offload_reques
if (uor->takeover) {
wsgi_req->fd_closed = 1;
// avoid edge-triggered mode
if (wsgi_req->socket->retry)
wsgi_req->socket->retry[wsgi_req->async_id] = 0;
}
if (uwsgi_offload_enqueue(wsgi_req, uor)) {
+11 -11
View File
@@ -46,10 +46,10 @@ int uwsgi_read_response(int fd, struct uwsgi_header *uh, int timeout, char **buf
break;
}
if (buf && uh->pktsize > 0) {
if (buf && uh->_pktsize > 0) {
if (*buf == NULL)
*buf = uwsgi_malloc(uh->pktsize);
remains = uh->pktsize;
*buf = uwsgi_malloc(uh->_pktsize);
remains = uh->_pktsize;
ptr = *buf;
ret = -1;
while (remains > 0) {
@@ -578,7 +578,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
struct uwsgi_dyn_dict *udd;
ptrbuf = buffer;
bufferend = ptrbuf + wsgi_req->uh->pktsize;
bufferend = ptrbuf + wsgi_req->len;
int i;
/* set an HTTP 500 status as default */
@@ -715,7 +715,7 @@ next:
}
if (uwsgi.manage_script_name) {
if (uwsgi_apps_cnt > 0 && wsgi_req->path_info_len > 1 && wsgi_req->path_info_pos != -1) {
if (uwsgi_apps_cnt > 0 && wsgi_req->path_info_len >= 1 && wsgi_req->path_info_pos != -1) {
// starts with 1 as the 0 app is the default (/) one
int best_found = 0;
char *orig_path_info = wsgi_req->path_info;
@@ -1050,7 +1050,7 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
}
}
if ((wsgi_req->uh->pktsize + (2 + keylen + 2 + vallen)) > uwsgi.buffer_size) {
if ((wsgi_req->len + (2 + keylen + 2 + vallen)) > uwsgi.buffer_size) {
uwsgi_log("not enough buffer space to add %.*s variable, consider increasing it with the --buffer-size option\n", keylen, key);
return NULL;
}
@@ -1060,7 +1060,7 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
return NULL;
}
char *ptr = wsgi_req->buffer + wsgi_req->uh->pktsize;
char *ptr = wsgi_req->buffer + wsgi_req->len;
*ptr++ = (uint8_t) (keylen & 0xff);
*ptr++ = (uint8_t) ((keylen >> 8) & 0xff);
@@ -1081,7 +1081,7 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = vallen;
wsgi_req->var_cnt++;
wsgi_req->uh->pktsize += (2 + keylen + 2 + vallen);
wsgi_req->len += (2 + keylen + 2 + vallen);
return ptr;
}
@@ -1106,7 +1106,7 @@ int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *i
wsgi_req->path_info_len += need_slash + index_len;
// 2 + 9 + 2
if ((wsgi_req->uh->pktsize + (13 + wsgi_req->path_info_len)) > uwsgi.buffer_size) {
if ((wsgi_req->len + (13 + wsgi_req->path_info_len)) > uwsgi.buffer_size) {
uwsgi_log("not enough buffer space to transform the PATH_INFO variable, consider increasing it with the --buffer-size option\n");
return -1;
}
@@ -1117,7 +1117,7 @@ int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *i
}
uint16_t keylen = 9;
char *ptr = wsgi_req->buffer + wsgi_req->uh->pktsize;
char *ptr = wsgi_req->buffer + wsgi_req->len;
*ptr++ = (uint8_t) (keylen & 0xff);
*ptr++ = (uint8_t) ((keylen >> 8) & 0xff);
@@ -1143,7 +1143,7 @@ int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *i
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = wsgi_req->path_info_len;
wsgi_req->var_cnt++;
wsgi_req->uh->pktsize += 13 + wsgi_req->path_info_len;
wsgi_req->len += 13 + wsgi_req->path_info_len;
wsgi_req->path_info = new_path_info;
return 0;
+2 -2
View File
@@ -477,7 +477,7 @@ int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
while (remains > 0) {
if (uwsgi.harakiri_options.workers > 0) {
inc_harakiri(uwsgi.harakiri_options.workers);
inc_harakiri(wsgi_req, uwsgi.harakiri_options.workers);
}
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, ptr, remains);
@@ -551,7 +551,7 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
// during post buffering we need to constantly reset the harakiri
if (uwsgi.harakiri_options.workers > 0) {
inc_harakiri(uwsgi.harakiri_options.workers);
inc_harakiri(wsgi_req, uwsgi.harakiri_options.workers);
}
// we use the already available post buffering buffer to read chunks....
+98 -2
View File
@@ -493,7 +493,7 @@ done:
r = r->next;
}
uwsgi_log("unable to register route \"%s\"\n", value);
uwsgi_log("unable to register route \"%s\". Missing router for: \"%s\"\n", value, command);
exit(1);
}
@@ -702,7 +702,7 @@ static int uwsgi_router_simple_math_divide(struct uwsgi_route *ur, char *arg) {
// harakiri router
static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
if (route->custom > 0) {
set_user_harakiri(route->custom);
set_user_harakiri(wsgi_req, route->custom);
}
return UWSGI_ROUTE_NEXT;
}
@@ -756,6 +756,27 @@ static int uwsgi_router_fixcl(struct uwsgi_route *ur, char *arg) {
return 0;
}
// force content length
static int transform_forcecl(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) ut->chunk->pos);
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
wsgi_req->write_errors++;
return -1;
}
// do not check for errors !!!
uwsgi_response_add_header_force(wsgi_req, "Content-Length", 14, buf, ret);
return 0;
}
static int uwsgi_router_forcecl_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
uwsgi_add_transformation(wsgi_req, transform_forcecl, NULL);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_forcecl(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_forcecl_func;
return 0;
}
// log route
static int uwsgi_router_log_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -1194,6 +1215,27 @@ static int uwsgi_router_setpathinfo(struct uwsgi_route *ur, char *arg) {
return 0;
}
// fixpathinfo route
static int uwsgi_router_fixpathinfo_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
if (wsgi_req->script_name_len == 0)
return UWSGI_ROUTE_NEXT;
char *ptr = uwsgi_req_append(wsgi_req, "PATH_INFO", 9, wsgi_req->path_info+wsgi_req->script_name_len, wsgi_req->path_info_len - wsgi_req->script_name_len);
if (!ptr) {
return UWSGI_ROUTE_BREAK;
}
wsgi_req->path_info = wsgi_req->path_info+wsgi_req->script_name_len;
wsgi_req->path_info_len = wsgi_req->path_info_len - wsgi_req->script_name_len;
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_fixpathinfo(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_fixpathinfo_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setscheme route
static int uwsgi_router_setscheme_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
@@ -1757,6 +1799,10 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
ret = uwsgi_64bit2str(wsgi_req->response_size);
*vallen = strlen(ret);
}
else if (!uwsgi_strncmp(key, keylen, "sor", 3)) {
ret = uwsgi_64bit2str(wsgi_req->start_of_request);
*vallen = strlen(ret);
}
return ret;
}
@@ -1793,6 +1839,10 @@ static char *uwsgi_route_var_time(struct wsgi_request *wsgi_req, char *key, uint
ret = uwsgi_num2str(uwsgi_now());
*vallen = strlen(ret);
}
else if (!uwsgi_strncmp(key, keylen, "micros", 6)) {
ret = uwsgi_64bit2str(uwsgi_micros());
*vallen = strlen(ret);
}
return ret;
}
@@ -1819,6 +1869,32 @@ static char *uwsgi_route_var_hex(struct wsgi_request *wsgi_req, char *key, uint1
return ret;
}
static char *uwsgi_route_var_upper(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, vallen);
if (var_value) {
ret = uwsgi_malloc((size_t) *vallen);
size_t i;
for (i = 0; i < *vallen; i++) {
ret[i] = toupper((int) var_value[i]);
}
}
return ret;
}
static char *uwsgi_route_var_lower(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, vallen);
if (var_value) {
ret = uwsgi_malloc((size_t) *vallen);
size_t i;
for (i = 0; i < *vallen; i++) {
ret[i] = tolower((int) var_value[i]);
}
}
return ret;
}
// register embedded routers
void uwsgi_register_embedded_routers() {
uwsgi_register_router("continue", uwsgi_router_continue);
@@ -1850,6 +1926,7 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("seturi", uwsgi_router_seturi);
uwsgi_register_router("setremoteaddr", uwsgi_router_setremoteaddr);
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
uwsgi_register_router("fixpathinfo", uwsgi_router_fixpathinfo);
uwsgi_register_router("setdocroot", uwsgi_router_setdocroot);
uwsgi_register_router("setscheme", uwsgi_router_setscheme);
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
@@ -1865,6 +1942,7 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("flush", uwsgi_router_flush);
uwsgi_register_router("fixcl", uwsgi_router_fixcl);
uwsgi_register_router("forcecl", uwsgi_router_forcecl);
uwsgi_register_router("harakiri", uwsgi_router_harakiri);
@@ -1911,6 +1989,10 @@ void uwsgi_register_embedded_routers() {
urv = uwsgi_register_route_var("hex", uwsgi_route_var_hex);
urv->need_free = 1;
urv = uwsgi_register_route_var("upper", uwsgi_route_var_upper);
urv->need_free = 1;
urv = uwsgi_register_route_var("lower", uwsgi_route_var_lower);
urv->need_free = 1;
}
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
@@ -2045,5 +2127,19 @@ next4:
usl->custom2 = strlen(space+1);
uwsgi_log("collecting header %.*s to var %s\n", usl->custom, usl->value, usl->custom_ptr);
}
uwsgi_foreach(usl, uwsgi.pull_headers) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid pull header syntax, must be <header> <var>\n");
exit(1);
}
*space = 0;
usl->custom = strlen(usl->value);
*space = ' ';
usl->custom_ptr = space+1;
usl->custom2 = strlen(space+1);
uwsgi_log("pulling header %.*s to var %s\n", usl->custom, usl->value, usl->custom_ptr);
}
}
#endif
+6 -1
View File
@@ -7,6 +7,11 @@ int uwsgi_register_rpc(char *name, struct uwsgi_plugin *plugin, uint8_t args, vo
struct uwsgi_rpc *urpc;
int ret = -1;
if (!uwsgi.workers || !uwsgi.shared || !uwsgi.rpc_table_lock) {
uwsgi_log("RPC subsystem still not initialized\n");
return -1;
}
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
uwsgi_log("only the master and the workers can register RPC functions\n");
return -1;
@@ -140,7 +145,7 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
// set the uwsgi header
uh = (struct uwsgi_header *) buffer;
uh->modifier1 = 173;
uh->pktsize = buffer_size;
uh->_pktsize = buffer_size;
uh->modifier2 = 0;
// add func to the array
+9 -9
View File
@@ -280,8 +280,8 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_fd(int fd, uint64_t len, off_t of
}
uwsgi.sharedareas[id]->id = id;
uwsgi.sharedareas[id]->fd = fd;
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
uwsgi.sharedareas[id]->pages = len / (size_t) uwsgi.page_size;
if (len % (size_t) uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
uwsgi.sharedareas[id]->max_pos = len-1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
@@ -292,12 +292,12 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_fd(int fd, uint64_t len, off_t of
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) {
int id = uwsgi_sharedarea_new_id();
uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1));
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size;
uwsgi.sharedareas[id] = uwsgi_calloc_shared((size_t)uwsgi.page_size * (size_t)(pages + 1));
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + (size_t) uwsgi.page_size;
uwsgi.sharedareas[id]->id = id;
uwsgi.sharedareas[id]->fd = -1;
uwsgi.sharedareas[id]->pages = pages;
uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1;
uwsgi.sharedareas[id]->max_pos = ((size_t)uwsgi.page_size * (size_t)pages) -1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
free(id_str);
@@ -310,8 +310,8 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) {
uwsgi.sharedareas[id]->area = area;
uwsgi.sharedareas[id]->id = id;
uwsgi.sharedareas[id]->fd = -1;
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
uwsgi.sharedareas[id]->pages = len / (size_t) uwsgi.page_size;
if (len % (size_t) uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
uwsgi.sharedareas[id]->max_pos = len-1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
@@ -348,8 +348,8 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
else {
len = uwsgi_n64(s_size);
}
pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) pages++;
pages = len / (size_t) uwsgi.page_size;
if (len % (size_t) uwsgi.page_size != 0) pages++;
}
if (s_offset) {
+27 -16
View File
@@ -2,7 +2,7 @@
extern struct uwsgi_server uwsgi;
int uwsgi_signal_handler(uint8_t sig) {
int uwsgi_signal_handler(struct wsgi_request *wsgi_req, uint8_t sig) {
struct uwsgi_signal_entry *use = NULL;
@@ -41,12 +41,12 @@ int uwsgi_signal_handler(uint8_t sig) {
// set harakiri here (if required and if i am a worker)
if (uwsgi.mywid > 0) {
if (uwsgi.mywid > 0 && wsgi_req) {
uwsgi.workers[uwsgi.mywid].sig = 1;
uwsgi.workers[uwsgi.mywid].signum = sig;
uwsgi.workers[uwsgi.mywid].signals++;
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
set_harakiri(wsgi_req, uwsgi.harakiri_options.workers);
}
}
else if (uwsgi.muleid > 0) {
@@ -65,10 +65,10 @@ int uwsgi_signal_handler(uint8_t sig) {
int ret = uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
if (uwsgi.mywid > 0) {
if (uwsgi.mywid > 0 && wsgi_req) {
uwsgi.workers[uwsgi.mywid].sig = 0;
if (uwsgi.workers[uwsgi.mywid].harakiri > 0) {
set_harakiri(0);
if (uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].harakiri > 0) {
set_harakiri(wsgi_req, 0);
}
}
else if (uwsgi.muleid > 0) {
@@ -266,7 +266,7 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
struct uwsgi_header uh;
uh.modifier1 = 110;
uh.pktsize = 0;
uh._pktsize = 0;
uh.modifier2 = sig;
int fd = uwsgi_connect(addr, 0, 1);
@@ -331,6 +331,16 @@ void uwsgi_route_signal(uint8_t sig) {
}
}
}
// send to al lactive workers
else if (!strcmp(use->receiver, "active-workers")) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0 && !uwsgi.workers[i].cheaped && !uwsgi.workers[i].suspended) {
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
}
}
}
// route to specific worker
else if (!strncmp(use->receiver, "worker", 6)) {
i = atoi(use->receiver + 6);
@@ -405,7 +415,7 @@ void uwsgi_route_signal(uint8_t sig) {
}
int uwsgi_signal_wait(int signum) {
int uwsgi_signal_wait(struct wsgi_request *wsgi_req, int signum) {
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
@@ -430,7 +440,7 @@ cycle:
uwsgi_error("read()");
}
else {
(void) uwsgi_signal_handler(uwsgi_signal);
(void) uwsgi_signal_handler(wsgi_req, uwsgi_signal);
if (wait_for_specific_signal) {
if (signum != uwsgi_signal)
goto cycle;
@@ -443,7 +453,7 @@ cycle:
uwsgi_error("read()");
}
else {
(void) uwsgi_signal_handler(uwsgi_signal);
(void) uwsgi_signal_handler(wsgi_req, uwsgi_signal);
if (wait_for_specific_signal) {
if (signum != uwsgi_signal)
goto cycle;
@@ -457,8 +467,7 @@ cycle:
return received_signal;
}
void uwsgi_receive_signal(int fd, char *name, int id) {
int uwsgi_receive_signal(struct wsgi_request *wsgi_req, int fd, char *name, int id) {
uint8_t uwsgi_signal;
ssize_t ret = read(fd, &uwsgi_signal, 1);
@@ -474,16 +483,18 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
if (uwsgi_signal_handler(wsgi_req, uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on %s %d\n", uwsgi_signal, name, id);
}
return 1;
}
return;
return 0;
destroy:
// better to kill the whole worker...
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: I will kill myself!!!\n", name, id);
end_me(0);
// never here
return 0;
}
+23 -2
View File
@@ -51,6 +51,8 @@ char *uwsgi_getsockname(int fd) {
if (!getsockname(fd, gsa.sa, &socket_type_len)) {
if (gsa.sa->sa_family == AF_UNIX) {
// unnamed socket ?
if (socket_type_len == sizeof(sa_family_t)) return "";
if (usa.sa_un.sun_path[0] == 0) {
return uwsgi_concat2("@", usa.sa_un.sun_path + 1);
}
@@ -189,7 +191,10 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
memset(uws_addr, 0, sizeof(struct sockaddr_un));
serverfd = create_server_socket(AF_UNIX, SOCK_STREAM);
if (serverfd < 0) return -1;
if (serverfd < 0) {
free(uws_addr);
return -1;
}
if (abstract_socket == 0) {
if (unlink(socket_name) != 0 && errno != ENOENT) {
uwsgi_error("error removing unix socket, unlink()");
@@ -707,6 +712,11 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (uwsgi.tcp_fast_open) {
#ifdef TCP_FASTOPEN
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif
if (setsockopt(serverfd, SOL_TCP, TCP_FASTOPEN, (const void *) &uwsgi.tcp_fast_open, sizeof(int)) < 0) {
uwsgi_error("TCP_FASTOPEN setsockopt()");
}
@@ -1246,10 +1256,20 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
}
void uwsgi_close_all_sockets() {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->bound)
close(uwsgi_sock->fd);
uwsgi_sock = uwsgi_sock->next;
}
}
void uwsgi_close_all_unshared_sockets() {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->bound)
if (uwsgi_sock->bound && !uwsgi_sock->shared)
close(uwsgi_sock->fd);
uwsgi_sock = uwsgi_sock->next;
}
@@ -1937,6 +1957,7 @@ void uwsgi_protocols_register() {
uwsgi_register_protocol("puwsgi", uwsgi_proto_puwsgi_setup);
uwsgi_register_protocol("http", uwsgi_proto_http_setup);
uwsgi_register_protocol("http11", uwsgi_proto_http11_setup);
#ifdef UWSGI_SSL
uwsgi_register_protocol("suwsgi", uwsgi_proto_suwsgi_setup);
Regular → Executable
+87 -28
View File
@@ -1,11 +1,13 @@
#include "uwsgi.h"
#ifdef __sun__
#include "strings.h"
#endif
extern struct uwsgi_server uwsgi;
static void spooler_readdir(struct uwsgi_spooler *, char *dir);
#ifdef __linux__
static void spooler_scandir(struct uwsgi_spooler *, char *dir);
#endif
static void spooler_manage_task(struct uwsgi_spooler *, char *, char *);
// increment it whenever a signal is raised
@@ -301,9 +303,9 @@ char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len,
struct uwsgi_header uh;
uh.modifier1 = 17;
uh.modifier2 = 0;
uh.pktsize = (uint16_t) len;
uh._pktsize = (uint16_t) len;
#ifdef __BIG_ENDIAN__
uh.pktsize = uwsgi_swap16(uh.pktsize);
uh._pktsize = uwsgi_swap16(uh._pktsize);
#endif
if (write(fd, &uh, 4) != 4) {
@@ -429,8 +431,9 @@ void spooler(struct uwsgi_spooler *uspool) {
// reset the tasks counter
uspool->tasks = 0;
for (;;) {
time_t last_task_managed = 0;
for (;;) {
if (chdir(uspool->dir)) {
uwsgi_error("chdir()");
@@ -438,16 +441,22 @@ void spooler(struct uwsgi_spooler *uspool) {
}
if (uwsgi.spooler_ordered) {
#ifdef __linux__
spooler_scandir(uspool, NULL);
#else
spooler_readdir(uspool, NULL);
#endif
}
else {
spooler_readdir(uspool, NULL);
}
// here we check (if in cheap mode), if the spooler has done its job
if (uwsgi.spooler_cheap) {
if (last_task_managed == uspool->last_task_managed) {
uwsgi_log_verbose("cheaping spooler %s ...\n", uspool->dir);
exit(0);
}
last_task_managed = uspool->last_task_managed;
}
int timeout = uwsgi.shared->spooler_frequency ? uwsgi.shared->spooler_frequency : uwsgi.spooler_frequency;
if (wakeup > 0) {
timeout = 0;
@@ -456,7 +465,15 @@ void spooler(struct uwsgi_spooler *uspool) {
if (event_queue_wait(spooler_event_queue, timeout, &interesting_fd) > 0) {
if (uwsgi.master_process) {
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[1]) {
uwsgi_receive_signal(interesting_fd, "spooler", (int) getpid());
if (uwsgi_receive_signal(NULL, interesting_fd, "spooler", (int) getpid())) {
if (uwsgi.spooler_signal_as_task) {
uspool->tasks++;
if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t) uwsgi.spooler_max_tasks) {
uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
end_me(0);
}
}
}
}
}
}
@@ -471,7 +488,6 @@ void spooler(struct uwsgi_spooler *uspool) {
}
}
#ifdef __linux__
static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
struct dirent **tasklist;
@@ -480,7 +496,11 @@ static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
if (!dir)
dir = uspool->dir;
n = scandir(dir, &tasklist, 0, versionsort);
#ifdef __NetBSD__
n = scandir(dir, &tasklist, NULL, (void *)uwsgi_versionsort);
#else
n = scandir(dir, &tasklist, NULL, uwsgi_versionsort);
#endif
if (n < 0) {
uwsgi_error("scandir()");
return;
@@ -493,7 +513,6 @@ static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
free(tasklist);
}
#endif
static void spooler_readdir(struct uwsgi_spooler *uspool, char *dir) {
@@ -512,7 +531,7 @@ static void spooler_readdir(struct uwsgi_spooler *uspool, char *dir) {
closedir(sdir);
}
else {
uwsgi_error("opendir()");
uwsgi_error("spooler_readdir()/opendir()");
}
}
@@ -532,6 +551,7 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
if (!strncmp("uwsgi_spoolfile_on_", task, 19) || (uwsgi.spooler_ordered && is_a_number(task))) {
struct stat sf_lstat;
if (lstat(task, &sf_lstat)) {
return;
}
@@ -541,26 +561,30 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
return;
}
#ifdef __linux__
if (S_ISDIR(sf_lstat.st_mode) && uwsgi.spooler_ordered) {
if (chdir(task)) {
uwsgi_error("chdir()");
uwsgi_error("spooler_manage_task()/chdir()");
return;
}
#ifdef __UCLIBC__
char *prio_path = uwsgi_malloc(PATH_MAX);
realpath(".", prio_path);
#else
char *prio_path = realpath(".", NULL);
#endif
spooler_scandir(uspool, prio_path);
free(prio_path);
if (chdir(dir)) {
uwsgi_error("chdir()");
uwsgi_error("spooler_manage_task()/chdir()");
}
return;
}
#endif
if (!S_ISREG(sf_lstat.st_mode)) {
return;
}
if (!access(task, R_OK | W_OK)) {
spool_fd = open(task, O_RDWR);
if (spool_fd < 0) {
@@ -581,33 +605,34 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
return;
}
ssize_t rlen = uwsgi_protected_read(spool_fd, &uh, 4);
if (rlen != 4) {
// it could be here for broken file or just opened one
if (rlen < 0)
uwsgi_error("read()");
uwsgi_error("spooler_manage_task()/read()");
uwsgi_protected_close(spool_fd);
return;
}
#ifdef __BIG_ENDIAN__
uh.pktsize = uwsgi_swap16(uh.pktsize);
uh._pktsize = uwsgi_swap16(uh._pktsize);
#endif
if (uwsgi_protected_read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
uwsgi_error("read()");
if (uwsgi_protected_read(spool_fd, spool_buf, uh._pktsize) != uh._pktsize) {
uwsgi_error("spooler_manage_task()/read()");
destroy_spool(dir, task);
uwsgi_protected_close(spool_fd);
return;
}
// body available ?
if (sf_lstat.st_size > (uh.pktsize + 4)) {
body_len = sf_lstat.st_size - (uh.pktsize + 4);
if (sf_lstat.st_size > (uh._pktsize + 4)) {
body_len = sf_lstat.st_size - (uh._pktsize + 4);
body = uwsgi_malloc(body_len);
if ((size_t) uwsgi_protected_read(spool_fd, body, body_len) != body_len) {
uwsgi_error("read()");
uwsgi_error("spooler_manage_task()/read()");
destroy_spool(dir, task);
uwsgi_protected_close(spool_fd);
free(body);
@@ -615,8 +640,10 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
}
}
// now the task is running and should not be waken up
// now the task is running and should not be woken up
uspool->running = 1;
// this is used in cheap mode for making decision about who must die
uspool->last_task_managed = uwsgi_now();
if (!uwsgi.spooler_quiet)
uwsgi_log("[spooler %s pid: %d] managing request %s ...\n", uspool->dir, (int) uwsgi.mypid, task);
@@ -625,7 +652,7 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
// chdir before running the task (if requested)
if (uwsgi.spooler_chdir) {
if (chdir(uwsgi.spooler_chdir)) {
uwsgi_error("chdir()");
uwsgi_error("spooler_manage_task()/chdir()");
}
}
@@ -636,7 +663,7 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
if (uwsgi.harakiri_options.spoolers > 0) {
set_spooler_harakiri(uwsgi.harakiri_options.spoolers);
}
ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
ret = uwsgi.p[i]->spooler(task, spool_buf, uh._pktsize, body, body_len);
if (uwsgi.harakiri_options.spoolers > 0) {
set_spooler_harakiri(0);
}
@@ -683,3 +710,35 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
}
}
}
// this function checks which spooler should be spawned
void uwsgi_spooler_cheap_check() {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
char *last_managed = NULL;
while(uspool) {
// skip already active spoolers
if (uspool->pid > 0) goto next;
// spooler dir names (in multiprocess mode, are ordered, so we can use
// this trick for avoiding spawning multiple processes for the same dir
// in the same cycle
if (!last_managed || strcmp(last_managed, uspool->dir)) {
// unfortunately, reusing readdir/scandir of the spooler is too dungeorus
// as the code is run in the master, let's do a simpler check
struct dirent *dp;
DIR *sdir = opendir(uspool->dir);
if (!sdir) goto next;
while ((dp = readdir(sdir)) != NULL) {
if (strncmp("uwsgi_spoolfile_on_", dp->d_name, 19)) continue;
// a uwsgi_spoolfile_on_* file has been found...
uspool->respawned++;
// spawn a new spooler
uspool->pid = spooler_start(uspool);
last_managed = uspool->dir;
break;
}
closedir(sdir);
}
next:
uspool = uspool->next;
}
}
+19 -1
View File
@@ -30,7 +30,18 @@ void uwsgi_ssl_info_cb(SSL const *ssl, int where, int ret) {
}
int uwsgi_ssl_verify_callback(int ok, X509_STORE_CTX * x509_store) {
return 1;
if (!ok && uwsgi.ssl_verbose) {
char buf[256];
X509 *err_cert;
int depth;
int err;
depth = X509_STORE_CTX_get_error_depth(x509_store);
err_cert = X509_STORE_CTX_get_current_cert(x509_store);
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
err = X509_STORE_CTX_get_error(x509_store);
uwsgi_log("[uwsgi-ssl] client certificate verify error: num=%d:%s:depth=%d:%s\n", err, X509_verify_cert_error_string(err), depth, buf);
}
return ok;
}
int uwsgi_ssl_session_new_cb(SSL *ssl, SSL_SESSION *sess) {
@@ -503,6 +514,13 @@ clear:
}
char *uwsgi_sanitize_cert_filename(char *base, char *key, uint16_t keylen) {
// stop at the first slash if mountpoints are involved
if (uwsgi.subscription_mountpoints) {
char *slash = memchr(key, '/', keylen);
if (slash) {
keylen = slash - key;
}
}
uint16_t i;
char *filename = uwsgi_concat4n(base, strlen(base), "/", 1, key, keylen, ".pem\0", 5);
+16 -14
View File
@@ -167,6 +167,9 @@ static time_t parse_http_date(char *date, uint16_t len) {
}
time_t uwsgi_parse_http_date(char *buf, uint16_t len) {
return parse_http_date(buf, len);
}
int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int mime_type_len, struct stat *st) {
@@ -456,30 +459,29 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
uwsgi_log("[uwsgi-fileserve] file %s found, mimetype %s\n", real_filename, mime_type);
#endif
// static file - don't update avg_rt after request
wsgi_req->do_not_account_avg_rt = 1;
size_t fsize = st->st_size;
if (wsgi_req->range_to) {
fsize = wsgi_req->range_to - wsgi_req->range_from;
if (fsize > (size_t)st->st_size) {
fsize = st->st_size;
}
// security check
if (wsgi_req->range_from > fsize) {
wsgi_req->range_from = 0;
wsgi_req->range_to = 0;
}
else {
// reset in case of inconsistent size
if (wsgi_req->range_from > fsize) {
wsgi_req->range_from = 0;
fsize = 0;
}
else {
fsize -= wsgi_req->range_from;
}
fsize -= wsgi_req->range_from;
}
if (wsgi_req->range_to) {
fsize = (wsgi_req->range_to - wsgi_req->range_from)+1;
if (fsize + wsgi_req->range_from > (size_t) (st->st_size)) {
fsize = st->st_size - wsgi_req->range_from;
}
}
// HTTP status
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
+2 -3
View File
@@ -569,14 +569,13 @@ static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *dat
int uwsgi_stats_dump_vars(struct uwsgi_stats *us, struct uwsgi_core *uc) {
if (!uc->in_request) return 0;
struct uwsgi_header *uh = (struct uwsgi_header *) uc->buffer;
uint16_t pktsize = uh->pktsize;
uint64_t pktsize = uc->req.len;
if (!pktsize) return 0;
char *dst = uwsgi.workers[0].cores[0].buffer;
memcpy(dst, uc->buffer+4, uwsgi.buffer_size);
// ok now check if something changed...
if (!uc->in_request) return 0;
if (uh->pktsize != pktsize) return 0;
if (uc->req.len != pktsize) return 0;
if (memcmp(dst, uc->buffer+4, uwsgi.buffer_size)) return 0;
// nothing changed let's dump vars
int ret = uwsgi_hooked_parse(dst, pktsize, stats_dump_var, us);
+22 -18
View File
@@ -65,16 +65,9 @@ char *uwsgi_lower(char *str, size_t size) {
return str;
}
// check if a string is contained in another one
// check if a char is contained in a string
char *uwsgi_str_contains(char *str, int slen, char what) {
int i;
for (i = 0; i < slen; i++) {
if (str[i] == what) {
return str + i;
}
}
return NULL;
return memchr(str, what, slen);
}
int uwsgi_contains_n(char *s1, size_t s1_len, char *s2, size_t s2_len) {
@@ -126,15 +119,7 @@ int uwsgi_starts_with(char *src, int slen, char *dst, int dlen) {
// unsized check
int uwsgi_startswith(char *src, char *what, int wlen) {
int i;
for (i = 0; i < wlen; i++) {
if (src[i] != what[i])
return -1;
}
return 0;
return memcmp(what, src, wlen);
}
// concatenate strings
@@ -483,3 +468,22 @@ char ** uwsgi_split_quoted(char *what, size_t what_len, char *sep, size_t *rlen)
return ret;
}
char *uwsgi_get_last_char(char *what, char c) {
return strrchr(what, c);
}
// Note by Mathieu Dupuy: memrchr here is better, unfortunately it is not supported
// everywhere. The only safe option looks checking for Linux :(
char *uwsgi_get_last_charn(char *what, size_t len, char c) {
#if defined(__linux__)
return memrchr(what, c, len);
#else
while (len--) {
if (what[len] == c)
return what + len;
}
return NULL;
#endif
}
+415 -162
View File
@@ -20,6 +20,17 @@
extern struct uwsgi_server uwsgi;
char *uwsgi_subscription_algo_name(void *ptr) {
struct uwsgi_string_list *usl = uwsgi.subscription_algos;
while(usl) {
if (usl->custom_ptr == ptr) {
return usl->value;
}
usl = usl->next;
}
return NULL;
}
#ifdef UWSGI_SSL
static void uwsgi_subscription_sni_check(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_req *usr) {
if (usr->sni_key_len > 0 && usr->sni_crt_len > 0) {
@@ -72,6 +83,8 @@ int uwsgi_subscription_credentials_check(struct uwsgi_subscribe_slot *slot, stru
}
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {
int retried = 0;
retry:
if (keylen > 0xff)
return NULL;
@@ -125,136 +138,20 @@ struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slo
break;
}
// if we are here and in mountpoints mode, try the domain only variant
if (uwsgi.subscription_mountpoints && !retried) {
char *slash = memchr(key, '/', keylen);
if (slash) {
keylen = slash - key;
retried = 1;
goto retry;
}
}
return NULL;
}
// least reference count
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_lrc(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node) {
// if node is NULL we are in the second step (in lrc mode we do not use the first step)
if (node)
return NULL;
struct uwsgi_subscribe_node *choosen_node = NULL;
node = current_slot->nodes;
uint64_t min_rc = 0;
while (node) {
if (!node->death_mark) {
if (min_rc == 0 || node->reference < min_rc) {
min_rc = node->reference;
choosen_node = node;
if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->last_requests <= node->last_requests))
break;
}
}
node = node->next;
}
if (choosen_node) {
choosen_node->reference++;
}
return choosen_node;
}
// weighted least reference count
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wlrc(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node) {
// if node is NULL we are in the second step (in wlrc mode we do not use the first step)
if (node)
return NULL;
struct uwsgi_subscribe_node *choosen_node = NULL;
node = current_slot->nodes;
double min_rc = 0;
while (node) {
if (!node->death_mark) {
// node->weight is always >= 1, we can safely use it as divider
double ref = (double) node->reference / (double) node->weight;
double next_node_ref = 0;
if (node->next)
next_node_ref = (double) node->next->reference / (double) node->next->weight;
if (min_rc == 0 || ref < min_rc) {
min_rc = ref;
choosen_node = node;
if (min_rc == 0 && !(node->next && next_node_ref <= ref && node->next->last_requests <= node->last_requests))
break;
}
}
node = node->next;
}
if (choosen_node) {
choosen_node->reference++;
}
return choosen_node;
}
// weighted round robin algo
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wrr(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node) {
// if node is NULL we are in the second step
if (node) {
if (node->death_mark == 0 && node->wrr > 0) {
node->wrr--;
node->reference++;
return node;
}
return NULL;
}
// no wrr > 0 node found, reset them
node = current_slot->nodes;
uint64_t min_weight = 0;
while (node) {
if (!node->death_mark) {
if (min_weight == 0 || node->weight < min_weight)
min_weight = node->weight;
}
node = node->next;
}
// now set wrr
node = current_slot->nodes;
struct uwsgi_subscribe_node *choosen_node = NULL;
while (node) {
if (!node->death_mark) {
node->wrr = node->weight / min_weight;
choosen_node = node;
}
node = node->next;
}
if (choosen_node) {
choosen_node->wrr--;
choosen_node->reference++;
}
return choosen_node;
}
void uwsgi_subscription_set_algo(char *algo) {
if (!algo)
goto wrr;
if (!strcmp(algo, "wrr")) {
uwsgi.subscription_algo = uwsgi_subscription_algo_wrr;
return;
}
if (!strcmp(algo, "lrc")) {
uwsgi.subscription_algo = uwsgi_subscription_algo_lrc;
return;
}
if (!strcmp(algo, "wlrc")) {
uwsgi.subscription_algo = uwsgi_subscription_algo_wlrc;
return;
}
wrr:
uwsgi.subscription_algo = uwsgi_subscription_algo_wrr;
}
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, struct uwsgi_subscription_client *client) {
if (keylen > 0xff)
return NULL;
@@ -287,14 +184,14 @@ struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slo
continue;
}
struct uwsgi_subscribe_node *choosen_node = uwsgi.subscription_algo(current_slot, node);
struct uwsgi_subscribe_node *choosen_node = current_slot->algo(current_slot, node, client);
if (choosen_node)
return choosen_node;
node = node->next;
}
return uwsgi.subscription_algo(current_slot, node);
return current_slot->algo(current_slot, node, client);
}
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, char *val, uint16_t vallen) {
@@ -436,6 +333,10 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
node->cores = usr->cores;
node->load = usr->load;
node->weight = usr->weight;
node->backup_level = usr->backup_level;
if (usr->proto_len > 0) {
node->proto = usr->proto[0];
}
if (!node->weight)
node->weight = 1;
node->last_requests = 0;
@@ -468,6 +369,10 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
node->cores = usr->cores;
node->load = usr->load;
node->weight = usr->weight;
node->backup_level = usr->backup_level;
if (usr->proto_len > 0) {
node->proto = usr->proto[0];
}
node->unix_check = usr->unix_check;
if (!node->weight)
node->weight = 1;
@@ -488,7 +393,7 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
}
node->next = NULL;
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address);
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s (weight: %d, backup: %d)\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, usr->weight, usr->backup_level);
if (node->notify[0]) {
char buf[1024];
int ret = snprintf(buf, 1024, "[subscription ack] %.*s => new node: %.*s", usr->keylen, usr->key, usr->address_len, usr->address);
@@ -539,6 +444,10 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
current_slot->nodes->cores = usr->cores;
current_slot->nodes->load = usr->load;
current_slot->nodes->weight = usr->weight;
current_slot->nodes->backup_level = usr->backup_level;
if (usr->proto_len > 0) {
current_slot->nodes->proto = usr->proto[0];
}
current_slot->nodes->unix_check = usr->unix_check;
if (!current_slot->nodes->weight)
current_slot->nodes->weight = 1;
@@ -570,13 +479,16 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
current_slot->prev = old_slot;
current_slot->next = NULL;
current_slot->algo = usr->algo;
if (!current_slot->algo) current_slot->algo = uwsgi.subscription_algo;
if (!slot[hash_key] || current_slot->prev == NULL) {
slot[hash_key] = current_slot;
}
uwsgi_log("[uwsgi-subscription for pid %d] new pool: %.*s (hash key: %d)\n", (int) uwsgi.mypid, usr->keylen, usr->key, current_slot->hash);
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address);
uwsgi_log("[uwsgi-subscription for pid %d] new pool: %.*s (hash key: %d, algo: %s)\n", (int) uwsgi.mypid, usr->keylen, usr->key, current_slot->hash, uwsgi_subscription_algo_name(current_slot->algo));
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s (weight: %d, backup: %d)\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, usr->weight, usr->backup_level);
if (current_slot->nodes->notify[0]) {
char buf[1024];
@@ -669,6 +581,30 @@ static void send_subscription(int sfd, char *host, char *message, uint16_t messa
close(fd);
}
static int uwsgi_subscription_ub_fix(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *sign) {
#ifdef UWSGI_SSL
if (sign) {
if (uwsgi_buffer_append_keynum(ub, "unix", 4, (uwsgi_now() + (time_t) cmd)))
return -1;
unsigned int signature_len = 0;
char *signature = uwsgi_rsa_sign(sign, ub->buf + 4, ub->pos - 4, &signature_len);
if (signature && signature_len > 0) {
if (uwsgi_buffer_append_keyval(ub, "sign", 4, signature, signature_len)) {
free(signature);
return -1;
}
free(signature);
}
}
#endif
// add uwsgi header
if (uwsgi_buffer_set_uh(ub, 224, cmd)) return -1;
return 0;
}
static struct uwsgi_buffer *uwsgi_subscription_ub(char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign, char *sni_key, char *sni_crt, char *sni_ca) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
@@ -679,6 +615,10 @@ static struct uwsgi_buffer *uwsgi_subscription_ub(char *key, size_t keysize, uin
goto end;
if (uwsgi_buffer_append_keyval(ub, "address", 7, socket_name, strlen(socket_name)))
goto end;
if (uwsgi.subscribe_with_modifier1) {
modifier1 = atoi(uwsgi.subscribe_with_modifier1);
}
if (uwsgi_buffer_append_keynum(ub, "modifier1", 9, modifier1))
goto end;
if (uwsgi_buffer_append_keynum(ub, "modifier2", 9, modifier2))
@@ -720,26 +660,7 @@ static struct uwsgi_buffer *uwsgi_subscription_ub(char *key, size_t keysize, uin
goto end;
}
#ifdef UWSGI_SSL
if (sign) {
if (uwsgi_buffer_append_keynum(ub, "unix", 4, (uwsgi_now() + (time_t) cmd)))
goto end;
unsigned int signature_len = 0;
char *signature = uwsgi_rsa_sign(sign, ub->buf + 4, ub->pos - 4, &signature_len);
if (signature && signature_len > 0) {
if (uwsgi_buffer_append_keyval(ub, "sign", 4, signature, signature_len)) {
free(signature);
goto end;
}
free(signature);
}
}
#endif
// add uwsgi header
if (uwsgi_buffer_set_uh(ub, 224, cmd))
goto end;
if (uwsgi_subscription_ub_fix(ub, modifier1, modifier2, cmd, sign)) goto end;
return ub;
@@ -861,13 +782,6 @@ int uwsgi_no_subscriptions(struct uwsgi_subscribe_slot **slot) {
return 1;
}
struct uwsgi_subscribe_slot **uwsgi_subscription_init_ht() {
if (!uwsgi.subscription_algo) {
uwsgi_subscription_set_algo(NULL);
}
return uwsgi_calloc(sizeof(struct uwsgi_subscription_slot *) * UMAX16);
}
void uwsgi_subscribe(char *subscription, uint8_t cmd) {
size_t subfile_size;
@@ -1014,8 +928,28 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
char *s2_sni_key = NULL;
char *s2_sni_crt = NULL;
char *s2_sni_ca = NULL;
char *s2_proto = NULL;
char *s2_algo = NULL;
char *s2_backup = NULL;
struct uwsgi_buffer *ub = NULL;
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=', "server", &s2_server, "key", &s2_key, "socket", &s2_socket, "addr", &s2_addr, "weight", &s2_weight, "modifier1", &s2_modifier1, "modifier2", &s2_modifier2, "sign", &s2_sign, "check", &s2_check, "sni_key", &s2_sni_key, "sni_crt", &s2_sni_crt, "sni_ca", &s2_sni_ca, NULL)) {
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"server", &s2_server,
"key", &s2_key,
"socket", &s2_socket,
"addr", &s2_addr,
"weight", &s2_weight,
"modifier1", &s2_modifier1,
"modifier2", &s2_modifier2,
"sign", &s2_sign,
"check", &s2_check,
"sni_key", &s2_sni_key,
"sni_crt", &s2_sni_crt,
"sni_ca", &s2_sni_ca,
"proto", &s2_proto,
"algo", &s2_algo,
"backup", &s2_backup,
NULL)) {
return;
}
@@ -1027,8 +961,15 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
goto end;
}
int weight = 1;
int backup = 0;
if (uwsgi.auto_weight) weight = uwsgi.numproc * uwsgi.cores;
if (s2_weight) {
uwsgi.weight = atoi(s2_weight);
weight = atoi(s2_weight);
}
if (s2_backup) {
backup = atoi(s2_backup);
}
if (s2_socket) {
@@ -1052,8 +993,76 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
modifier2 = atoi(s2_modifier2);
}
uwsgi_send_subscription(s2_server, s2_key, strlen(s2_key), modifier1, modifier2, cmd, s2_addr, s2_sign, s2_sni_key, s2_sni_crt, s2_sni_ca);
if (s2_addr == NULL) {
// no socket... no subscription
if (!uwsgi.sockets) goto end;
s2_addr = uwsgi_str(uwsgi.sockets->name);
}
ub = uwsgi_buffer_new(uwsgi.page_size);
if (!ub) goto end;
// leave space for the header
ub->pos = 4;
if (uwsgi_buffer_append_keyval(ub, "key", 3, s2_key, strlen(s2_key)))
goto end;
if (uwsgi_buffer_append_keyval(ub, "address", 7, s2_addr, strlen(s2_addr)))
goto end;
if (uwsgi_buffer_append_keynum(ub, "modifier1", 9, modifier1))
goto end;
if (uwsgi_buffer_append_keynum(ub, "modifier2", 9, modifier2))
goto end;
if (uwsgi_buffer_append_keynum(ub, "cores", 5, uwsgi.numproc * uwsgi.cores))
goto end;
if (uwsgi_buffer_append_keynum(ub, "load", 4, uwsgi.shared->load))
goto end;
if (uwsgi_buffer_append_keynum(ub, "weight", 6, weight))
goto end;
if (uwsgi_buffer_append_keynum(ub, "backup", 6, backup))
goto end;
if (s2_sni_key) {
if (uwsgi_buffer_append_keyval(ub, "sni_key", 7, s2_sni_key, strlen(s2_sni_key)))
goto end;
}
if (s2_sni_crt) {
if (uwsgi_buffer_append_keyval(ub, "sni_crt", 7, s2_sni_crt, strlen(s2_sni_crt)))
goto end;
}
if (s2_sni_ca) {
if (uwsgi_buffer_append_keyval(ub, "sni_ca", 6, s2_sni_ca, strlen(s2_sni_ca)))
goto end;
}
if (s2_proto) {
if (uwsgi_buffer_append_keyval(ub, "proto", 5, s2_proto, strlen(s2_proto)))
goto end;
}
if (s2_algo) {
if (uwsgi_buffer_append_keyval(ub, "algo", 4, s2_algo, strlen(s2_algo)))
goto end;
}
if (uwsgi.subscription_notify_socket) {
if (uwsgi_buffer_append_keyval(ub, "notify", 6, uwsgi.subscription_notify_socket, strlen(uwsgi.subscription_notify_socket)))
goto end;
}
else if (uwsgi.notify_socket_fd > -1 && uwsgi.notify_socket) {
if (uwsgi_buffer_append_keyval(ub, "notify", 6, uwsgi.notify_socket, strlen(uwsgi.notify_socket)))
goto end;
}
if (uwsgi_subscription_ub_fix(ub, modifier1, modifier2, cmd, s2_sign)) goto end;
send_subscription(-1, s2_server, ub->buf, ub->pos);
end:
if (ub)
uwsgi_buffer_destroy(ub);
if (s2_server)
free(s2_server);
if (s2_key)
@@ -1078,6 +1087,12 @@ end:
free(s2_sni_key);
if (s2_sni_ca)
free(s2_sni_ca);
if (s2_proto)
free(s2_proto);
if (s2_algo)
free(s2_algo);
if (s2_backup)
free(s2_backup);
}
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
@@ -1105,3 +1120,241 @@ void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
}
}
// iphash
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_iphash(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node, struct uwsgi_subscription_client *client) {
// if node is NULL we are in the second step (in lrc mode we do not use the first step)
if (node)
return NULL;
// iphash does not support requests without client data
if (!client) return NULL;
if (!client->sockaddr) return NULL;
uint64_t count = 0;
// first step is counting the number of nodes
node = current_slot->nodes;
while(node) {
if (!node->death_mark) count++;
node = node->next;
}
if (count == 0) return NULL;
uint64_t hash = 0;
//hash the ip
if (client->sockaddr->sa.sa_family == AF_INET) {
hash = client->sockaddr->sa_in.sin_addr.s_addr % count;
}
#ifdef AF_INET6
else if (client->sockaddr->sa.sa_family == AF_INET6) {
hash = djb33x_hash((char *)client->sockaddr->sa_in6.sin6_addr.s6_addr, 16) % count;
}
#endif
// now re-iterate until count matches;
count = 0;
struct uwsgi_subscribe_node *choosen_node = NULL;
node = current_slot->nodes;
while (node) {
if (!node->death_mark) {
if (count == hash) {
choosen_node = node;
break;
}
count++;
}
node = node->next;
}
if (choosen_node) {
choosen_node->reference++;
}
return choosen_node;
}
// least reference count
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_lrc(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node, struct uwsgi_subscription_client *client) {
uint64_t backup_level = 0;
uint64_t has_backup = 0;
// if node is NULL we are in the second step (in lrc mode we do not use the first step)
if (node)
return NULL;
struct uwsgi_subscribe_node *choosen_node = NULL;
retry:
node = current_slot->nodes;
uint64_t min_rc = 0;
while (node) {
if (!node->death_mark) {
if (node->backup_level == backup_level) {
if (min_rc == 0 || node->reference < min_rc) {
min_rc = node->reference;
choosen_node = node;
if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->last_requests <= node->last_requests))
break;
}
}
else if (node->backup_level > backup_level && (!has_backup || has_backup > node->backup_level)) {
has_backup = node->backup_level;
}
}
node = node->next;
}
if (choosen_node) {
choosen_node->reference++;
}
else if (has_backup) {
backup_level = has_backup;
goto retry;
}
return choosen_node;
}
// weighted least reference count
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wlrc(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node, struct uwsgi_subscription_client *client) {
uint64_t backup_level = 0;
uint64_t has_backup = 0;
// if node is NULL we are in the second step (in wlrc mode we do not use the first step)
if (node)
return NULL;
struct uwsgi_subscribe_node *choosen_node = NULL;
retry:
node = current_slot->nodes;
has_backup = 0;
double min_rc = 0;
while (node) {
if (!node->death_mark) {
if (node->backup_level == backup_level) {
// node->weight is always >= 1, we can safely use it as divider
double ref = (double) node->reference / (double) node->weight;
double next_node_ref = 0;
if (node->next)
next_node_ref = (double) node->next->reference / (double) node->next->weight;
if (min_rc == 0 || ref < min_rc) {
min_rc = ref;
choosen_node = node;
if (min_rc == 0 && !(node->next && next_node_ref <= ref && node->next->last_requests <= node->last_requests))
break;
}
}
else if (node->backup_level > backup_level && (!has_backup || has_backup > node->backup_level)) {
has_backup = node->backup_level;
}
}
node = node->next;
}
if (choosen_node) {
choosen_node->reference++;
}
else if (has_backup) {
backup_level = has_backup;
goto retry;
}
return choosen_node;
}
// weighted round robin algo (with backup support)
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wrr(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node, struct uwsgi_subscription_client *client) {
uint64_t backup_level = 0;
uint64_t has_backup = 0;
// if node is NULL we are in the second step
if (node) {
if (node->death_mark == 0 && node->wrr > 0) {
node->wrr--;
node->reference++;
return node;
}
return NULL;
}
// no wrr > 0 node found, reset them
node = current_slot->nodes;
uint64_t min_weight = 0;
while (node) {
if (!node->death_mark) {
if (min_weight == 0 || node->weight < min_weight)
min_weight = node->weight;
}
node = node->next;
}
// now set wrr
retry:
node = current_slot->nodes;
has_backup = 0;
struct uwsgi_subscribe_node *choosen_node = NULL;
while (node) {
if (!node->death_mark) {
if (node->backup_level == backup_level) {
node->wrr = node->weight / min_weight;
choosen_node = node;
}
else if (node->backup_level > backup_level && (!has_backup || has_backup > node->backup_level)) {
has_backup = node->backup_level;
}
}
node = node->next;
}
if (choosen_node) {
choosen_node->wrr--;
choosen_node->reference++;
}
else if (has_backup) {
backup_level = has_backup;
goto retry;
}
return choosen_node;
}
void uwsgi_subscription_init_algos() {
uwsgi_register_subscription_algo("wrr", uwsgi_subscription_algo_wrr);
uwsgi_register_subscription_algo("lrc", uwsgi_subscription_algo_lrc);
uwsgi_register_subscription_algo("wlrc", uwsgi_subscription_algo_wlrc);
uwsgi_register_subscription_algo("iphash", uwsgi_subscription_algo_iphash);
}
void uwsgi_subscription_set_algo(char *algo) {
if (!uwsgi.subscription_algos) {
uwsgi_subscription_init_algos();
}
if (!algo)
goto wrr;
uwsgi.subscription_algo = uwsgi_subscription_algo_get(algo, strlen(algo));
if (uwsgi.subscription_algo) return ;
wrr:
uwsgi.subscription_algo = uwsgi_subscription_algo_wrr;
}
// we are lazy for subscription algos, we initialize them only if needed
struct uwsgi_subscribe_slot **uwsgi_subscription_init_ht() {
if (!uwsgi.subscription_algo) {
uwsgi_subscription_set_algo(NULL);
}
return uwsgi_calloc(sizeof(struct uwsgi_subscription_slot *) * UMAX16);
}
struct uwsgi_subscribe_node *(*uwsgi_subscription_algo_get(char *name , size_t len))(struct uwsgi_subscribe_slot *, struct uwsgi_subscribe_node *, struct uwsgi_subscription_client *) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.subscription_algos) {
if (!uwsgi_strncmp(usl->value, usl->len, name, len)) {
return (struct uwsgi_subscribe_node *(*)(struct uwsgi_subscribe_slot *, struct uwsgi_subscribe_node *, struct uwsgi_subscription_client *)) usl->custom_ptr;
}
}
return NULL;
}
void uwsgi_register_subscription_algo(char *name, struct uwsgi_subscribe_node *(*func)(struct uwsgi_subscribe_slot *, struct uwsgi_subscribe_node *, struct uwsgi_subscription_client *)) {
struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.subscription_algos, name);
usl->custom_ptr = func;
}
Regular → Executable
+169 -87
View File
@@ -42,9 +42,9 @@ int check_hex(char *str, int len) {
}
// increase worker harakiri
void inc_harakiri(int sec) {
void inc_harakiri(struct wsgi_request *wsgi_req, int sec) {
if (uwsgi.master_process) {
uwsgi.workers[uwsgi.mywid].harakiri += sec;
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].harakiri += sec;
}
else {
alarm(uwsgi.harakiri_options.workers + sec);
@@ -52,12 +52,13 @@ void inc_harakiri(int sec) {
}
// set worker harakiri
void set_harakiri(int sec) {
void set_harakiri(struct wsgi_request *wsgi_req, int sec) {
if (!wsgi_req) return;
if (sec == 0) {
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].harakiri = 0;
}
else {
uwsgi.workers[uwsgi.mywid].harakiri = uwsgi_now() + sec;
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].harakiri = uwsgi_now() + sec;
}
if (!uwsgi.master_process) {
alarm(sec);
@@ -65,7 +66,7 @@ void set_harakiri(int sec) {
}
// set user harakiri
void set_user_harakiri(int sec) {
void set_user_harakiri(struct wsgi_request *wsgi_req, int sec) {
if (!uwsgi.master_process) {
uwsgi_log("!!! unable to set user harakiri without the master process !!!\n");
return;
@@ -79,8 +80,8 @@ void set_user_harakiri(int sec) {
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
uspool->user_harakiri = 0;
}
else {
uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
else if (wsgi_req) {
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].user_harakiri = 0;
}
}
else {
@@ -91,8 +92,8 @@ void set_user_harakiri(int sec) {
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
uspool->user_harakiri = uwsgi_now() + sec;
}
else {
uwsgi.workers[uwsgi.mywid].user_harakiri = uwsgi_now() + sec;
else if (wsgi_req) {
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].user_harakiri = uwsgi_now() + sec;
}
}
}
@@ -332,9 +333,11 @@ void uwsgi_as_root() {
if (getuid() > 0)
goto nonroot;
#ifndef __RUMP__
if (!uwsgi.master_as_root && !uwsgi.uidname) {
uwsgi_log_initial("uWSGI running as root, you can use --uid/--gid/--chroot options\n");
}
#endif
int in_jail = 0;
@@ -700,20 +703,20 @@ void uwsgi_as_root() {
}
uwsgi_foreach(usl, uwsgi.wait_for_fs) {
if (uwsgi_wait_for_fs(usl->value, 0)) exit(1);
}
if (uwsgi_wait_for_fs(usl->value, 0)) exit(1);
}
uwsgi_foreach(usl, uwsgi.wait_for_file) {
if (uwsgi_wait_for_fs(usl->value, 1)) exit(1);
}
uwsgi_foreach(usl, uwsgi.wait_for_file) {
if (uwsgi_wait_for_fs(usl->value, 1)) exit(1);
}
uwsgi_foreach(usl, uwsgi.wait_for_dir) {
if (uwsgi_wait_for_fs(usl->value, 2)) exit(1);
}
uwsgi_foreach(usl, uwsgi.wait_for_dir) {
if (uwsgi_wait_for_fs(usl->value, 2)) exit(1);
}
uwsgi_foreach(usl, uwsgi.wait_for_mountpoint) {
if (uwsgi_wait_for_mountpoint(usl->value)) exit(1);
}
uwsgi_foreach(usl, uwsgi.wait_for_mountpoint) {
if (uwsgi_wait_for_mountpoint(usl->value)) exit(1);
}
uwsgi_hooks_run(uwsgi.hook_as_root, "as root", 1);
@@ -892,6 +895,7 @@ void uwsgi_as_root() {
}
}
}
free(gids);
}
}
if (uwsgi.uid) {
@@ -903,9 +907,11 @@ void uwsgi_as_root() {
}
}
#ifndef __RUMP__
if (!getuid()) {
uwsgi_log_initial("*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n");
}
#endif
#ifdef UWSGI_CAP
@@ -1037,7 +1043,7 @@ void uwsgi_destroy_request(struct wsgi_request *wsgi_req) {
// reset for avoiding following requests to fail on non-uwsgi protocols
// thanks Marko Tiikkaja for catching it
wsgi_req->uh->pktsize = 0;
wsgi_req->uh->_pktsize = 0;
// some plugins expected async_id to be defined before setup
int tmp_id = wsgi_req->async_id;
@@ -1121,13 +1127,13 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
}
// leave harakiri mode
if (uwsgi.workers[uwsgi.mywid].harakiri > 0) {
set_harakiri(0);
if (uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].harakiri > 0) {
set_harakiri(wsgi_req, 0);
}
// leave user harakiri mode
if (uwsgi.workers[uwsgi.mywid].user_harakiri > 0) {
set_user_harakiri(0);
if (uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].user_harakiri > 0) {
set_user_harakiri(wsgi_req, 0);
}
if (!wsgi_req->do_not_account) {
@@ -1185,7 +1191,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
// reset request
wsgi_req->uh->pktsize = 0;
wsgi_req->uh->_pktsize = 0;
tmp_id = wsgi_req->async_id;
memset(wsgi_req, 0, sizeof(struct wsgi_request));
// some plugins expected async_id to be defined before setup
@@ -1193,17 +1199,26 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
// yes, this is pretty useless but we cannot ensure all of the plugin have the same behaviour
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
if (uwsgi.max_requests > 0 && uwsgi.workers[uwsgi.mywid].delta_requests >= uwsgi.max_requests
if (uwsgi.max_requests > 0 && uwsgi.workers[uwsgi.mywid].delta_requests >= (uwsgi.max_requests + ((uwsgi.mywid-1) * uwsgi.max_requests_delta))
&& (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
goodbye_cruel_world();
goodbye_cruel_world("max requests reached (%llu >= %llu)",
(unsigned long long) uwsgi.workers[uwsgi.mywid].delta_requests,
(unsigned long long) (uwsgi.max_requests + ((uwsgi.mywid-1) * uwsgi.max_requests_delta))
);
}
if (uwsgi.reload_on_as && (rlim_t) vsz >= uwsgi.reload_on_as && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
goodbye_cruel_world();
goodbye_cruel_world("reload-on-as limit reached (%llu >= %llu)",
(unsigned long long) (rlim_t) vsz,
(unsigned long long) uwsgi.reload_on_as
);
}
if (uwsgi.reload_on_rss && (rlim_t) rss >= uwsgi.reload_on_rss && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
goodbye_cruel_world();
goodbye_cruel_world("reload-on-rss limit reached (%llu >= %llu)",
(unsigned long long) (rlim_t) rss,
(unsigned long long) uwsgi.reload_on_rss
);
}
@@ -1384,7 +1399,7 @@ int wsgi_req_async_recv(struct wsgi_request *wsgi_req) {
// enter harakiri mode
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
set_harakiri(wsgi_req, uwsgi.harakiri_options.workers);
}
return 0;
@@ -1416,7 +1431,7 @@ int wsgi_req_recv(int queue, struct wsgi_request *wsgi_req) {
// enter harakiri mode
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
set_harakiri(wsgi_req, uwsgi.harakiri_options.workers);
}
#ifdef UWSGI_ROUTING
@@ -1537,7 +1552,7 @@ int wsgi_req_accept(int queue, struct wsgi_request *wsgi_req) {
thunder_unlock;
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
uwsgi_receive_signal(wsgi_req, interesting_fd, "worker", uwsgi.mywid);
if (uwsgi.threads > 1)
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ret);
@@ -1788,9 +1803,15 @@ void *uwsgi_malloc(size_t size) {
}
void *uwsgi_calloc(size_t size) {
char *ptr = uwsgi_malloc(size);
memset(ptr, 0, size);
// thanks Mathieu Dupuy for pointing out that calloc is faster
// than malloc + memset
char *ptr = calloc(1, size);
if (ptr == NULL) {
uwsgi_error("calloc()");
uwsgi_log("!!! tried memory allocation of %llu bytes !!!\n", (unsigned long long) size);
uwsgi_backtrace(uwsgi.backtrace_depth);
exit(1);
}
return ptr;
}
@@ -1832,7 +1853,7 @@ char *magic_sub(char *buffer, size_t len, size_t * size, char *magic_table[]) {
for (i = 0; i < len; i++) {
if (buffer[i] == '%' && (i + 1) < len && magic_table[(unsigned char) buffer[i + 1]]) {
old_magic_buf = magic_buf;
magic_buf = uwsgi_concat3n(old_magic_buf, magic_len, magic_table[(unsigned char) buffer[i + 1]], strlen(magic_table[(unsigned char) buffer[i + 1]]), buffer + i + 2, len - i);
magic_buf = uwsgi_concat3n(old_magic_buf, magic_len, magic_table[(unsigned char) buffer[i + 1]], strlen(magic_table[(unsigned char) buffer[i + 1]]), buffer + i + 2, len - i - 2);
free(old_magic_buf);
magic_len += strlen(magic_table[(unsigned char) buffer[i + 1]]);
magic_ptr = magic_buf + magic_len;
@@ -1862,24 +1883,6 @@ void init_magic_table(char *magic_table[]) {
magic_table['('] = "%(";
}
char *uwsgi_get_last_char(char *what, char c) {
size_t len = strlen(what);
while (len--) {
if (what[len] == c)
return what + len;
}
return NULL;
}
char *uwsgi_get_last_charn(char *what, size_t len, char c) {
while (len--) {
if (what[len] == c)
return what + len;
}
return NULL;
}
char *uwsgi_num2str(int num) {
char *str = uwsgi_malloc(11);
@@ -1911,13 +1914,7 @@ int uwsgi_long2str2n(unsigned long long num, char *ptr, int size) {
}
int is_unix(char *socket_name, int len) {
int i;
for (i = 0; i < len; i++) {
if (socket_name[i] == ':')
return 0;
}
return 1;
return !memchr(socket_name, ':', len);
}
int is_a_number(char *what) {
@@ -2216,6 +2213,19 @@ void uwsgi_dyn_dict_del(struct uwsgi_dyn_dict *item) {
free(item);
}
void uwsgi_dyn_dict_free(struct uwsgi_dyn_dict **dd) {
struct uwsgi_dyn_dict *attr = *dd;
while(attr) {
struct uwsgi_dyn_dict *tmp = attr;
attr = attr->next;
if (tmp->value) free(tmp->value);
free(tmp);
}
*dd = NULL;
}
void *uwsgi_malloc_shared(size_t size) {
void *addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
@@ -2231,6 +2241,12 @@ void *uwsgi_malloc_shared(size_t size) {
void *uwsgi_calloc_shared(size_t size) {
void *ptr = uwsgi_malloc_shared(size);
// NOTE by Mathieu Dupuy:
// OSes guarantee mmap MAP_ANON memory area to be zero-filled (see man pages)
// we should trust it, but history has taught us it is better to be paranoid.
// Lucky enough this function is called ony in startup phases, so performance
// tips/tricks are irrelevant (So, le'ts call memset...)
memset(ptr, 0, size);
return ptr;
}
@@ -3124,6 +3140,8 @@ pid_t uwsgi_fork(char *name) {
#if defined(__linux__) || defined(__sun__)
int i;
for (i = 0; i < uwsgi.argc; i++) {
// stop fixing original argv if the new one is bigger
if (!uwsgi.orig_argv[i]) break;
strcpy(uwsgi.orig_argv[i], uwsgi.argv[i]);
}
#endif
@@ -3514,7 +3532,7 @@ int uwsgi_tmpfd() {
tmpdir = "/tmp";
}
#ifdef O_TMPFILE
fd = open(tmpdir, O_TMPFILE | O_RDWR);
fd = open(tmpdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
if (fd >= 0) {
return fd;
}
@@ -3596,6 +3614,13 @@ void uwsgi_write_pidfile(char *pidfile_name) {
}
}
void uwsgi_write_pidfile_explicit(char *pidfile_name, pid_t pid) {
uwsgi_log("writing pidfile to %s\n", pidfile_name);
if (uwsgi_write_intfile(pidfile_name, (int) pid)) {
uwsgi_log("could not write pidfile.\n");
}
}
char *uwsgi_expand_path(char *dir, int dir_len, char *ptr) {
char src[PATH_MAX + 1];
memcpy(src, dir, dir_len);
@@ -3876,7 +3901,6 @@ int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separ
}
}
va_end(ap);
base = ptr;
break;
}
else if (usl->value[i] == '\\' && !escaped) {
@@ -4446,6 +4470,7 @@ void uwsgi_setns(char *path) {
}
}
free(fds);
close(ns_fd);
break;
}
if (fds)
@@ -4479,6 +4504,29 @@ mode_t uwsgi_mode_t(char *value, int *error) {
return mode;
}
int uwsgi_wait_for_socket(char *socket_name) {
if (!uwsgi.wait_for_socket_timeout) {
uwsgi.wait_for_socket_timeout = 60;
}
uwsgi_log("waiting for %s (max %d seconds) ...\n", socket_name, uwsgi.wait_for_socket_timeout);
int counter = 0;
for (;;) {
if (counter > uwsgi.wait_for_socket_timeout) {
uwsgi_log("%s unavailable after %d seconds\n", socket_name, counter);
return -1;
}
// wait for 1 second to respect uwsgi.wait_for_fs_timeout
int fd = uwsgi_connect(socket_name, 1, 0);
if (fd < 0) goto retry;
close(fd);
uwsgi_log_verbose("%s ready\n", socket_name);
return 0;
retry:
sleep(1);
counter++;
}
return -1;
}
int uwsgi_wait_for_mountpoint(char *mountpoint) {
if (!uwsgi.wait_for_fs_timeout) {
@@ -4491,47 +4539,81 @@ int uwsgi_wait_for_mountpoint(char *mountpoint) {
uwsgi_log("%s unavailable after %d seconds\n", mountpoint, counter);
return -1;
}
struct stat st0;
struct stat st1;
if (stat(mountpoint, &st0)) goto retry;
if (!S_ISDIR(st0.st_mode)) goto retry;
char *relative = uwsgi_concat2(mountpoint, "/../");
if (stat(relative, &st1)) {
free(relative);
goto retry;
}
free(relative);
// useless :P
struct stat st0;
struct stat st1;
if (stat(mountpoint, &st0)) goto retry;
if (!S_ISDIR(st0.st_mode)) goto retry;
char *relative = uwsgi_concat2(mountpoint, "/../");
if (stat(relative, &st1)) {
free(relative);
goto retry;
}
free(relative);
// useless :P
if (!S_ISDIR(st1.st_mode)) goto retry;
if (st0.st_dev == st1.st_dev) goto retry;
if (st0.st_dev == st1.st_dev) goto retry;
uwsgi_log_verbose("%s mounted\n", mountpoint);
return 0;
retry:
sleep(1);
counter++;
}
return -1;
}
// type -> 1 file, 2 dir, 0 both
int uwsgi_wait_for_fs(char *filename, int type) {
if (!uwsgi.wait_for_fs_timeout) {
uwsgi.wait_for_fs_timeout = 60;
if (!uwsgi.wait_for_fs_timeout) {
uwsgi.wait_for_fs_timeout = 60;
}
uwsgi_log("waiting for %s (max %d seconds) ...\n", filename, uwsgi.wait_for_fs_timeout);
int counter = 0;
for (;;) {
if (counter > uwsgi.wait_for_fs_timeout) {
uwsgi_log("%s unavailable after %d seconds\n", filename, counter);
return -1;
if (counter > uwsgi.wait_for_fs_timeout) {
uwsgi_log("%s unavailable after %d seconds\n", filename, counter);
return -1;
}
struct stat st;
if (stat(filename, &st)) goto retry;
if (type == 1 && !S_ISREG(st.st_mode)) goto retry;
if (type == 2 && !S_ISDIR(st.st_mode)) goto retry;
struct stat st;
if (stat(filename, &st)) goto retry;
if (type == 1 && !S_ISREG(st.st_mode)) goto retry;
if (type == 2 && !S_ISDIR(st.st_mode)) goto retry;
uwsgi_log_verbose("%s found\n", filename);
return 0;
return 0;
retry:
sleep(1);
counter++;
}
return -1;
}
#if !defined(_GNU_SOURCE) && !defined(__UCLIBC__)
int uwsgi_versionsort(const struct dirent **da, const struct dirent **db) {
const char *a = (*da)->d_name;
const char *b = (*db)->d_name;
long la, lb;
char *endptr;
// Check if a and b are valid numbers.
la = strtol(a, &endptr, 10);
if (strcmp(endptr, "\0") || endptr == a) {
a = NULL;
}
lb = strtol(b, &endptr, 10);
if (strcmp(endptr, "\0") || endptr == b) {
b = NULL;
}
if (a && b) {
return (la < lb ? -1 : la > lb);
} else if (a) {
return -1;
} else if (b) {
return 1;
} else {
return strcmp((*da)->d_name, (*db)->d_name);
}
}
#endif
Regular → Executable
+231 -27
View File
@@ -2,7 +2,7 @@
*** uWSGI ***
Copyright (C) 2009-2014 Unbit S.a.s. <info@unbit.it>
Copyright (C) 2009-2015 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -47,6 +47,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"http-socket-modifier1", required_argument, 0, "force the specified modifier1 when using HTTP protocol", uwsgi_opt_set_64bit, &uwsgi.http_modifier1, 0},
{"http-socket-modifier2", required_argument, 0, "force the specified modifier2 when using HTTP protocol", uwsgi_opt_set_64bit, &uwsgi.http_modifier2, 0},
{"http11-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTP 1.1 (Keep-Alive) protocol", uwsgi_opt_add_socket, "http11", 0},
#ifdef UWSGI_SSL
{"https-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTPS protocol", uwsgi_opt_add_ssl_socket, "https", 0},
{"https-socket-modifier1", required_argument, 0, "force the specified modifier1 when using HTTPS protocol", uwsgi_opt_set_64bit, &uwsgi.https_modifier1, 0},
@@ -172,7 +174,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"listen", required_argument, 'l', "set the socket listen queue size", uwsgi_opt_set_int, &uwsgi.listen_queue, 0},
{"max-vars", required_argument, 'v', "set the amount of internal iovec/vars structures", uwsgi_opt_max_vars, NULL, 0},
{"max-apps", required_argument, 0, "set the maximum number of per-worker applications", uwsgi_opt_set_int, &uwsgi.max_apps, 0},
{"buffer-size", required_argument, 'b', "set internal buffer size", uwsgi_opt_set_16bit, &uwsgi.buffer_size, 0},
{"buffer-size", required_argument, 'b', "set internal buffer size", uwsgi_opt_set_64bit, &uwsgi.buffer_size, 0},
{"memory-report", no_argument, 'm', "enable memory report", uwsgi_opt_true, &uwsgi.logging_options.memory_report, 0},
{"profiler", required_argument, 0, "enable the specified profiler", uwsgi_opt_set_str, &uwsgi.profiler, 0},
{"cgi-mode", no_argument, 'c', "force CGI-mode for plugins supporting it", uwsgi_opt_true, &uwsgi.cgi_mode, 0},
@@ -202,6 +204,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
{"emperor-proxy-socket", required_argument, 0, "force the vassal to became an Emperor proxy", uwsgi_opt_set_str, &uwsgi.emperor_proxy, 0},
{"emperor-wrapper", required_argument, 0, "set a binary wrapper for vassals", uwsgi_opt_set_str, &uwsgi.emperor_wrapper, 0},
{"emperor-wrapper-override", required_argument, 0, "set a binary wrapper for vassals to try before the default one", uwsgi_opt_add_string_list, &uwsgi.emperor_wrapper_override, 0},
{"emperor-wrapper-fallback", required_argument, 0, "set a binary wrapper for vassals to try as a last resort", uwsgi_opt_add_string_list, &uwsgi.emperor_wrapper_fallback, 0},
{"emperor-nofollow", no_argument, 0, "do not follow symlinks when checking for mtime", uwsgi_opt_true, &uwsgi.emperor_nofollow, 0},
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
@@ -210,8 +214,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"emperor-pidfile", required_argument, 0, "write the Emperor pid in the specified file", uwsgi_opt_set_str, &uwsgi.emperor_pidfile, 0},
{"emperor-tyrant", no_argument, 0, "put the Emperor in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant, 0},
{"emperor-tyrant-nofollow", no_argument, 0, "do not follow symlinks when checking for uid/gid in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant_nofollow, 0},
{"emperor-tyrant-initgroups", no_argument, 0, "add additional groups set via initgroups() in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant_initgroups, 0},
{"emperor-stats", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
{"emperor-stats-server", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
{"emperor-trigger-socket", required_argument, 0, "enable the Emperor trigger socket", uwsgi_opt_set_str, &uwsgi.emperor_trigger_socket, 0},
{"early-emperor", no_argument, 0, "spawn the emperor as soon as possibile", uwsgi_opt_true, &uwsgi.early_emperor, 0},
{"emperor-broodlord", required_argument, 0, "run the emperor in BroodLord mode", uwsgi_opt_set_int, &uwsgi.emperor_broodlord, 0},
{"emperor-throttle", required_argument, 0, "set throttling level (in milliseconds) for bad behaving vassals (default 1000)", uwsgi_opt_set_int, &uwsgi.emperor_throttle, 0},
@@ -228,11 +234,19 @@ static struct uwsgi_option uwsgi_base_options[] = {
#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-use-fork-server", required_argument, 0, "connect to the specified fork server instead of using plain fork() for new vassals", uwsgi_opt_set_str, &uwsgi.emperor_use_fork_server, 0},
{"vassal-fork-base", required_argument, 0, "use plain fork() for the specified vassal (instead of a fork-server)", uwsgi_opt_add_string_list, &uwsgi.vassal_fork_base, 0},
{"emperor-subreaper", no_argument, 0, "force the Emperor to be a sub-reaper (if supported)", uwsgi_opt_true, &uwsgi.emperor_subreaper, 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},
{"vassal-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 0},
#endif
{"emperor-collect-attribute", required_argument, 0, "collect the specified vassal attribute from imperial monitors", uwsgi_opt_add_string_list, &uwsgi.emperor_collect_attributes, 0},
{"emperor-collect-attr", required_argument, 0, "collect the specified vassal attribute from imperial monitors", uwsgi_opt_add_string_list, &uwsgi.emperor_collect_attributes, 0},
{"emperor-fork-server-attr", required_argument, 0, "set teh vassal's attribute to get when checking for fork-server", uwsgi_opt_set_str, &uwsgi.emperor_fork_server_attr, 0},
{"emperor-wrapper-attr", required_argument, 0, "set the vassal's attribute to get when checking for fork-wrapper", uwsgi_opt_set_str, &uwsgi.emperor_wrapper_attr, 0},
{"emperor-chdir-attr", required_argument, 0, "set the vassal's attribute to get when checking for chdir", uwsgi_opt_set_str, &uwsgi.emperor_chdir_attr, 0},
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
{"vassals-inherit", required_argument, 0, "add config templates to vassals config (uses --inherit)", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
@@ -248,11 +262,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"heartbeat", required_argument, 0, "announce healthiness to the emperor", uwsgi_opt_set_int, &uwsgi.heartbeat, 0},
{"zeus", required_argument, 0, "enable Zeus mode", uwsgi_opt_set_str, &uwsgi.zeus, 0},
{"reload-mercy", required_argument, 0, "set the maximum time (in seconds) we wait for workers and other processes to die during reload/shutdown", uwsgi_opt_set_int, &uwsgi.reload_mercy, 0},
{"worker-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.worker_reload_mercy, 0},
{"mule-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a mule can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.mule_reload_mercy, 0},
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload, 0},
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM (no more needed)", uwsgi_opt_deprecated, &uwsgi.die_on_term, 0},
{"force-gateway", no_argument, 0, "force the spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
@@ -262,6 +278,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"reaper", no_argument, 'r', "call waitpid(-1,...) after each request to get rid of zombies", uwsgi_opt_true, &uwsgi.reaper, 0},
{"max-requests", required_argument, 'R', "reload workers after the specified amount of managed requests", uwsgi_opt_set_64bit, &uwsgi.max_requests, 0},
{"max-requests-delta", required_argument, 0, "add (worker_id * delta) to the max_requests value of each worker", uwsgi_opt_set_64bit, &uwsgi.max_requests_delta, 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},
@@ -309,9 +326,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"spooler-processes", required_argument, 0, "set the number of processes for spoolers", uwsgi_opt_set_int, &uwsgi.spooler_numproc, UWSGI_OPT_IMMEDIATE},
{"spooler-quiet", no_argument, 0, "do not be verbose with spooler tasks", uwsgi_opt_true, &uwsgi.spooler_quiet, 0},
{"spooler-max-tasks", required_argument, 0, "set the maximum number of tasks to run before recycling a spooler", uwsgi_opt_set_int, &uwsgi.spooler_max_tasks, 0},
{"spooler-signal-as-task", no_argument, 0, "treat signal events as tasks in spooler, combine used with spooler-max-tasks", uwsgi_opt_true, &uwsgi.spooler_signal_as_task, 0},
{"spooler-harakiri", required_argument, 0, "set harakiri timeout for spooler tasks", uwsgi_opt_set_int, &uwsgi.harakiri_options.spoolers, 0},
{"spooler-frequency", required_argument, 0, "set spooler frequency", uwsgi_opt_set_int, &uwsgi.spooler_frequency, 0},
{"spooler-freq", required_argument, 0, "set spooler frequency", uwsgi_opt_set_int, &uwsgi.spooler_frequency, 0},
{"spooler-cheap", no_argument, 0, "set spooler cheap mode", uwsgi_opt_true, &uwsgi.spooler_cheap, 0},
{"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
{"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
@@ -340,6 +359,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"pidfile", required_argument, 0, "create pidfile (before privileges drop)", uwsgi_opt_set_str, &uwsgi.pidfile, 0},
{"pidfile2", required_argument, 0, "create pidfile (after privileges drop)", uwsgi_opt_set_str, &uwsgi.pidfile2, 0},
{"safe-pidfile", required_argument, 0, "create safe pidfile (before privileges drop)", uwsgi_opt_set_str, &uwsgi.safe_pidfile, 0},
{"safe-pidfile2", required_argument, 0, "create safe pidfile (after privileges drop)", uwsgi_opt_set_str, &uwsgi.safe_pidfile2, 0},
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
#ifdef __linux__
{"pivot-root", required_argument, 0, "pivot_root() to the specified directories (new_root and put_old must be separated with a space)", uwsgi_opt_set_str, &uwsgi.pivot_root, 0},
@@ -363,6 +384,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"setns-skip", required_argument, 0, "skip the specified entry when sending setns file descriptors", uwsgi_opt_add_string_list, &uwsgi.setns_socket_skip, 0},
{"setns", required_argument, 0, "join a namespace created by an external uWSGI instance", uwsgi_opt_set_str, &uwsgi.setns, 0},
{"setns-preopen", no_argument, 0, "open /proc/self/ns as soon as possible and cache fds", uwsgi_opt_true, &uwsgi.setns_preopen, 0},
{"fork-socket", required_argument, 0, "suspend the execution after early initialization and fork() at every unix socket connection", uwsgi_opt_set_str, &uwsgi.fork_socket, 0},
{"fork-server", required_argument, 0, "suspend the execution after early initialization and fork() at every unix socket connection", uwsgi_opt_set_str, &uwsgi.fork_socket, 0},
#endif
{"jailed", no_argument, 0, "mark the instance as jailed (force the execution of post_jail hooks)", uwsgi_opt_true, &uwsgi.jailed, 0},
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
@@ -393,7 +416,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"hook-as-user-atexit", required_argument, 0, "run the specified hook before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.hook_as_user_atexit, 0},
{"hook-pre-app", required_argument, 0, "run the specified hook before app loading", uwsgi_opt_add_string_list, &uwsgi.hook_pre_app, 0},
{"hook-post-app", required_argument, 0, "run the specified hook after app loading", uwsgi_opt_add_string_list, &uwsgi.hook_post_app, 0},
{"hook-post-fork", required_argument, 0, "run the specified hook after each fork", uwsgi_opt_add_string_list, &uwsgi.hook_post_fork, 0},
{"hook-post-fork", required_argument, 0, "run the specified hook after each fork", uwsgi_opt_add_string_list, &uwsgi.hook_post_fork, 0},
{"hook-accepting", required_argument, 0, "run the specified hook after each worker enter the accepting phase", uwsgi_opt_add_string_list, &uwsgi.hook_accepting, 0},
{"hook-accepting1", required_argument, 0, "run the specified hook after the first worker enters the accepting phase", uwsgi_opt_add_string_list, &uwsgi.hook_accepting1, 0},
{"hook-accepting-once", required_argument, 0, "run the specified hook after each worker enter the accepting phase (once per-instance)", uwsgi_opt_add_string_list, &uwsgi.hook_accepting_once, 0},
@@ -411,6 +434,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"hook-as-vassal", required_argument, 0, "run the specified hook before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.hook_as_vassal, 0},
{"hook-as-emperor", required_argument, 0, "run the specified hook in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.hook_as_emperor, 0},
{"hook-as-on-demand-vassal", required_argument, 0, "run the specified hook whenever a vassal enters on-demand mode", uwsgi_opt_add_string_list, &uwsgi.hook_as_on_demand_vassal, 0},
{"hook-as-on-config-vassal", required_argument, 0, "run the specified hook whenever the emperor detects a config change for an on-demand vassal", uwsgi_opt_add_string_list, &uwsgi.hook_as_on_config_vassal, 0},
{"hook-as-emperor-before-vassal", required_argument, 0, "run the specified hook before the new vassal is spawned", uwsgi_opt_add_string_list, &uwsgi.hook_as_emperor_before_vassal, 0},
{"hook-as-vassal-before-drop", required_argument, 0, "run the specified hook into vassal, before dropping its privileges", uwsgi_opt_add_string_list, &uwsgi.hook_as_vassal_before_drop, 0},
{"hook-as-emperor-setns", required_argument, 0, "run the specified hook in the emperor entering vassal namespace", uwsgi_opt_add_string_list, &uwsgi.hook_as_emperor_setns, 0},
{"hook-as-mule", required_argument, 0, "run the specified hook in each mule", uwsgi_opt_add_string_list, &uwsgi.hook_as_mule, 0},
{"hook-as-gateway", required_argument, 0, "run the specified hook in each gateway", uwsgi_opt_add_string_list, &uwsgi.hook_as_gateway, 0},
@@ -467,6 +498,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"wait-for-mountpoint", required_argument, 0, "wait for the specified mountpoint to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_mountpoint, 0},
{"wait-for-fs-timeout", required_argument, 0, "set the timeout for wait-for-fs/file/dir", uwsgi_opt_set_int, &uwsgi.wait_for_fs_timeout, 0},
{"wait-for-socket", required_argument, 0, "wait for the specified socket to be ready before loading apps", uwsgi_opt_add_string_list, &uwsgi.wait_for_socket, 0},
{"wait-for-socket-timeout", required_argument, 0, "set the timeout for wait-for-socket", uwsgi_opt_set_int, &uwsgi.wait_for_socket_timeout, 0},
{"call-asap", required_argument, 0, "call the specified function as soon as possible", uwsgi_opt_add_string_list, &uwsgi.call_asap, 0},
{"call-pre-jail", required_argument, 0, "call the specified function before jailing", uwsgi_opt_add_string_list, &uwsgi.call_pre_jail, 0},
{"call-post-jail", required_argument, 0, "call the specified function after jailing", uwsgi_opt_add_string_list, &uwsgi.call_post_jail, 0},
@@ -516,6 +550,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"reload-on-rss", required_argument, 0, "reload if rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_rss, UWSGI_OPT_MEMORY},
{"evil-reload-on-as", required_argument, 0, "force the master to reload a worker if its address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_as, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
{"evil-reload-on-rss", required_argument, 0, "force the master to reload a worker if its rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_rss, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
{"mem-collector-freq", required_argument, 0, "set the memory collector frequency when evil reloads are in place", uwsgi_opt_set_int, &uwsgi.mem_collector_freq, 0},
{"reload-on-fd", required_argument, 0, "reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.reload_on_fd, UWSGI_OPT_MASTER},
{"brutal-reload-on-fd", required_argument, 0, "brutal reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.brutal_reload_on_fd, UWSGI_OPT_MASTER},
@@ -596,6 +631,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"notify-socket", required_argument, 0, "enable the notification socket", uwsgi_opt_set_str, &uwsgi.notify_socket, UWSGI_OPT_MASTER},
{"subscription-notify-socket", required_argument, 0, "set the notification socket for subscriptions", uwsgi_opt_set_str, &uwsgi.subscription_notify_socket, UWSGI_OPT_MASTER},
{"subscription-mountpoints", no_argument, 0, "enable mountpoints support for subscription system", uwsgi_opt_true, &uwsgi.subscription_mountpoints, UWSGI_OPT_MASTER},
{"subscription-mountpoint", no_argument, 0, "enable mountpoints support for subscription system", uwsgi_opt_true, &uwsgi.subscription_mountpoints, UWSGI_OPT_MASTER},
#ifdef UWSGI_SSL
{"legion", required_argument, 0, "became a member of a legion", uwsgi_opt_legion, NULL, UWSGI_OPT_MASTER},
@@ -632,6 +669,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"subscription-tolerance", required_argument, 0, "set tolerance for subscription servers", uwsgi_opt_set_int, &uwsgi.subscription_tolerance, 0},
{"unsubscribe-on-graceful-reload", no_argument, 0, "force unsubscribe request even during graceful reload", uwsgi_opt_true, &uwsgi.unsubscribe_on_graceful_reload, 0},
{"start-unsubscribed", no_argument, 0, "configure subscriptions but do not send them (useful with master fifo)", uwsgi_opt_true, &uwsgi.subscriptions_blocked, 0},
{"subscribe-with-modifier1", required_argument, 0, "force the specififed modifier1 when subscribing", uwsgi_opt_set_str, &uwsgi.subscribe_with_modifier1, UWSGI_OPT_MASTER},
{"snmp", optional_argument, 0, "enable the embedded snmp server", uwsgi_opt_snmp, NULL, 0},
{"snmp-community", required_argument, 0, "set the snmp community string", uwsgi_opt_snmp_community, NULL, 0},
#ifdef UWSGI_SSL
@@ -659,6 +699,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"privileged-binary-patch-arg", required_argument, 0, "patch the uwsgi binary with a new command and arguments (before privileges drop)", uwsgi_opt_set_str, &uwsgi.privileged_binary_patch_arg, 0},
{"unprivileged-binary-patch-arg", required_argument, 0, "patch the uwsgi binary with a new command and arguments (after privileges drop)", uwsgi_opt_set_str, &uwsgi.unprivileged_binary_patch_arg, 0},
{"async", required_argument, 0, "enable async mode with specified cores", uwsgi_opt_set_int, &uwsgi.async, 0},
{"disable-async-warn-on-queue-full", no_argument, 0, "Disable printing 'async queue is full' warning messages.", uwsgi_opt_false, &uwsgi.async_warn_if_queue_full, 0},
{"max-fd", required_argument, 0, "set maximum number of file descriptors (requires root privileges)", uwsgi_opt_set_int, &uwsgi.requested_max_fd, 0},
{"logto", required_argument, 0, "set logfile/udp address", uwsgi_opt_set_str, &uwsgi.logfile, 0},
{"logto2", required_argument, 0, "log to specified file or udp address after privileges drop", uwsgi_opt_set_str, &uwsgi.logto2, 0},
@@ -673,6 +714,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"req-logger", required_argument, 0, "set/append a request logger", uwsgi_opt_set_req_logger, NULL, UWSGI_OPT_REQ_LOG_MASTER},
{"logger-req", required_argument, 0, "set/append a request logger", uwsgi_opt_set_req_logger, NULL, UWSGI_OPT_REQ_LOG_MASTER},
{"logger", required_argument, 0, "set/append a logger", uwsgi_opt_set_logger, NULL, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"worker-logger", required_argument, 0, "set/append a logger in single-worker setup", uwsgi_opt_set_worker_logger, NULL, 0},
{"worker-logger-req", required_argument, 0, "set/append a request logger in single-worker setup", uwsgi_opt_set_req_logger, NULL, 0},
{"logger-list", no_argument, 0, "list enabled loggers", uwsgi_opt_true, &uwsgi.loggers_list, 0},
{"loggers-list", no_argument, 0, "list enabled loggers", uwsgi_opt_true, &uwsgi.loggers_list, 0},
{"threaded-logger", no_argument, 0, "offload log writing to a thread", uwsgi_opt_true, &uwsgi.threaded_logger, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
@@ -680,6 +723,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"log-encoder", required_argument, 0, "add an item in the log encoder chain", uwsgi_opt_add_string_list, &uwsgi.requested_log_encoders, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"log-req-encoder", required_argument, 0, "add an item in the log req encoder chain", uwsgi_opt_add_string_list, &uwsgi.requested_log_req_encoders, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"worker-log-encoder", required_argument, 0, "add an item in the log encoder chain", uwsgi_opt_add_string_list, &uwsgi.requested_log_encoders, 0},
{"worker-log-req-encoder", required_argument, 0, "add an item in the log req encoder chain", uwsgi_opt_add_string_list, &uwsgi.requested_log_req_encoders, 0},
#ifdef UWSGI_PCRE
@@ -693,7 +739,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
{"alarm-cheap", required_argument, 0, "use main alarm thread rather than create dedicated threads for curl-based alarms", uwsgi_opt_true, &uwsgi.alarm_cheap, 0},
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
{"alarm-freq", required_argument, 0, "tune the anti-loop alarm system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
{"alarm-segfault", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
{"segfault-alarm", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
@@ -751,6 +797,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"cheaper-algo", required_argument, 0, "choose to algorithm used for adaptive process spawning", uwsgi_opt_set_str, &uwsgi.requested_cheaper_algo, UWSGI_OPT_MASTER},
{"cheaper-step", required_argument, 0, "number of additional processes to spawn at each overload", uwsgi_opt_set_int, &uwsgi.cheaper_step, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
{"cheaper-overload", required_argument, 0, "increase workers after specified overload", uwsgi_opt_set_64bit, &uwsgi.cheaper_overload, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
{"cheaper-idle", required_argument, 0, "decrease workers after specified idle (algo: spare2) (default: 10)", uwsgi_opt_set_int, &uwsgi.cheaper_idle, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
{"cheaper-algo-list", no_argument, 0, "list enabled cheapers algorithms", uwsgi_opt_true, &uwsgi.cheaper_algo_list, 0},
{"cheaper-algos-list", no_argument, 0, "list enabled cheapers algorithms", uwsgi_opt_true, &uwsgi.cheaper_algo_list, 0},
{"cheaper-list", no_argument, 0, "list enabled cheapers algorithms", uwsgi_opt_true, &uwsgi.cheaper_algo_list, 0},
@@ -758,6 +805,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"cheaper-rss-limit-hard", required_argument, 0, "if total workers resident memory usage is higher try to stop workers", uwsgi_opt_set_64bit, &uwsgi.cheaper_rss_limit_hard, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
{"idle", required_argument, 0, "set idle mode (put uWSGI in cheap mode after inactivity)", uwsgi_opt_set_int, &uwsgi.idle, UWSGI_OPT_MASTER},
{"die-on-idle", no_argument, 0, "shutdown uWSGI when idle", uwsgi_opt_true, &uwsgi.die_on_idle, 0},
{"die-on-no-workers", no_argument, 0, "shutdown uWSGI when no workers are running", uwsgi_opt_true, &uwsgi.die_on_no_workers, 0},
{"mount", required_argument, 0, "load application under mountpoint", uwsgi_opt_add_string_list, &uwsgi.mounts, 0},
{"worker-mount", required_argument, 0, "load application under mountpoint in the specified worker or after workers spawn", uwsgi_opt_add_string_list, &uwsgi.mounts, 0},
@@ -859,6 +907,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"collect-header", required_argument, 0, "store the specified response header in a request var (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.collect_headers, 0},
{"response-header-collect", required_argument, 0, "store the specified response header in a request var (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.collect_headers, 0},
{"pull-header", required_argument, 0, "store the specified response header in a request var and remove it from the response (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.pull_headers, 0},
{"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
{"check-static-docroot", no_argument, 0, "check for static files in the requested DOCUMENT_ROOT", uwsgi_opt_true, &uwsgi.check_static_docroot, UWSGI_OPT_MIME},
{"static-check", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
@@ -912,6 +962,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"close-on-exec2", no_argument, 0, "set close-on-exec on server sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec2, 0},
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode, 0},
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
{"ienv", required_argument, 0, "set environment variable (IMMEDIATE version)", uwsgi_opt_set_env, NULL, UWSGI_OPT_IMMEDIATE},
{"envdir", required_argument, 0, "load a daemontools compatible envdir", uwsgi_opt_add_string_list, &uwsgi.envdirs, 0},
{"early-envdir", required_argument, 0, "load a daemontools compatible envdir ASAP", uwsgi_opt_envdir, NULL, UWSGI_OPT_IMMEDIATE},
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
@@ -928,7 +979,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"ns-net", required_argument, 0, "add network namespace", uwsgi_opt_set_str, &uwsgi.ns_net, 0},
#endif
{"enable-proxy-protocol", no_argument, 0, "enable PROXY1 protocol support (only for http parsers)", uwsgi_opt_true, &uwsgi.enable_proxy_protocol, 0},
{"reuse-port", no_argument, 0, "enable REUSE_PORT flag on socket (BSD only)", uwsgi_opt_true, &uwsgi.reuse_port, 0},
{"reuse-port", no_argument, 0, "enable REUSE_PORT flag on socket (BSD and Linux >3.9 only)", uwsgi_opt_true, &uwsgi.reuse_port, 0},
{"tcp-fast-open", required_argument, 0, "enable TCP_FASTOPEN flag on TCP sockets with the specified qlen value", uwsgi_opt_set_int, &uwsgi.tcp_fast_open, 0},
{"tcp-fastopen", required_argument, 0, "enable TCP_FASTOPEN flag on TCP sockets with the specified qlen value", uwsgi_opt_set_int, &uwsgi.tcp_fast_open, 0},
{"tcp-fast-open-client", no_argument, 0, "use sendto(..., MSG_FASTOPEN, ...) instead of connect() if supported", uwsgi_opt_true, &uwsgi.tcp_fast_open_client, 0},
@@ -1169,7 +1220,7 @@ void wait_for_threads() {
int sudden_death = 0;
pthread_mutex_lock(&uwsgi.six_feet_under_lock);
for (i = 0; i < uwsgi.threads; i++) {
for (i = 1; i < uwsgi.threads; i++) {
if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, pthread_self())) {
if (pthread_cancel(uwsgi.workers[uwsgi.mywid].cores[i].thread_id)) {
uwsgi_error("pthread_cancel()\n");
@@ -1182,7 +1233,7 @@ void wait_for_threads() {
goto end;
// wait for thread termination
for (i = 0; i < uwsgi.threads; i++) {
for (i = 1; i < uwsgi.threads; i++) {
if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, pthread_self())) {
ret = pthread_join(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, NULL);
if (ret) {
@@ -1191,6 +1242,22 @@ void wait_for_threads() {
}
}
// cancel inital thread last since after pthread_cancel() and
// pthread_join() is called on it, the whole process will appear to be
// a zombie. although it won't eliminate process zombie time, but it
// should minimize it.
if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[0].thread_id, pthread_self())) {
if (pthread_cancel(uwsgi.workers[uwsgi.mywid].cores[0].thread_id)) {
uwsgi_error("pthread_cancel() on initial thread\n");
goto end;
}
ret = pthread_join(uwsgi.workers[uwsgi.mywid].cores[0].thread_id, NULL);
if (ret) {
uwsgi_log("pthread_join() = %d on initial thread\n", ret);
}
}
end:
pthread_mutex_unlock(&uwsgi.six_feet_under_lock);
@@ -1212,7 +1279,7 @@ void gracefully_kill(int signum) {
}
// still not found a way to gracefully reload in async mode
if (uwsgi.async > 1) {
if (uwsgi.async > 0) {
exit(UWSGI_RELOAD_CODE);
}
@@ -1229,25 +1296,31 @@ void end_me(int signum) {
exit(UWSGI_END_CODE);
}
void simple_goodbye_cruel_world() {
static void simple_goodbye_cruel_world(const char *reason) {
if (uwsgi.threads > 1 && !uwsgi_instance_is_dying) {
wait_for_threads();
}
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
uwsgi_log("...The work of process %d is done. Seeya!\n", getpid());
uwsgi_log("...The work of process %d is done (%s). Seeya!\n", getpid(), (reason != NULL ? reason : "no reason given"));
exit(0);
}
void goodbye_cruel_world() {
void goodbye_cruel_world(const char *reason_fmt, ...) {
char reason[1024];
va_list args;
va_start(args, reason_fmt);
vsnprintf(reason, 1024, reason_fmt, args);
va_end(args);
uwsgi_curse(uwsgi.mywid, 0);
if (!uwsgi.gbcw_hook) {
simple_goodbye_cruel_world();
simple_goodbye_cruel_world(reason);
}
else {
uwsgi.gbcw_hook();
uwsgi.gbcw_hook(reason);
}
}
@@ -1458,7 +1531,7 @@ void what_i_am_doing() {
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage);
#endif
if (uwsgi.harakiri_options.workers > 0 && uwsgi.workers[uwsgi.mywid].harakiri < uwsgi_now()) {
if (uwsgi.harakiri_options.workers > 0 && uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].harakiri < uwsgi_now()) {
uwsgi_log("HARAKIRI: --- uWSGI worker %d core %d (pid: %d) WAS managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, i, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
}
else {
@@ -1475,14 +1548,14 @@ void what_i_am_doing() {
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage);
#endif
if (uwsgi.harakiri_options.workers > 0 && uwsgi.workers[uwsgi.mywid].harakiri < uwsgi_now()) {
if (uwsgi.harakiri_options.workers > 0 && uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].harakiri < uwsgi_now()) {
uwsgi_log("HARAKIRI: --- uWSGI worker %d (pid: %d) WAS managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
}
else {
uwsgi_log("SIGUSR2: --- uWSGI worker %d (pid: %d) is managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
}
}
else if (uwsgi.harakiri_options.workers > 0 && uwsgi.workers[uwsgi.mywid].harakiri < uwsgi_now() && uwsgi.workers[uwsgi.mywid].sig) {
else if (uwsgi.harakiri_options.workers > 0 && uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].harakiri < uwsgi_now() && uwsgi.workers[uwsgi.mywid].sig) {
uwsgi_log("HARAKIRI: --- uWSGI worker %d (pid: %d) WAS handling signal %d ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, uwsgi.workers[uwsgi.mywid].signum);
}
}
@@ -1571,6 +1644,22 @@ static void vacuum(void) {
uwsgi_log("VACUUM: pidfile2 removed.\n");
}
}
if (uwsgi.safe_pidfile && !uwsgi.uid) {
if (unlink(uwsgi.safe_pidfile)) {
uwsgi_error("unlink()");
}
else {
uwsgi_log("VACUUM: safe pidfile removed.\n");
}
}
if (uwsgi.safe_pidfile2) {
if (unlink(uwsgi.safe_pidfile2)) {
uwsgi_error("unlink()");
}
else {
uwsgi_log("VACUUM: safe pidfile2 removed.\n");
}
}
if (uwsgi.chdir) {
if (chdir(uwsgi.chdir)) {
uwsgi_error("chdir()");
@@ -1606,6 +1695,18 @@ next:
}
}
}
if (uwsgi.master_fifo) {
// also remove all master fifo
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.master_fifo) {
if (unlink(usl->value)) {
uwsgi_error("unlink()");
}
else {
uwsgi_log("VACUUM: master fifo %s removed.\n", usl->value);
}
}
}
}
}
}
@@ -1749,7 +1850,7 @@ void uwsgi_plugins_atexit(void) {
void uwsgi_backtrace(int depth) {
#if defined(__linux__) || (defined(__APPLE__) && !defined(NO_EXECINFO)) || defined(UWSGI_HAS_EXECINFO)
#if (defined(__GLIBC__) && !defined(__UCLIBC__))|| (defined(__APPLE__) && !defined(NO_EXECINFO)) || defined(UWSGI_HAS_EXECINFO)
#include <execinfo.h>
@@ -1987,6 +2088,7 @@ static char *uwsgi_at_file_read(char *filename) {
}
void uwsgi_setup(int argc, char *argv[], char *envp[]) {
#ifdef UWSGI_AS_SHARED_LIBRARY
#ifdef __APPLE__
char ***envPtr = _NSGetEnviron();
@@ -1996,7 +2098,6 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
int i;
struct utsname uuts;
// signal mask is inherited, and sme process manager could make a real mess...
sigset_t smask;
@@ -2167,6 +2268,8 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
struct group *gr = getgrgid(getgid());
uwsgi.magic_table['G'] = gr ? gr->gr_name : uwsgi.magic_table['g'];
configure:
// you can embed a ini file in the uWSGi binary with default options
#ifdef UWSGI_EMBED_CONFIG
uwsgi_ini_config("", uwsgi.magic_table);
@@ -2191,6 +2294,14 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
// ok, the options dictionary is available, lets manage it
uwsgi_configure();
// stop the execution until a connection arrives on the fork socket
if (uwsgi.fork_socket) {
uwsgi_log_verbose("waiting for fork-socket connections...\n");
uwsgi_fork_server(uwsgi.fork_socket);
// if we are here a new process has been spawned
goto configure;
}
// fixup cwd
if (uwsgi.force_cwd) uwsgi.cwd = uwsgi.force_cwd;
@@ -2259,6 +2370,13 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
// setup master logging
if (uwsgi.log_master)
uwsgi_setup_log_master();
else if (uwsgi.numproc == 1 && uwsgi.log_worker && uwsgi.master_process == 0) {
// hack for allowing request loggers
if (uwsgi.requested_req_logger)
uwsgi.req_log_master = 1;
uwsgi_setup_log_master();
uwsgi_threaded_logger_worker_spawn();
}
// setup offload engines
uwsgi_offload_engines_register_all();
@@ -2269,6 +2387,7 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
// setup cheaper algos
uwsgi_register_cheaper_algo("spare", uwsgi_cheaper_algo_spare);
uwsgi_register_cheaper_algo("spare2", uwsgi_cheaper_algo_spare2);
uwsgi_register_cheaper_algo("backlog", uwsgi_cheaper_algo_backlog);
uwsgi_register_cheaper_algo("manual", uwsgi_cheaper_algo_manual);
@@ -2340,6 +2459,10 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
uwsgi_log_initial("compiled with version: %s on %s\n", __VERSION__, UWSGI_BUILD_DATE);
#ifdef __RUMP__
uwsgi_log_initial("Rump system detected\n");
#else
struct utsname uuts;
#ifdef __sun__
if (uname(&uuts) < 0) {
#else
@@ -2352,6 +2475,7 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
uwsgi_log_initial("nodename: %s\n", uuts.nodename);
uwsgi_log_initial("machine: %s\n", uuts.machine);
}
#endif
uwsgi_log_initial("clock source: %s\n", uwsgi.clock->name);
#ifdef UWSGI_PCRE
@@ -2479,6 +2603,10 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
#if defined(__linux__) && !defined(__ia64__)
}
#endif
if (uwsgi.safe_pidfile && !uwsgi.is_a_reload) {
uwsgi_write_pidfile_explicit(uwsgi.safe_pidfile, masterpid);
}
}
@@ -2537,6 +2665,11 @@ int uwsgi_start(void *v_argv) {
uwsgi_as_root();
}
// wait for socket
uwsgi_foreach(usl, uwsgi.wait_for_socket) {
if (uwsgi_wait_for_socket(usl->value)) exit(1);
}
if (uwsgi.logto2) {
if (!uwsgi.is_a_reload || uwsgi.log_reopen) {
logto(uwsgi.logto2);
@@ -2555,10 +2688,13 @@ int uwsgi_start(void *v_argv) {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
#ifndef __RUMP__
if (!uwsgi.master_process && !uwsgi.command_mode) {
uwsgi_log_initial("*** WARNING: you are running uWSGI without its master process manager ***\n");
}
#endif
#ifndef __RUMP__
#ifdef RLIMIT_NPROC
if (uwsgi.rl_nproc.rlim_max > 0) {
uwsgi.rl_nproc.rlim_cur = uwsgi.rl_nproc.rlim_max;
@@ -2578,6 +2714,8 @@ int uwsgi_start(void *v_argv) {
}
}
#endif
#endif
#ifndef __OpenBSD__
if (uwsgi.rl.rlim_max > 0) {
@@ -2656,7 +2794,7 @@ int uwsgi_start(void *v_argv) {
}
}
if (uwsgi.async > 1) {
if (uwsgi.async > 0) {
if ((unsigned long) uwsgi.max_fd < (unsigned long) uwsgi.async) {
uwsgi_log_initial("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
uwsgi.rl.rlim_cur = uwsgi.async;
@@ -2910,8 +3048,23 @@ unsafe:
uwsgi_log("your server socket listen backlog is limited to %d connections\n", uwsgi.listen_queue);
#endif
uwsgi_log("your mercy for graceful operations on workers is %d seconds\n", uwsgi.worker_reload_mercy);
uwsgi_log("your request buffer size is %llu bytes\n", (unsigned long long) uwsgi.buffer_size);
if (!uwsgi.__buffer_size) {
if (uwsgi.buffer_size > 0xffff) {
uwsgi_log("your request buffer size for old plugins has been limited to 64k\n");
uwsgi.__buffer_size = 0xffff;
}
else {
uwsgi.__buffer_size = uwsgi.buffer_size;
}
}
else {
uwsgi_log("your request buffer size for old plugins is %u bytes\n", uwsgi.__buffer_size);
}
if (uwsgi.crons) {
struct uwsgi_cron *ucron = uwsgi.crons;
while (ucron) {
@@ -2964,7 +3117,7 @@ unsafe:
uwsgi_log("*** Operational MODE: threaded ***\n");
}
}
else if (uwsgi.async > 1) {
else if (uwsgi.async > 0) {
if (uwsgi.numproc > 1) {
uwsgi_log("*** Operational MODE: preforking+async ***\n");
}
@@ -3144,6 +3297,8 @@ next:
while (uspool) {
if (uspool->mode == UWSGI_SPOOLER_EXTERNAL)
goto next2;
// skip spooler start on cheap mode
if (uwsgi.spooler_cheap) goto next2;
uspool->pid = spooler_start(uspool);
next2:
uspool = uspool->next;
@@ -3199,12 +3354,33 @@ next2:
}
}
if (uwsgi.safe_pidfile2 && !uwsgi.is_a_reload) {
uwsgi_write_pidfile_explicit(uwsgi.safe_pidfile2, masterpid);
}
// END OF INITIALIZATION
return 0;
}
// this lives in a worker thread and periodically scans for memory usage
// when evil reloaders are in place
void *mem_collector(void *foobar) {
// block all signals
sigset_t smask;
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
uwsgi_log_verbose("mem-collector thread started for worker %d\n", uwsgi.mywid);
for(;;) {
sleep(uwsgi.mem_collector_freq);
uint64_t rss = 0, vsz = 0;
get_memusage(&rss, &vsz);
uwsgi.workers[uwsgi.mywid].rss_size = rss;
uwsgi.workers[uwsgi.mywid].vsz_size = vsz;
}
return NULL;
}
int uwsgi_run() {
// !!! from now on, we could be in the master or in a worker !!!
@@ -3231,6 +3407,11 @@ int uwsgi_run() {
}
#endif
if (uwsgi.evil_reload_on_rss || uwsgi.evil_reload_on_as) {
pthread_t t;
pthread_create(&t, NULL, mem_collector, NULL);
}
// eventually maps (or disable) sockets for the worker
uwsgi_map_sockets();
@@ -3334,7 +3515,7 @@ void uwsgi_worker_run() {
// some apps could be mounted only on specific workers
uwsgi_init_worker_mount_apps();
if (uwsgi.async > 1) {
if (uwsgi.async > 0) {
// a stack of unused cores
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
@@ -3478,7 +3659,7 @@ void uwsgi_ignition() {
uwsgi_log("your loop engine died. R.I.P.\n");
}
else {
if (uwsgi.async < 2) {
if (uwsgi.async < 1) {
simple_loop();
}
else {
@@ -3709,8 +3890,8 @@ void uwsgi_init_all_apps() {
what++;
for (j = 0; j < 256; j++) {
if (uwsgi.p[j]->mount_app) {
uwsgi_log("mounting %s on %s\n", what, app_mps->value);
if (uwsgi.p[j]->mount_app(app_mps->value, what) != -1)
uwsgi_log("mounting %s on %s\n", what, app_mps->value[0] == 0 ? "/" : app_mps->value);
if (uwsgi.p[j]->mount_app(app_mps->value[0] == 0 ? "/" : app_mps->value, what) != -1)
break;
}
}
@@ -3969,6 +4150,11 @@ void uwsgi_opt_set_16bit(char *opt, char *value, void *key) {
void uwsgi_opt_set_megabytes(char *opt, char *value, void *key) {
uint64_t *ptr = (uint64_t *) key;
if(strchr(value, '.') != NULL) {
double megabytes = atof(value);
*ptr = (uint64_t)(megabytes * 1024 * 1024);
return;
}
*ptr = (uint64_t)strtoul(value, NULL, 10) * 1024 * 1024;
}
@@ -4000,6 +4186,11 @@ void uwsgi_opt_set_logger(char *opt, char *value, void *prefix) {
}
}
void uwsgi_opt_set_worker_logger(char *opt, char *value, void *prefix) {
uwsgi_opt_set_logger(opt, value, prefix);
uwsgi.log_worker = 1;
}
void uwsgi_opt_set_req_logger(char *opt, char *value, void *prefix) {
if (!value)
@@ -4408,6 +4599,7 @@ int uwsgi_zerg_attach(char *value) {
if (zerg == NULL) {
uwsgi_log("--- invalid data received from zerg-server ---\n");
close(zerg_fd);
return -1;
}
@@ -4703,7 +4895,7 @@ extern char *uwsgi_dot_h;
char *uwsgi_get_dot_h() {
char *src = uwsgi_dot_h;
size_t len = strlen(src);
char *ptr = uwsgi_malloc(len / 2);
char *ptr = uwsgi_malloc((len / 2) + 1);
char *base = ptr;
size_t i;
unsigned int u;
@@ -4724,6 +4916,9 @@ char *uwsgi_get_dot_h() {
base = ub->buf;
ub->buf = NULL;
uwsgi_buffer_destroy(ub);
#else
// add final null byte
*ptr = '\0';
#endif
return base;
}
@@ -4736,7 +4931,7 @@ extern char *uwsgi_config_py;
char *uwsgi_get_config_py() {
char *src = uwsgi_config_py;
size_t len = strlen(src);
char *ptr = uwsgi_malloc(len / 2);
char *ptr = uwsgi_malloc((len / 2) + 1);
char *base = ptr;
size_t i;
unsigned int u;
@@ -4757,6 +4952,9 @@ char *uwsgi_get_config_py() {
base = ub->buf;
ub->buf = NULL;
uwsgi_buffer_destroy(ub);
#else
// add final null byte
*ptr = '\0';
#endif
return base;
}
@@ -4834,6 +5032,12 @@ void uwsgi_update_pidfiles() {
if (uwsgi.pidfile2) {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
if (uwsgi.safe_pidfile) {
uwsgi_write_pidfile(uwsgi.safe_pidfile);
}
if (uwsgi.safe_pidfile2) {
uwsgi_write_pidfile(uwsgi.safe_pidfile2);
}
}
void uwsgi_opt_binary_append_data(char *opt, char *value, void *none) {
+110
View File
@@ -0,0 +1,110 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
The following functions are useful to implement simil-webdav support in plugins.
Most of them are not fully webdav compliant, but will work on the vast majority of clients.
*/
// a multi-status response (207) will return an xml with a list
// of <D:response> stanzas
struct uwsgi_buffer *uwsgi_webdav_multistatus_new() {
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
if (uwsgi_buffer_append(ub, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n", 40)) goto error;
if (uwsgi_buffer_append(ub, "<D:multistatus xmlns:D=\"DAV:\">\n", 31)) goto error;
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
int uwsgi_webdav_multistatus_close(struct uwsgi_buffer *ub) {
if (uwsgi_buffer_append(ub, "</D:multistatus>\n", 17)) return -1;
return 0;
}
int uwsgi_webdav_multistatus_response_new(struct uwsgi_buffer *ub) {
if (uwsgi_buffer_append(ub, "<D:response>\n", 13)) return -1;
return 0;
}
int uwsgi_webdav_multistatus_response_close(struct uwsgi_buffer *ub) {
if (uwsgi_buffer_append(ub, "</D:response>\n", 14)) return -1;
return 0;
}
int uwsgi_webdav_multistatus_propstat_new(struct uwsgi_buffer *ub) {
if (uwsgi_buffer_append(ub, "<D:propstat>\n", 13)) return -1;
return 0;
}
int uwsgi_webdav_multistatus_propstat_close(struct uwsgi_buffer *ub) {
if (uwsgi_buffer_append(ub, "</D:propstat>\n", 14)) return -1;
return 0;
}
int uwsgi_webdav_multistatus_prop_new(struct uwsgi_buffer *ub) {
if (uwsgi_buffer_append(ub, "<D:prop>\n", 9)) return -1;
return 0;
}
int uwsgi_webdav_multistatus_prop_close(struct uwsgi_buffer *ub) {
if (uwsgi_buffer_append(ub, "</D:prop>\n", 10)) return -1;
return 0;
}
// shortcut for adding a propfind-response item
int uwsgi_webdav_propfind_item_add(struct uwsgi_buffer *ub, char *href, uint16_t href_len, uint64_t cl, time_t mtime, char *ctype, uint16_t ctype_len, char *displayname, uint16_t displayname_len, char *etag, uint16_t etag_len) {
if (uwsgi_webdav_multistatus_response_new(ub)) return -1;
if (uwsgi_buffer_append(ub, "<D:href>", 8)) return -1;
if (uwsgi_buffer_append(ub, href, href_len)) return -1;
if (uwsgi_buffer_append(ub, "</D:href>\n", 10)) return -1;
if (uwsgi_webdav_multistatus_propstat_new(ub)) return -1;
if (uwsgi_webdav_multistatus_prop_new(ub)) return -1;
if (href[href_len-1] == '/') {
if (uwsgi_buffer_append(ub, "<D:resourcetype><D:collection/></D:resourcetype>\n", 49)) return -1;
}
else {
// getcontentlength
if (uwsgi_buffer_append(ub, "<D:getcontentlength>", 20)) return -1;
if (uwsgi_buffer_num64(ub, cl)) return -1;
if (uwsgi_buffer_append(ub, "</D:getcontentlength>\n", 22)) return -1;
}
// getlastmodified
if (mtime > 0) {
if (uwsgi_buffer_append(ub, "<D:getlastmodified>", 19)) return -1;
if (uwsgi_buffer_httpdate(ub, mtime)) return -1;
if (uwsgi_buffer_append(ub, "</D:getlastmodified>\n", 21)) return -1;
}
// displayname
if (displayname_len > 0) {
if (uwsgi_buffer_append(ub, "<D:displayname>\n", 16)) return -1;
if (uwsgi_buffer_append_xml(ub, displayname, displayname_len)) return -1;
if (uwsgi_buffer_append(ub, "</D:displayname>\n", 17)) return -1;
}
if (ctype_len > 0) {
if (uwsgi_buffer_append(ub, "<D:getcontenttype>", 18)) return -1;
if (uwsgi_buffer_append(ub, ctype, ctype_len)) return -1;
if (uwsgi_buffer_append(ub, "</D:getcontenttype>\n", 20)) return -1;
}
if (etag_len > 0) {
if (uwsgi_buffer_append(ub, "<D:getetag>\n", 12)) return -1;
if (uwsgi_buffer_append_xml(ub, etag, etag_len)) return -1;
if (uwsgi_buffer_append(ub, "</D:getetag>\n", 13)) return -1;
}
if (uwsgi_webdav_multistatus_prop_close(ub)) return -1;
if (uwsgi_webdav_multistatus_propstat_close(ub)) return -1;
if (uwsgi_webdav_multistatus_response_close(ub)) return -1;
return 0;
}
+1
View File
@@ -273,6 +273,7 @@ static struct uwsgi_buffer *uwsgi_websocket_recv_do(struct wsgi_request *wsgi_re
}
else {
wsgi_req->websocket_need += wsgi_req->websocket_size;
wsgi_req->websocket_pktsize += wsgi_req->websocket_size;
wsgi_req->websocket_phase = 4;
}
break;
+10 -1
View File
@@ -124,9 +124,18 @@ error:
static int uwsgi_response_add_header_do(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
// collect the header ?
// pull/collect the header ?
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.pull_headers) {
if (!uwsgi_strnicmp(key, key_len, usl->value, usl->custom)) {
if (!uwsgi_req_append(wsgi_req, usl->custom_ptr, usl->custom2, value, value_len)) {
wsgi_req->write_errors++ ; return -1;
}
return 0;
}
}
uwsgi_foreach(usl, uwsgi.collect_headers) {
if (!uwsgi_strnicmp(key, key_len, usl->value, usl->custom)) {
if (!uwsgi_req_append(wsgi_req, usl->custom_ptr, usl->custom2, value, value_len)) {
+25 -3
View File
@@ -1,3 +1,5 @@
#include <uwsgi.h>
/*
*** WORK IN PROGRESS ***
@@ -16,11 +18,11 @@
# unencrypted mode
uwsgi --zeus "192.168.173.17:4040 /etc/uwsgi/vassals"
uwsgi --zeus 192.168.173.17:4040 --emperor /etc/uwsgi/vassals
# crypted mode
uwsgi --zeus "192.168.173.17:4040,foobar.crt,foobar.key /etc/uwsgi/vassals"
uwsgi --zeus 192.168.173.17:4040,foobar.crt,foobar.key --emperor /etc/uwsgi/vassals
# crypted + authentication mode
uwsgi --zeus "192.168.173.17:4040,foobar.crt,foobar.key,clients.pem /etc/uwsgi/vassals"
uwsgi --zeus 192.168.173.17:4040,foobar.crt,foobar.key,clients.pem --emperor /etc/uwsgi/vassals
to connect an Emperor to Zeus
@@ -64,3 +66,23 @@
11 -> VASSAL_DESTROYED {name: 'foobar.ini'} [the choosen emperor -> zeus]
*/
/*
check how many nodes the instace needs (default 1)
*/
int uwsgi_zeus_spawn_instance(struct uwsgi_instance *ui) {
int i, nodes = 1;
char *how_many_nodes = vassal_attr_get(ui, "zeus-nodes");
if (how_many_nodes) {
nodes = atoi(how_many_nodes);
}
for(i=0;i<nodes;i++) {
// now start analyzing nodes, the one with most
// free slots will be used
// send NEW_VASSAL request to the node,
// if it answers with ACCEPTED_VASSAL
}
return 0;
}
+2
View File
@@ -2,10 +2,12 @@ from flask import Flask, request
app = Flask(__name__)
app.debug = True
@app.route('/')
def hello_world():
return "<form method='POST' enctype='multipart/form-data' action='/upload'><input type='text' name='pippo'/><input type='file' name='ufile'/><input type='submit' value='upload'/></form>"
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
return str(len(request.form.get('pippo', 'boh'))) + request.form.get('pippo', 'boh')
+7 -1
View File
@@ -3,12 +3,18 @@ import werkzeug.testapp
uwsgi.cache_set("/cache/get", "HTTP 1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>I am the uWSGI cache</h1>")
def app001(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return "PATH_INFO=%s" % env['PATH_INFO']
def app002(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return "requests: %d" % uwsgi.total_requests()
uwsgi.applications = { '':werkzeug.testapp.test_app, '/app001':app001, '/app002':app002 }
uwsgi.applications = {
'': werkzeug.testapp.test_app,
'/app001': app001,
'/app002': app002
}
+16 -18
View File
@@ -1,25 +1,23 @@
import uwsgi
import os
def application(env, start_response):
boundary = 'uwsgi_mjpeg_frame'
boundary = 'uwsgi_mjpeg_frame'
start_response('200 Ok', [
start_response('200 Ok', [
('Cache-Control', 'no-cache'),
('Cache-Control', 'private'),
('Pragma', 'no-cache'),
('Content-Type', 'multipart/x-mixed-replace; boundary=' + boundary),
])
('Cache-Control', 'no-cache'),
('Cache-Control', 'private'),
('Pragma', 'no-cache'),
('Content-Type', 'multipart/x-mixed-replace; boundary=' + boundary),
]
)
yield "--%s\r\n" % boundary
yield "--%s\r\n" % boundary
while 1:
yield "Content-Type: image/jpeg\r\n\r\n"
print os.system('screencapture -t jpg -m -T 1 screenshot.jpg')
f = open('screenshot.jpg')
yield env['wsgi.file_wrapper'](f)
yield "\r\n--%s\r\n" % boundary
#os.system('./isightcapture -w 640 -h 480 screenshot.jpg')
while 1:
yield "Content-Type: image/jpeg\r\n\r\n"
print os.system('screencapture -t jpg -m -T 1 screenshot.jpg')
f = open('screenshot.jpg')
yield env['wsgi.file_wrapper'](f)
yield "\r\n--%s\r\n" % boundary
# os.system('./isightcapture -w 640 -h 480 screenshot.jpg')
+15 -7
View File
@@ -1,22 +1,30 @@
import werkzeug
import uwsgi
def zero_app(e,s):
s('200 OK', [ ('Content-Type', 'text/plain') ])
def zero_app(e, s):
s('200 OK', [('Content-Type', 'text/plain')])
return "0"
def not_found(e,s):
s('404 Not Found', [ ('Content-Type', 'text/plain') ])
def not_found(e, s):
s('404 Not Found', [('Content-Type', 'text/plain')])
return ""
def wsgi_app(e, s):
s('200 OK', [ ('Content-Type', 'text/plain') ])
s('200 OK', [('Content-Type', 'text/plain')])
yield "I am a WSGI app\n"
def internal_server_error(e, s):
s('500 Internal Server Error', [ ('Content-Type', 'text/plain') ])
s('500 Internal Server Error', [('Content-Type', 'text/plain')])
return ""
uwsgi.applications = {'/wsgi':wsgi_app, '/test':werkzeug.test_app, '/zero':zero_app, '/notfound':not_found, '/ise':internal_server_error}
uwsgi.applications = {
'/wsgi': wsgi_app,
'/test': werkzeug.test_app,
'/zero': zero_app,
'/notfound': not_found,
'/ise': internal_server_error
}
+4 -4
View File
@@ -3,9 +3,11 @@ import os
print("!!! uWSGI version:", uwsgi.version)
def ciao():
print("modifica su /tmp")
def ciao2():
print("nuovo uwsgi_server")
print os.getpid()
@@ -23,17 +25,15 @@ counter = 0
uwsgi.post_fork_hook = ciao2
def application(env, start_response):
def application(env, start_response):
global counter
#print(env)
start_response('200 Ok', [('Content-type', 'text/plain')])
yield "hello world"
yield "hello world2"
for i in range(1,1000):
for i in range(1, 1000):
yield str(i)
yield "\n"
+3 -3
View File
@@ -1,9 +1,9 @@
def mygen(uri):
for i in xrange(1,100):
for i in xrange(1, 100):
yield "ciao %s<br/>" % uri
def application(env, start_response = None):
def application(env, start_response=None):
return '200 OK', [('Content-Type', 'text/html')], "<h1>This is the fastest homepage of the world !!!</h1>"
#return '200 OK', [('Content-Type', 'text/html')], mygen(env['PATH_INFO'])
# return '200 OK', [('Content-Type', 'text/html')], mygen(env['PATH_INFO'])
+2 -1
View File
@@ -1,6 +1,7 @@
import uwsgi
def print_logs(ip, port, message):
print(ip, port, message)
print(ip, port, message)
uwsgi.udp_callable = print_logs
+3 -2
View File
@@ -4,10 +4,11 @@ from os import path
uwsgi.snmp_set_counter64(1, 0) # Number of requests
uwsgi.snmp_set_counter64(2, 0) # Number of bytes
def application(environ, start_response):
size = path.getsize('logo_uWSGI.png')
start_response('200 OK', [('Content-Type', 'image/png'), ('Content-Length', str(size))] )
fd = open('logo_uWSGI.png','r')
start_response('200 OK', [('Content-Type', 'image/png'), ('Content-Length', str(size))])
fd = open('logo_uWSGI.png', 'r')
uwsgi.snmp_incr_counter64(1)
uwsgi.snmp_incr_counter64(2, size)
return environ['wsgi.file_wrapper'](fd, 4096)
+5 -4
View File
@@ -4,22 +4,24 @@ import uwsgi
CONSUMERS = 4
def consumer(q):
while True:
item = q.get()
print(item)
#... DO A HEAVY TASK HERE ...
# ... DO A HEAVY TASK HERE ...
q.task_done()
def spawn_consumers():
global q
q = Queue.Queue()
for i in range(CONSUMERS):
t = Thread(target=consumer,args=(q,))
t = Thread(target=consumer, args=(q,))
t.daemon = True
t.start()
print("consumer %d on worker %d started" % (i, uwsgi.worker_id()))
uwsgi.post_fork_hook = spawn_consumers
@@ -33,4 +35,3 @@ def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
yield "Task enqueued"
+60 -62
View File
@@ -1,78 +1,76 @@
import uwsgi
def application(env, start_response):
# open the socket
fd = uwsgi.async_connect("192.168.173.100:3032")
# open the socket
fd = uwsgi.async_connect("192.168.173.100:3032")
# wait for connection ready (3s timeout)
yield uwsgi.wait_fd_write(fd, 3)
# wait for connection ready (3s timeout)
yield uwsgi.wait_fd_write(fd, 3)
# has timed out ?
if env['x-wsgiorg.fdevent.timeout']:
print "connection timed out !!!"
uwsgi.close(fd)
raise StopIteration
# has timed out ?
if env['x-wsgiorg.fdevent.timeout']:
print "connection timed out !!!"
uwsgi.close(fd)
raise StopIteration
# connection refused ?
if not uwsgi.is_connected(fd):
print "unable to connect"
uwsgi.close(fd)
raise StopIteration
# connection refused ?
if not uwsgi.is_connected(fd):
print "unable to connect"
uwsgi.close(fd)
raise StopIteration
# send request
# env can contains python objects, but send_message will discard them.
# In this way we will automagically have a congruent and valid uwsgi packet
uwsgi.async_send_message(fd, 0, 0, env)
# send request
# env can contains python objects, but send_message will discard them.
# In this way we will automagically have a congruent and valid uwsgi packet
uwsgi.async_send_message(fd, 0, 0, env)
# send the http body
# ready body in async mode and resend to fd
# uwsgi.recv will use always an internal buffer of 4096, but can be limited in the number of bytes to read
# send the http body
# ready body in async mode and resend to fd
# uwsgi.recv will use always an internal buffer of 4096, but can be limited in the number of bytes to read
# does this request has a body ?
cl = uwsgi.cl()
# does this request has a body ?
cl = uwsgi.cl()
if cl > 0:
# get the input fd
input = env['wsgi.input'].fileno()
if cl > 0:
# get the input fd
input = env['wsgi.input'].fileno()
# read (in async mode) upto 'cl' data and send to uwsgi peer
while cl > 0:
bufsize = min(cl, 4096)
yield uwsgi.wait_fd_read(input, 30)
if env['x-wsgiorg.fdevent.timeout']:
print "connection timed out !!!"
uwsgi.close(fd)
raise StopIteration
body = uwsgi.recv(input, bufsize)
if body:
uwsgi.send(fd, body)
cl = cl - len(body)
else:
break
# read (in async mode) upto 'cl' data and send to uwsgi peer
while cl > 0:
bufsize = min(cl, 4096)
yield uwsgi.wait_fd_read(input, 30)
if env['x-wsgiorg.fdevent.timeout']:
print "connection timed out !!!"
uwsgi.close(fd)
raise StopIteration
body = uwsgi.recv(input, bufsize)
if body:
uwsgi.send(fd, body)
cl = cl - len(body)
else:
break
# wait for response (30s timeout)
yield uwsgi.wait_fd_read(fd, 30)
# wait for response (30s timeout)
yield uwsgi.wait_fd_read(fd, 30)
# has timed out ?
if env['x-wsgiorg.fdevent.timeout']:
print "connection timed out !!!"
uwsgi.close(fd)
raise StopIteration
# has timed out ?
if env['x-wsgiorg.fdevent.timeout']:
print "connection timed out !!!"
uwsgi.close(fd)
raise StopIteration
data = uwsgi.recv(fd)
# recv the data, if it returns None the callable will end
while data:
yield data
# wait for response
yield uwsgi.wait_fd_read(fd, 30)
if env['x-wsgiorg.fdevent.timeout']:
print "connection timed out !!!"
uwsgi.close(fd)
raise StopIteration
data = uwsgi.recv(fd)
data = uwsgi.recv(fd)
# recv the data, if it returns None the callable will end
while data:
yield data
# wait for response
yield uwsgi.wait_fd_read(fd, 30)
if env['x-wsgiorg.fdevent.timeout']:
print "connection timed out !!!"
uwsgi.close(fd)
raise StopIteration
data = uwsgi.recv(fd)
uwsgi.close(fd)
uwsgi.close(fd)
+3 -3
View File
@@ -2,7 +2,7 @@
import uwsgi
def application(e,s):
def application(e, s):
for part in uwsgi.send_message("192.168.173.100:3032", 0, 0, e, 0, e['wsgi.input'].fileno(), uwsgi.cl()):
yield part
for part in uwsgi.send_message("192.168.173.100:3032", 0, 0, e, 0, e['wsgi.input'].fileno(), uwsgi.cl()):
yield part
+14 -13
View File
@@ -3,23 +3,24 @@ import uwsgi
current_node = 0
def application(e,s):
global current_node
def application(e, s):
nodes = uwsgi.cluster_nodes()
print nodes
global current_node
if len(nodes) == 0:
print "no cluster node available"
raise StopIteration
nodes = uwsgi.cluster_nodes()
print nodes
if current_node >= len(nodes):
current_node = 0
if len(nodes) == 0:
print "no cluster node available"
raise StopIteration
node = nodes[current_node]
if current_node >= len(nodes):
current_node = 0
for part in uwsgi.send_message(node, 0, 0, e, 0, e['wsgi.input'].fileno(), uwsgi.cl()):
yield part
node = nodes[current_node]
current_node+=1
for part in uwsgi.send_message(node, 0, 0, e, 0, e['wsgi.input'].fileno(), uwsgi.cl()):
yield part
current_node += 1
+9 -8
View File
@@ -1,14 +1,15 @@
import uwsgi
def application(e,s):
node = uwsgi.cluster_best_node()
print node
def application(e, s):
if not node:
print "sorry node unavailable"
raise StopIteration
node = uwsgi.cluster_best_node()
print node
for part in uwsgi.send_message(node, 0, 0, e, 0, e['wsgi.input'].fileno(), uwsgi.cl()):
yield part
if not node:
print "sorry node unavailable"
raise StopIteration
for part in uwsgi.send_message(node, 0, 0, e, 0, e['wsgi.input'].fileno(), uwsgi.cl()):
yield part
+4 -3
View File
@@ -3,7 +3,8 @@ import uwsgi
fd = uwsgi.connect("127.0.0.1:3033")
def application(e,s):
for part in uwsgi.send_message(fd, 0, 4, e, 30, e['wsgi.input'].fileno(), uwsgi.cl()):
yield part
def application(e, s):
for part in uwsgi.send_message(fd, 0, 4, e, 30, e['wsgi.input'].fileno(), uwsgi.cl()):
yield part
+5 -5
View File
@@ -36,7 +36,7 @@ def application(env, start_response):
yield "<h2>Hooks</h2>"
for h in range(0,255):
for h in range(0, 255):
if uwsgi.has_hook(h):
yield "%d<br/>" % h
@@ -45,15 +45,15 @@ def application(env, start_response):
yield '<table border="1">'
yield '<th>worker id</th><th>pid</th><th>in request</th><th>requests</th><th>running time</th><th>address space</th><th>rss</th>'
workers = uwsgi.workers();
workers = uwsgi.workers()
yield '<h2>workers</h2>'
for w in workers:
#print w
#print w['running_time']
# print w
# print w['running_time']
if w is not None:
yield '<tr><td>'+ str(w['id']) +'</td><td>' + str(w['pid']) + '</td><td>' + str(w['pid']) + '</td><td>' + str(w['requests']) + '</td><td>' + str(w['running_time']) + '</td><td>' + str(w['vsz']) + '</td><td>' + str(w['rss']) + '</td></tr>'
yield '<tr><td>' + str(w['id']) + '</td><td>' + str(w['pid']) + '</td><td>' + str(w['pid']) + '</td><td>' + str(w['requests']) + '</td><td>' + str(w['running_time']) + '</td><td>' + str(w['vsz']) + '</td><td>' + str(w['rss']) + '</td></tr>'
print w
yield '</table>'
+13 -11
View File
@@ -2,7 +2,8 @@ import uwsgi
import os
import gc
import sys
from uwsgidecorators import *
from uwsgidecorators import rpc, signal, postfork
print(sys.version)
print(sys.version_info)
if 'set_debug' in gc.__dict__:
@@ -26,6 +27,7 @@ def after_request_hook():
uwsgi.after_req_hook = after_request_hook
@rpc('hello')
def hello_rpc(one, two, three):
arg0 = one[::-1]
@@ -33,20 +35,24 @@ def hello_rpc(one, two, three):
arg2 = three[::-1]
return "!%s-%s-%s!" % (arg1, arg2, arg0)
@signal(17)
def ciao_mondo(signum):
print("Hello World")
def xsendfile(e, sr):
sr('200 OK', [('Content-Type', 'image/png'), ('X-Sendfile', os.path.abspath('logo_uWSGI.png'))])
return ''
def serve_logo(e, sr):
# use raw facilities (status will not be set...)
uwsgi.send("%s 200 OK\r\nContent-Type: image/png\r\n\r\n" % e['SERVER_PROTOCOL'])
uwsgi.sendfile('logo_uWSGI.png')
return ''
def serve_config(e, sr):
sr('200 OK', [('Content-Type', 'text/html')])
for opt in uwsgi.opt.keys():
@@ -57,11 +63,13 @@ routes['/xsendfile'] = xsendfile
routes['/logo'] = serve_logo
routes['/config'] = serve_config
@postfork
def setprocname():
if uwsgi.worker_id() > 0:
uwsgi.setprocname("i am the worker %d" % uwsgi.worker_id())
def application(env, start_response):
try:
uwsgi.mule_msg(env['REQUEST_URI'], 1)
@@ -82,7 +90,6 @@ def application(env, start_response):
if env['PATH_INFO'] in routes:
return routes[env['PATH_INFO']](env, start_response)
if DEBUG:
print(env['wsgi.input'].fileno())
@@ -98,7 +105,7 @@ def application(env, start_response):
for w in uwsgi.workers():
apps = '<table border="1"><tr><th>id</th><th>mountpoint</th><th>startup time</th><th>requests</th></tr>'
for app in w['apps']:
apps += '<tr><td>%d</td><td>%s</td><td>%d</td><td>%d</td></tr>' % (app['id'], app['mountpoint'], app['startup_time'], app['requests'])
apps += '<tr><td>%d</td><td>%s</td><td>%d</td><td>%d</td></tr>' % (app['id'], app['mountpoint'], app['startup_time'], app['requests'])
apps += '</table>'
workers += """
<tr>
@@ -122,14 +129,9 @@ Workers and applications<br/>
%s
</table>
""" % (uwsgi.version, uwsgi.hostname, env.get('REMOTE_USER','None'), workers)
""" % (uwsgi.version, uwsgi.hostname, env.get('REMOTE_USER', 'None'), workers)
start_response('200 OK', [('Content-Type', 'text/html'), ('Content-Length', str(len(output)) )])
start_response('200 OK', [('Content-Type', 'text/html'), ('Content-Length', str(len(output)))])
#return bytes(output.encode('latin1'))
# return bytes(output.encode('latin1'))
return output
+4 -6
View File
@@ -1,14 +1,17 @@
import uwsgi
import os
def xsendfile(e, sr):
sr('200 OK', [('Content-Type', 'image/png'), ('X-Sendfile', os.path.abspath('logo_uWSGI.png'))])
return b''
def serve_logo(e, sr):
sr('200 OK', [('Content-Type', 'image/png')])
return uwsgi.sendfile('logo_uWSGI.png')
def serve_config(e, sr):
sr('200 OK', [('Content-Type', 'text/html')])
for opt in uwsgi.opt.keys():
@@ -20,6 +23,7 @@ routes['/xsendfile'] = xsendfile
routes['/logo'] = serve_logo
routes['/config'] = serve_config
def application(env, start_response):
if env['PATH_INFO'] in routes:
@@ -39,9 +43,3 @@ Configuration<br/>
""".format(version=uwsgi.version.decode('ascii'))
return bytes(body.encode('ascii'))
+1 -1
View File
@@ -1,6 +1,6 @@
require 'net/http'
Net::HTTP.start("uwsgi.it") do |http|
Net::HTTP.start("uwsgi.it", :use_ssl=>true) do |http|
resp = http.get("/install")
open("install.sh", "wb") do |file|
file.write(resp.body)
-4
View File
@@ -179,10 +179,6 @@ char *uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut) {
}
}
// skip empty lines
if (!p)
goto next;
line_node = xmlNewChild(node, NULL, BAD_CAST "line", NULL);
if ((n+1)[0] == ')') {
+5 -3
View File
@@ -1,9 +1,11 @@
from uwsgiconfig import spcall
NAME='airbrake'
NAME = 'airbrake'
CFLAGS = [spcall('xml2-config --cflags')]
LDFLAGS = []
LIBS = ['-lcurl', spcall('xml2-config --libs')]
LIBS = [
'-lcurl',
spcall('xml2-config --libs')
]
GCC_LIST = ['airbrake_plugin']
+1 -1
View File
@@ -92,7 +92,7 @@ static struct uwsgi_alarm_curl_opt uaco[] = {
static void uwsgi_alarm_curl_setopt(CURL *curl, char *opt, struct uwsgi_alarm_curl_config *uacc) {
struct uwsgi_alarm_curl_opt *o = uaco;
char *equal = strchr(opt,'=');
if (!equal && !uacc->url) {
if (!equal || !uacc->url) {
uwsgi_alarm_curl_url(curl, CURLOPT_URL, opt, uacc);
return;
}
+1 -1
View File
@@ -1,4 +1,4 @@
NAME='alarm_curl'
NAME = 'alarm_curl'
CFLAGS = []
LDFLAGS = []
+1 -1
View File
@@ -1,6 +1,6 @@
import os
NAME='alarm_speech'
NAME = 'alarm_speech'
uwsgi_os = os.uname()[0]
+1 -1
View File
@@ -1,4 +1,4 @@
NAME='alarm_xmpp'
NAME = 'alarm_xmpp'
CFLAGS = []
LDFLAGS = []
+3 -3
View File
@@ -205,7 +205,7 @@ static PyObject *py_uwsgi_asyncio_accept(PyObject *self, PyObject *args) {
// enter harakiri mode
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
set_harakiri(wsgi_req, uwsgi.harakiri_options.workers);
}
uwsgi.async_proto_fd_table[wsgi_req->fd] = wsgi_req;
@@ -312,7 +312,7 @@ static void asyncio_loop() {
uwsgi.wait_write_hook = uwsgi_asyncio_wait_write_hook;
uwsgi.wait_read_hook = uwsgi_asyncio_wait_read_hook;
if (uwsgi.async < 2) {
if (uwsgi.async < 1) {
uwsgi_log("the asyncio loop engine requires async mode (--async <n>)\n");
exit(1);
}
@@ -328,7 +328,7 @@ static void asyncio_loop() {
uwsgi.schedule_fix = uwsgi_asyncio_schedule_fix;
}
#ifndef UWSGI_PYTHREE
#ifndef PYTHREE
PyObject *asyncio = PyImport_ImportModule("trollius");
#else
PyObject *asyncio = PyImport_ImportModule("asyncio");
+6 -3
View File
@@ -1,8 +1,11 @@
from distutils import sysconfig
NAME='asyncio'
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
NAME = 'asyncio'
CFLAGS = [
'-I' + sysconfig.get_python_inc(),
'-I' + sysconfig.get_python_inc(plat_specific=True)
]
LDFLAGS = []
LIBS = []
GCC_LIST = ['asyncio']
+17 -17
View File
@@ -208,10 +208,10 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
switch(wsgi_req->uh->modifier2) {
case 0:
// get
if (wsgi_req->uh->pktsize > 0) {
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL, NULL);
if (wsgi_req->uh->_pktsize > 0) {
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->_pktsize, &vallen, NULL, NULL);
if (value) {
wsgi_req->uh->pktsize = vallen;
wsgi_req->uh->_pktsize = vallen;
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) { free(value) ; return -1;}
uwsgi_response_write_body_do(wsgi_req, value, vallen);
free(value);
@@ -220,10 +220,10 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
break;
case 1:
// set
if (wsgi_req->uh->pktsize > 0) {
if (wsgi_req->uh->_pktsize > 0) {
// max 3 items
argc = 3;
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh->pktsize, argv, argvs, &argc)) {
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh->_pktsize, argv, argvs, &argc)) {
if (argc > 1) {
uwsgi_cache_magic_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0, NULL);
}
@@ -232,30 +232,30 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
break;
case 2:
// del
if (wsgi_req->uh->pktsize > 0) {
uwsgi_cache_magic_del(wsgi_req->buffer, wsgi_req->uh->pktsize, NULL);
if (wsgi_req->uh->_pktsize > 0) {
uwsgi_cache_magic_del(wsgi_req->buffer, wsgi_req->uh->_pktsize, NULL);
}
break;
case 3:
case 4:
// dict
if (wsgi_req->uh->pktsize > 0) {
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->pktsize, cache_simple_command, (void *) wsgi_req);
if (wsgi_req->uh->_pktsize > 0) {
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->_pktsize, cache_simple_command, (void *) wsgi_req);
}
break;
case 5:
// get (uwsgi + stream)
if (wsgi_req->uh->pktsize > 0) {
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL, NULL);
if (wsgi_req->uh->_pktsize > 0) {
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->_pktsize, &vallen, NULL, NULL);
if (value) {
wsgi_req->uh->pktsize = 0;
wsgi_req->uh->_pktsize = 0;
wsgi_req->uh->modifier2 = 1;
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) { free(value) ;return -1;}
uwsgi_response_write_body_do(wsgi_req, value, vallen);
free(value);
}
else {
wsgi_req->uh->pktsize = 0;
wsgi_req->uh->_pktsize = 0;
wsgi_req->uh->modifier2 = 0;
uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4);
free(value);
@@ -265,8 +265,8 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
case 6:
// dump
uc = uwsgi.caches;
if (wsgi_req->uh->pktsize > 0) {
uc = uwsgi_cache_by_namelen(wsgi_req->buffer, wsgi_req->uh->pktsize);
if (wsgi_req->uh->_pktsize > 0) {
uc = uwsgi_cache_by_namelen(wsgi_req->buffer, wsgi_req->uh->_pktsize);
}
if (!uc) break;
@@ -299,9 +299,9 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uwsgi_buffer_destroy(cache_dump);
break;
case 17:
if (wsgi_req->uh->pktsize == 0) break;
if (wsgi_req->uh->_pktsize == 0) break;
memset(&ucmc, 0, sizeof(struct uwsgi_cache_magic_context));
if (uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->pktsize, uwsgi_cache_magic_context_hook, &ucmc)) {
if (uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->_pktsize, uwsgi_cache_magic_context_hook, &ucmc)) {
break;
}
manage_magic_context(wsgi_req, &ucmc);
+1 -1
View File
@@ -1,5 +1,5 @@
NAME = 'cache'
NAME='cache'
CFLAGS = []
LDFLAGS = []
LIBS = []
+4 -1
View File
@@ -71,7 +71,9 @@ static void carbon_post_init() {
u_server->errors = 0;
char *p, *ctx = NULL;
uwsgi_foreach_token(usl->value, ":", p, ctx) {
// make a copy to not clobber argv
char *tmp = uwsgi_str(usl->value);
uwsgi_foreach_token(tmp, ":", p, ctx) {
if (!u_server->hostname) {
u_server->hostname = uwsgi_str(p);
}
@@ -81,6 +83,7 @@ static void carbon_post_init() {
else
break;
}
free(tmp);
if (!u_server->hostname || !u_server->port) {
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
usl = usl->next;
+1 -2
View File
@@ -1,7 +1,6 @@
NAME = 'carbon'
NAME='carbon'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['carbon']
+3 -3
View File
@@ -480,7 +480,7 @@ static int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
char *script_name = NULL;
/* Standard CGI request */
if (!wsgi_req->uh->pktsize) {
if (!wsgi_req->len) {
uwsgi_log("Empty CGI request. skip.\n");
return -1;
}
@@ -533,9 +533,9 @@ static int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
memcpy(full_path, tmp_path, full_path_len+1);
if (uwsgi_starts_with(full_path, full_path_len, docroot, docroot_len)) {
uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot);
if (need_free)
free(docroot);
uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot);
return -1;
}
@@ -731,7 +731,7 @@ clear2:
// now wait for process exit/death
// in async mode we need a trick...
if (uwsgi.async > 1) {
if (uwsgi.async > 0) {
pid_t diedpid = waitpid(cgi_pid, &waitpid_status, WNOHANG);
if (diedpid < 0) {
uwsgi_error("waitpid()");
+2 -1
View File
@@ -1,4 +1,5 @@
NAME='cgi'
NAME = 'cgi'
CFLAGS = []
LDFLAGS = []
LIBS = []
+1 -1
View File
@@ -1,4 +1,4 @@
NAME='cheaper_backlog2'
NAME = 'cheaper_backlog2'
CFLAGS = []
LDFLAGS = []
+1 -1
View File
@@ -1,4 +1,4 @@
NAME='cheaper_busyness'
NAME = 'cheaper_busyness'
CFLAGS = []
LDFLAGS = []
+1 -1
View File
@@ -1,4 +1,4 @@
NAME='clock_monotonic'
NAME = 'clock_monotonic'
CFLAGS = []
LDFLAGS = []
+1 -1
View File
@@ -1,4 +1,4 @@
NAME='clock_realtime'
NAME = 'clock_realtime'
CFLAGS = []
LDFLAGS = []
+24 -3
View File
@@ -65,6 +65,7 @@ void uwsgi_cr_peer_reset(struct corerouter_peer *peer) {
free(peer->tmp_socket_name);
peer->tmp_socket_name = NULL;
}
cr_del_timeout(peer->session->corerouter, peer);
if (peer->fd != -1) {
@@ -75,6 +76,12 @@ void uwsgi_cr_peer_reset(struct corerouter_peer *peer) {
peer->hook_write = NULL;
}
if (peer->is_buffering) {
if (peer->buffering_fd != -1) {
close(peer->buffering_fd);
}
}
peer->failed = 0;
peer->soopt = 0;
peer->timed_out = 0;
@@ -87,9 +94,9 @@ void uwsgi_cr_peer_reset(struct corerouter_peer *peer) {
int uwsgi_cr_peer_del(struct corerouter_peer *peer) {
// first of all check if we need to run a flush procedure
if (peer->flush && !peer->is_flushing) {
peer->is_flushing = 1;
peer->is_flushing = 1;
// on success, suspend the execution
if (peer->flush(peer) >= 0) return -1;
if (peer->flush(peer) > 0) return -1;
}
struct corerouter_peer *prev = peer->prev;
struct corerouter_peer *next = peer->next;
@@ -116,6 +123,7 @@ int uwsgi_cr_peer_del(struct corerouter_peer *peer) {
if (peer->out && peer->out_need_free) {
uwsgi_buffer_destroy(peer->out);
}
free(peer);
return 0;
}
@@ -298,6 +306,16 @@ void corerouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
usr->notify = val;
usr->notify_len = vallen;
}
else if (!uwsgi_strncmp("algo", 4, key, keylen)) {
usr->algo = uwsgi_subscription_algo_get(val, vallen);
}
else if (!uwsgi_strncmp("backup", 6, key, keylen)) {
usr->backup_level = uwsgi_str_num(val, vallen);
}
else if (!uwsgi_strncmp("proto", 5, key, keylen)) {
usr->proto = val;
usr->proto_len = vallen;
}
}
void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
@@ -420,7 +438,7 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
if (ucr->subscriptions && tmp_peer->un && tmp_peer->un->len) {
tmp_peer->un->reference--;
}
if (uwsgi_cr_peer_del(tmp_peer) < 0) return;
if (uwsgi_cr_peer_del(tmp_peer) < 0) return;
}
// could be used to free additional resources
@@ -1058,6 +1076,7 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
#ifdef UWSGI_SSL
if (uwsgi_stats_keylong_comma(us, "sni_enabled", (unsigned long long) s_slot->sni_enabled)) goto end0;
#endif
if (uwsgi_stats_keyval_comma(us, "algo", uwsgi_subscription_algo_name(s_slot->algo))) goto end0;
if (uwsgi_stats_key(us , "nodes")) goto end0;
if (uwsgi_stats_list_open(us)) goto end0;
@@ -1081,6 +1100,8 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
if (uwsgi_stats_keylong_comma(us, "cores", (unsigned long long) s_node->cores)) goto end0;
if (uwsgi_stats_keylong_comma(us, "load", (unsigned long long) s_node->load)) goto end0;
if (uwsgi_stats_keylong_comma(us, "weight", (unsigned long long) s_node->weight)) goto end0;
if (uwsgi_stats_keylong_comma(us, "backup", (unsigned long long) s_node->backup_level)) goto end0;
if (uwsgi_stats_keyvaln_comma(us, "proto", &s_node->proto, 1)) goto end0;
if (uwsgi_stats_keylong_comma(us, "wrr", (unsigned long long) s_node->wrr)) goto end0;
if (uwsgi_stats_keylong_comma(us, "ref", (unsigned long long) s_node->reference)) goto end0;
if (uwsgi_stats_keylong_comma(us, "failcnt", (unsigned long long) s_node->failcnt)) goto end0;
+9 -3
View File
@@ -180,8 +180,8 @@ struct corerouter_peer {
uint16_t retries;
// parsed key
char *key;
uint16_t key_len;
char key[0xff];
uint8_t key_len;
uint8_t modifier1;
uint8_t modifier2;
@@ -192,7 +192,13 @@ struct corerouter_peer {
int current_timeout;
ssize_t (*flush)(struct corerouter_peer *);
int is_flushing;
int is_flushing;
// maps 1:1 with subscription proto
char proto;
int is_buffering;
int buffering_fd;
};
struct uwsgi_corerouter {
+16 -2
View File
@@ -48,11 +48,18 @@ int uwsgi_cr_map_use_pattern(struct uwsgi_corerouter *ucr, struct corerouter_pee
int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
peer->un = uwsgi_get_subscribe_node(ucr->subscriptions, peer->key, peer->key_len);
struct uwsgi_subscription_client usc;
usc.fd = peer->session->main_peer->fd;
usc.sockaddr = &peer->session->client_sockaddr;
usc.cookie = NULL;
peer->un = uwsgi_get_subscribe_node(ucr->subscriptions, peer->key, peer->key_len, &usc);
if (peer->un && peer->un->len) {
peer->instance_address = peer->un->name;
peer->instance_address_len = peer->un->len;
peer->modifier1 = peer->un->modifier1;
peer->modifier2 = peer->un->modifier2;
peer->proto = peer->un->proto;
}
else if (ucr->cheap && !ucr->i_am_cheap && uwsgi_no_subscriptions(ucr->subscriptions)) {
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
@@ -68,12 +75,17 @@ int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *ucr, struct
// max 5 split, reduce DOS attempts
int count = 5;
struct uwsgi_subscription_client usc;
usc.fd = peer->session->main_peer->fd;
usc.sockaddr = &peer->session->client_sockaddr;
usc.cookie = NULL;
split:
if (!count) return 0;
#ifdef UWSGI_DEBUG
uwsgi_log("trying with %.*s\n", name_len, name);
#endif
peer->un = uwsgi_get_subscribe_node(ucr->subscriptions, name, name_len);
peer->un = uwsgi_get_subscribe_node(ucr->subscriptions, name, name_len, &usc);
if (!peer->un) {
char *next = memchr(name+1, '.', name_len-1);
if (next) {
@@ -88,6 +100,8 @@ split:
peer->instance_address = peer->un->name;
peer->instance_address_len = peer->un->len;
peer->modifier1 = peer->un->modifier1;
peer->modifier2 = peer->un->modifier2;
peer->proto = peer->un->proto;
}
else if (ucr->cheap && !ucr->i_am_cheap && uwsgi_no_subscriptions(ucr->subscriptions)) {
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
+1 -1
View File
@@ -1,5 +1,5 @@
NAME = 'corerouter'
NAME='corerouter'
CFLAGS = []
LDFLAGS = []
LIBS = []
+3 -3
View File
@@ -187,7 +187,7 @@ end:
XS(XS_coroae_sighandler) {
int sigfd = (long) XSANY.any_ptr;
uwsgi_receive_signal(sigfd, "worker", uwsgi.mywid);
uwsgi_receive_signal(NULL, sigfd, "worker", uwsgi.mywid);
}
XS(XS_coroae_acceptor) {
@@ -227,7 +227,7 @@ edge:
// enter harakiri mode
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
set_harakiri(wsgi_req, uwsgi.harakiri_options.workers);
}
@@ -356,7 +356,7 @@ static void coroae_wait_condvar(SV *cv) {
static void coroae_loop() {
if (uwsgi.async < 2) {
if (uwsgi.async < 1) {
if (uwsgi.mywid == 1) {
uwsgi_log("the Coro::AnyEvent loop engine requires async mode (--async <n>)\n");
}
+2 -1
View File
@@ -1,6 +1,8 @@
import os
import sys
NAME = 'coroae'
coroapi = None
search_paths = os.popen('perl -MConfig -e \'print $Config{sitearch}.",".join(",", @INC);\'').read().rstrip().split(',')
@@ -12,7 +14,6 @@ if not coroapi:
print "unable to find the Coro perl module !!!"
sys.exit(1)
NAME='coroae'
CFLAGS = os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip().split()
CFLAGS += ['-Wno-int-to-pointer-cast', '-Wno-error=format', '-Wno-error=int-to-pointer-cast', '-I%s/Coro' % coroapi]
LDFLAGS = []
+1 -1
View File
@@ -28,7 +28,7 @@ extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
FakeClass *fc;
// empty request ?
if (!wsgi_req->uh->pktsize) {
if (!wsgi_req->len) {
uwsgi_log( "Invalid request. skip.\n");
goto clear;
}
+1 -1
View File
@@ -1,4 +1,4 @@
NAME='cplusplus'
NAME = 'cplusplus'
CFLAGS = []
LDFLAGS = []

Some files were not shown because too many files have changed in this diff Show More