Compare commits

...
465 Commits
Author SHA1 Message Date
Unbit 38682590e9 added UWSGI_END_OF_OPTIONS macro 2013-12-11 11:38:32 +01:00
Unbit aa2a212be8 prepare for tomorrow release 2013-12-10 18:47:37 +01:00
Unbit 51714203a7 added var. logchunk 2013-12-10 17:19:58 +01:00
Unbit fbac57a903 fixed mongrel2 plugin 2013-12-10 15:55:11 +01:00
Unbit 768d1c4099 support platforms not exposing RTLD_NEXT 2013-12-10 13:13:24 +01:00
Unbit 82fa510030 fixed build on python 2.6 2013-12-10 12:04:52 +01:00
Unbit a6e6bff082 sharedarea can be mapped to generic objects 2013-12-10 10:09:38 +01:00
Unbit 304f847dc6 added sharedarea_update api 2013-12-10 09:06:27 +01:00
Roberto De Ioris 5bb7f02921 added memoryview wrapper for sharedarea and locking api 2013-12-10 07:33:45 +01:00
unbit 02ee60c6ef Merge pull request #472 from prymitive/ns_exit_on_reload
namespace init process should exit if exit-on-reload is enabled
2013-12-09 21:52:27 -08:00
Łukasz Mierzwa 4d3526a377 namespace init process should exit if exit-on-reload is enabled, fixes #471 2013-12-09 21:42:48 +01:00
Unbit ca9d1830bb refactored logchunks management 2013-12-08 05:43:21 +01:00
Unbit 4ff485d565 allow using RTLD_NEXT in symcall 2013-12-08 05:04:03 +01:00
Unbit 63d5c6afc9 added symcal routing action 2013-12-08 04:49:34 +01:00
Roberto De Ioris 3a36551d1f fix G_EVAL in coroae 2013-12-07 11:32:43 +01:00
Roberto De Ioris 26877e1da9 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-12-07 10:54:16 +01:00
Unbit d81330c514 support IO object is perl async mode too 2013-12-07 09:52:51 +00:00
Unbit 441013b71b added mule support for symcall and more robust check for psgi response 2013-12-07 09:07:42 +00:00
Unbit a6b9e653a4 fix plugin build time 2013-12-07 08:26:01 +00:00
Unbit c7161139e7 report build time even for plugins 2013-12-07 08:16:43 +00:00
Unbit ce07c1a454 report total build time 2013-12-07 07:33:38 +01:00
unbit 4eb3b76c35 Update README 2013-12-06 17:38:52 +01:00
unbit 3519fcbcc6 Update README 2013-12-06 17:37:51 +01:00
Unbit 70dd9fca32 allows building plugin from a single file 2013-12-04 21:33:27 +01:00
Unbit a573602171 added tmsecs and tmicros log vars 2013-12-04 12:56:31 +01:00
Unbit 29418654d7 added support for mountpoints in the symcall plugin 2013-12-04 12:03:47 +01:00
Unbit 31c31c4ce2 fixed read2 hook in non async mode 2013-12-03 22:52:51 +01:00
Unbit 0217766dd1 read2 hook for async mode 2013-12-03 22:25:30 +01:00
Unbit 3d15660407 added a skel hook for waiting for 2 file descriptors 2013-12-03 19:34:15 +01:00
Unbit 57ce416ae1 fixed unbit CPU smashing 2013-12-03 14:26:49 +01:00
Unbit 248a22b064 added another optimization for writev and a test for it 2013-12-02 07:01:44 +01:00
Roberto De Ioris 49c5206d86 fixed writev optimization 2013-12-02 04:58:08 +01:00
Unbit 5b17363b40 enable writev optimization by default 2013-12-01 09:11:33 +01:00
Unbit e6c3c04e64 completed vector based I/O 2013-12-01 08:47:43 +01:00
Unbit 9a36b2b891 added writev api 2013-12-01 08:12:32 +01:00
Roberto De Ioris bfd699dac5 another mjpeg fix 2013-12-01 05:44:36 +01:00
Unbit cc3e43eb3d fixed uwsgi_sharedarea_read 2013-12-01 04:40:39 +00:00
Unbit b934ac9588 refactored sharedarea read 2013-11-30 18:30:52 +00:00
Unbit 92b6c62cac improved mjpeg example 2013-11-30 15:43:17 +01:00
Unbit 46cceb0465 croak if the psgi streamer fails 2013-11-30 14:30:22 +00:00
Unbit f1b3522c2a allows building coroae on raspberrypi 2013-11-30 13:49:21 +00:00
Unbit c99f5d0875 fixed sharedarea_wait perl api 2013-11-30 12:46:17 +01:00
Unbit b972c2d6bb another round of non-blocking optimizations 2013-11-30 12:33:24 +01:00
Unbit d226f65890 optimized sendfile 2013-11-30 12:23:13 +01:00
Unbit 60b54c4d7c allows sending websockets messages directly from a sharedarea 2013-11-30 11:19:28 +00:00
Unbit ace79b1179 various websockets and sharedarea optimizations 2013-11-30 10:41:56 +00:00
Roberto De Ioris 9993e3710c first attempt of uwsgi_sharedarea_readfast 2013-11-30 07:31:57 +01:00
Roberto De Ioris 98541dbc65 more sharedarea improvements 2013-11-30 07:23:05 +01:00
Roberto De Ioris cabb6d72d9 added uwsgi.websocket_send_binary_message to cpython 2013-11-30 06:49:15 +01:00
Roberto De Ioris 217f2f99ff added declarations for sharedarea api 2013-11-30 06:47:52 +01:00
Unbit 890e0004b6 fixed signs in sharedarea 2013-11-29 17:28:05 +01:00
Unbit d17d947cd1 added dec variants for sharedarea 2013-11-29 17:21:15 +01:00
Unbit a69c775cd5 added inc variants for sharedarea 2013-11-29 17:17:36 +01:00
Unbit 4c051d90ed split setup from running for easy library integration 2013-11-29 17:07:11 +01:00
Unbit f55c52eaff added milliseconds hook support for rbthreads 2013-11-29 16:47:33 +01:00
Unbit 88b5f968a4 added milliseconds hook support to gevent 2013-11-29 16:43:07 +01:00
Unbit 6fdeecce0f added milliseconds wait hook to Coro::AnyEvent 2013-11-29 16:33:39 +01:00
Unbit f6923728d8 more sharedarea api functions 2013-11-29 16:07:27 +01:00
unbit cf96783dce Merge pull request #468 from xrmx/coverity2911
Coverity Fixes
2013-11-29 06:34:36 -08:00
Unbit e4d3d209c8 allows sharedarea_wait to specify the freq 2013-11-29 13:32:30 +00:00
Unbit 5182eaf485 another round of sharedarea implementations 2013-11-29 12:47:59 +00:00
Roberto De Ioris 082d47e156 area is a better field name for sharedarea 2013-11-29 07:46:28 +01:00
Roberto De Ioris 0715031b00 prepare for the new sharedarea api 2013-11-29 07:39:12 +01:00
Unbit 27c3532617 added S master fifo command 2013-11-28 11:36:28 +01:00
Roberto De Ioris cb1370b148 avoid allocating memory structures for fd monitoring and timeouts when non-plain async mode is in place 2013-11-28 07:12:38 +01:00
Roberto De Ioris 9cc58a3c13 avoid segfault when async mode api is called without async mode 2013-11-28 07:00:18 +01:00
Roberto De Ioris 150f0c631e fixed plain (without suspend engine) async mode 2013-11-28 06:47:36 +01:00
Roberto De Ioris 0574a120bc ported mjpeg stream to newer osx 2013-11-28 06:04:15 +01:00
Unbit c6550ece68 added as-mule hook 2013-11-27 16:01:49 +01:00
Unbit e76a40530b in request context uwsgi_req_error should always be used 2013-11-26 09:41:15 +01:00
Unbit 31c73ce298 report request data in writers and readers 2013-11-26 09:33:02 +01:00
Unbit b304766718 added werr, rerr and ioerr to logvars 2013-11-26 07:20:36 +01:00
Unbit 0ab1cfacc9 added read errors counters and --log-ioerror 2013-11-26 07:13:07 +01:00
Riccardo Magliocchetti b1f06bce32 plugins/rpc_plugin: check return value of uwsgi_response_prepare_headers
Reported by Coverity as CID #1100798.
2013-11-23 16:18:09 +01:00
Riccardo Magliocchetti 347ef1a5bf plugins/router_hash: Avoid possible divide by zero
Reported by Coverity as CID #1100804.
2013-11-23 16:05:56 +01:00
Unbit b4d9eb4f73 various fifo improvements 2013-11-23 08:01:56 +01:00
Unbit f44a36900a added unlink command 2013-11-23 07:48:50 +01:00
Unbit b6c969254d added accepting once variant 2013-11-23 07:40:53 +01:00
Unbit c5003561dd added write hook 2013-11-23 07:35:08 +01:00
Unbit 18dead4cd2 added hook-accepting1 2013-11-23 07:31:20 +01:00
Unbit 62aee259fa prepare for 1.9.21 2013-11-23 05:11:02 +01:00
Unbit 69c49f713e remove zeromq from build profiles 2013-11-23 05:09:50 +01:00
Unbit 08525a91ee reverted gccgo argv_list free 2013-11-23 04:59:12 +01:00
unbit 40fee74a5f Merge pull request #464 from xrmx/coverity2211
Fix a couple of memory leaks
2013-11-22 19:56:37 -08:00
unbit 6d8f179863 Merge pull request #465 from xrmx/coverity2211-2
core: Fix unintentonal integer overflow
2013-11-22 19:52:40 -08:00
Riccardo Magliocchetti d0b3c442c1 core: Fix unintential integer overflow
The expression would be evaluated as 32bit unsigned before
promoting to 64bit unsigned so cast the strtoul return value to
avoid integer overflows. Please note that the value passed here
comes from the user.

Reported by Coverity as CID #971244.
2013-11-22 20:13:54 +01:00
Riccardo Magliocchetti de82b58952 plugins/gccgo: fix memory leak
Reported by Coverity as CID #1128440
2013-11-22 19:44:04 +01:00
Riccardo Magliocchetti eb33fa7b19 core/config: fix memory leak
Reported by Coverity s CID #1128441
2013-11-22 19:32:56 +01:00
Unbit 9dde5f9d82 completed error pages 2013-11-22 18:53:05 +01:00
Unbit 036df0e5ff fixed fd leak in error pages 2013-11-22 18:52:02 +01:00
Unbit 1154aa8ddc added accepting hook 2013-11-22 18:46:07 +01:00
Unbit 3371dd2f94 added error-page management 2013-11-22 18:42:30 +01:00
unbit 06791376af honour CFLAGS and LDFLAGS in embedded builder 2013-11-22 09:22:08 +01:00
Roberto De Ioris 30e0af3826 only GCC_LIST and NAME are required 2013-11-22 06:45:14 +01:00
Unbit e4903ee0bf first working prototype of embedded plugins builder 2013-11-21 15:29:30 +01:00
Unbit 859c386b40 improved --extra-plugin 2013-11-21 14:54:42 +01:00
Unbit b83fecf4d3 another step for embedded plugins builder 2013-11-21 14:37:58 +01:00
Unbit 25dc608fa3 prepare for embedded plugins builder 2013-11-21 14:10:41 +01:00
Roberto De Ioris c01cf1f6be added accepting and ready state to the Emperor 2013-11-21 06:39:23 +01:00
Roberto De Ioris 9825f95ed5 improved chain reloading 2013-11-20 18:47:55 +01:00
Unbit 36143381e1 tiny uwsgi.h refactoring 2013-11-20 05:28:32 +01:00
unbit 8c25bafc73 Merge pull request #462 from Kapishin/master
Fix few typos
2013-11-19 01:46:12 -08:00
Pavlo Kapyshin 826f49c010 Fix few typos 2013-11-19 11:28:50 +02:00
Unbit 8b006c0874 support timerfd_create/timerfd_settime on __arm__ 2013-11-18 16:34:45 +01:00
Unbit 5806c333f5 do not spit errors on non x86 timerfd_create 2013-11-18 16:21:36 +01:00
Unbit e606d1e5d1 removal of embedded zeromq api 2013-11-18 11:11:46 +01:00
Unbit ec954b8aa7 fixed v8 RPC 2013-11-17 07:02:21 +01:00
Unbit 95d20e9f48 add rack to gemspec 2013-11-17 06:44:16 +01:00
Unbit 165aad8cd0 Merge branch 'master' of ssh://github.com/unbit/uwsgi 2013-11-17 06:42:04 +01:00
Unbit 29c339a3c3 gemspec for 1.9.20 2013-11-17 06:41:46 +01:00
unbit 12afba035b Merge pull request #460 from Kapishin/master
Fix typos
2013-11-16 09:01:33 -08:00
Pavlo Kapyshin eeb203afd4 Fix typos 2013-11-16 17:41:26 +02:00
Roberto De Ioris 2ccdd0fb67 fixed zeromq support 2013-11-15 07:46:37 +01:00
Unbit 6a18d10c56 fixed typo in total_tx metric 2013-11-13 21:38:56 +01:00
Unbit d1383d7749 added multiplier and adder collector 2013-11-13 19:53:47 +01:00
Unbit 0abbabbe10 added accumulator metrics collector 2013-11-13 19:51:22 +01:00
Roberto De Ioris ea44525c22 fixed zeromq support 2013-11-15 07:48:49 +01:00
Unbit 2396c7cf31 prepare for 1.9.20 2013-11-13 15:14:51 +01:00
Roberto De Ioris 4805a9c219 added chunked input api to psgi 2013-11-14 07:44:13 +01:00
Roberto De Ioris 882cdcc2b6 added --plshell and Perl uwsgi::rpc 2013-11-14 06:24:56 +01:00
unbit 59c8bb51b4 Merge pull request #454 from xiaost-bytedance/master
fixed master hang when gracefully reloading in lazy mode
2013-11-13 08:50:52 -08:00
xiaost 3c2350f5ad fixed master hang when gracefully reloading in lazy mode 2013-11-14 00:33:49 +08:00
Unbit 422e958fe3 added uwsgi over SSL 2013-11-13 04:46:27 +01:00
Unbit 4d9c7809d6 added support for proxy protocol 2013-11-13 03:20:55 +01:00
Unbit 6b3d8ea146 added avg metrics collector 2013-11-13 02:41:47 +01:00
Unbit b5d8538fe8 added oid metric in stats 2013-11-12 17:48:48 +01:00
Unbit 47796b315e fixed stupid bug in websocket perl example 2013-11-12 12:38:22 +01:00
Unbit 222bcd8fdc another fix for default app 2013-11-12 12:22:54 +01:00
Unbit f92b800a7c fixed default app usage 2013-11-12 12:18:31 +01:00
Unbit dec2b234f8 fixed no default app 2013-11-12 12:14:15 +01:00
Unbit 3dbd7e3115 fixed comments in websockets_chat.pl 2013-11-12 08:50:50 +01:00
Unbit 09d8747918 added tests/websockets_chat.pl 2013-11-12 08:48:49 +01:00
Unbit fa78fd915b force https to on when --https-socket is in place 2013-11-12 05:59:10 +01:00
Unbit db56141485 completed --https-socket 2013-11-12 05:54:47 +01:00
Unbit 7685af4652 pluginized the socket protocols 2013-11-12 05:44:52 +01:00
unbit 21cb62db6c Merge pull request #452 from Kapishin/master
Fix typos
2013-11-11 20:15:07 -08:00
Pavlo Kapyshin c62aa8e7ed Fix typos 2013-11-11 23:05:30 +02:00
unbit 4765965d8e Merge pull request #451 from xrmx/coverity1111
build/coverity: remove broken erlang plugin
2013-11-11 10:14:08 -08:00
Riccardo Magliocchetti 556feaef2c build/coverity: remove broken erlang plugin 2013-11-11 19:11:20 +01:00
Unbit 799b8a22e0 improved content_type detection for rpc-path_info bridge 2013-11-11 15:50:11 +01:00
Unbit 2336580164 more rpc fixes 2013-11-11 15:09:13 +01:00
Unbit ca4f30c003 fixed rpc 64bit networking extension 2013-11-11 14:52:22 +01:00
Unbit d7d0a71d87 completed rpc 64bit network client 2013-11-11 14:42:28 +01:00
Unbit 44b92f1578 implemented 64bit extension for rpc protocol 2013-11-11 14:08:26 +01:00
Unbit abed95362f another series of rpc 64bit fixes 2013-11-11 13:46:00 +01:00
Unbit 72ecc217f7 perl passes the 64bit rpc test 2013-11-11 13:43:21 +01:00
Unbit 1405d01d50 pypy passes 64bit rpc local test 2013-11-11 13:24:08 +01:00
Unbit def65c4793 fixed python, perl and ruby rpc 64bit 2013-11-11 13:06:16 +01:00
Unbit 26386909de first attempt of moving rpc output from 16 to 64 bit 2013-11-11 13:00:20 +01:00
Unbit 2d4e04059a uwsgi.go low-level optimizations and implementation of uwsgi.CacheGet 2013-11-11 12:18:43 +01:00
unbit ac557739c2 allows monolithic gccgo to run on 32bit 2013-11-11 11:00:33 +01:00
Unbit 73bfc20ba1 added connection_fd to rack plugin 2013-11-11 09:12:52 +01:00
Unbit 6d5ae96d50 hack for adding an empty DEBUG section to the uwsgi core binary 2013-11-11 09:04:48 +01:00
Unbit 20b5b7b0dc added support for uwsgi::connection_fd and psgix.io 2013-11-11 08:22:01 +01:00
Unbit 82c5afd0c7 forgot PROFILE in Makefile 2013-11-11 06:12:32 +01:00
Unbit ec14f5b0fe Merge branch 'master' of ssh://github.com/unbit/uwsgi 2013-11-11 05:45:06 +01:00
unbit d93bdcb7b4 Merge pull request #450 from awentzonline/patch-1
Fixed spelling of error message in pyloader.c
2013-11-10 20:55:22 -08:00
Unbit b68ffc842d prepare for gccgo docs 2013-11-11 05:44:51 +01:00
Adam Wentz 0326c1d508 Fixed spelling of error message in pyloader.c 2013-11-10 14:08:41 -06:00
Unbit 42f45bfbf9 erlang plugin is broken 2013-11-10 08:27:44 +01:00
Unbit d018d3af99 pyerl plugin is broken 2013-11-10 08:27:23 +01:00
Unbit 42afc476d7 improved gccgo monolithic build 2013-11-10 08:26:14 +01:00
Unbit b5037d3f0f sanitize gccgo environment 2013-11-10 07:54:13 +01:00
Unbit 065dd7cfff return after grace_them_all 2013-11-10 06:49:02 +01:00
unbit 7909e092b5 Merge pull request #449 from xrmx/coverity0911-2
More coverity fixes
2013-11-09 21:52:49 -08:00
Unbit 9da53f5fd4 improved gccgo signal handling and added --timer and --rbtimer commodity options 2013-11-10 06:42:46 +01:00
Unbit 025cb7744e implemented goroutines timeout 2013-11-10 05:55:54 +01:00
Unbit e48a3ff1b7 added %k magic vars (number of cpu cores) 2013-11-10 04:51:25 +01:00
Unbit 2be371003c added %t and %T magic vars 2013-11-10 04:36:14 +01:00
Unbit 60d940e301 added simple math and concat to placeholders 2013-11-10 04:27:26 +01:00
Unbit 96c56cd8d5 added simple math routing actions 2013-11-10 03:30:33 +01:00
Unbit 4184619f7b removed snapshotting old feature 2013-11-10 02:59:15 +01:00
Unbit 50a8ec8a19 removed matheval flag, added generic matheval plugin and startin 1.9.20 development cycle 2013-11-10 02:53:08 +01:00
Unbit 79c702278a fixed async queue full condition in goroutine mode 2013-11-10 02:42:00 +01:00
Unbit 8fc41a4c85 remove useless gccgo code 2013-11-09 18:45:57 +01:00
Unbit 9c6455252d avoid GC to destroy go request env 2013-11-09 18:22:36 +01:00
Unbit 83e41844f3 first hardcore commit for supporting gccgo coroutines 2013-11-09 17:28:06 +01:00
Riccardo Magliocchetti 2cc17d6b11 core/logging: if we cannot reopen the log exit
This fixes passing negative fds to write and lseek.

Reported by Coverity as CID #1100807.
2013-11-09 16:15:49 +01:00
Riccardo Magliocchetti 14057b72c8 core: fix memory leak
Reported by Coverity as CID #1100813.
2013-11-09 16:08:47 +01:00
Riccardo Magliocchetti faf72b6a77 plugins/corerouter: fix memory leak
While at it reindent the code

Reported by Coverity as CID #1100818.
2013-11-09 16:05:41 +01:00
Riccardo Magliocchetti 963afa5174 core: fix memory leak
Reported by Coverity as CID #1100819
2013-11-09 15:46:05 +01:00
Unbit ce8ff8c45f fixed metric bug discovered by coverity 2013-11-09 15:15:32 +01:00
Riccardo Magliocchetti 5ae742e8e1 plugins/xslt: fail early if content_type is null
Fixes null pointer dereference.

Reported by Coverity as CID #1125161
2013-11-09 15:11:35 +01:00
Riccardo Magliocchetti 60f6572985 plugins/xslt: fix memory leak
Reported by Coverity as CID #1125168
2013-11-09 15:06:46 +01:00
Riccardo Magliocchetti 4ea34c63d2 plugins/servlet: Check uwsgi_jvm_exception return value
Reported vy Coverity as CID #1125169.
2013-11-09 15:04:47 +01:00
Riccardo Magliocchetti 5699d21aa7 metrics: add missing exit on error path
Fixed null pointer dereference.

Reported by Coverity as CID #1127337
2013-11-09 15:00:58 +01:00
Unbit dda8d25495 try to address EAGAIn body read problem 2013-11-09 13:17:17 +01:00
Unbit d4f690322c moved go to broken plugins 2013-11-09 13:01:28 +01:00
Unbit 4f2f30d1e5 improved gccgo plugin 2013-11-09 12:55:52 +01:00
Unbit d3b28e7956 more plugins for coveriti, fixed gccgo 2013-11-09 12:20:32 +01:00
Unbit ab4afdbeaa fixed template plugin 2013-11-09 06:39:29 +01:00
Unbit 54e2d698cb prepare for uWSGI 1.9.19 2013-11-09 04:58:52 +01:00
Unbit 8b0565c0b8 added metric api to ruby 2013-11-09 04:31:14 +01:00
unbit 102d6f25ed Merge pull request #447 from flavour/master
Support HTTP Status 509
2013-11-08 03:05:11 -08:00
Fran Boon d0a53aa976 Support HTTP Status 509
Whilst this isn't an official RFC, it's documented on e.g. Wikipedia. http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_Server_Error
2013-11-08 10:49:48 +00:00
Unbit f8cf808e47 metrics as objects in stats subsystem 2013-11-07 12:10:56 +01:00
Unbit f8bbd2177e added stats pusher default plugins 2013-11-07 11:27:40 +01:00
Unbit f44c145941 do not destroy the stats pusher loop on EINTR 2013-11-07 09:54:16 +01:00
Unbit f34ac9f6aa completed metric threshold subystem 2013-11-07 09:43:01 +01:00
Unbit b971230fd9 use uwsgi.start_tv for srand instead of recomputing it 2013-11-07 08:56:04 +01:00
Unbit 5c6340caac busy_workers and idle_workers must be GAUGE 2013-11-07 07:45:12 +01:00
Unbit c0b97b47d3 implemented #284 2013-11-07 06:43:13 +01:00
Unbit a6b7f6e5bb added better random initialization and rr/rand hash algos 2013-11-06 18:20:38 +01:00
Unbit 1b99f9a750 added no_content_length to the cache router 2013-11-06 11:44:47 +01:00
Unbit a434195318 transformation_template has been moved to a plugin 2013-11-06 11:39:34 +01:00
Unbit a6a8faea78 added 'uwsgi' transformation 2013-11-06 10:52:19 +01:00
Unbit 31458320ab optimization in sendnl routing 2013-11-06 10:35:39 +01:00
Unbit 037a1f7f77 fixed #404 2013-11-05 09:43:11 +01:00
Unbit 10d4d10ac9 do not register metrics if metrics subsystem is not enabled 2013-11-04 15:12:18 +01:00
Unbit 00e8d509f8 metrics for routed and unrouted signals 2013-11-04 15:07:40 +01:00
Unbit c9ca14df4d fixed rbtimers 2013-11-03 19:31:18 +01:00
unbit 841cdfc62d Merge pull request #443 from prymitive/carbon_no_retry
allow disabling retries in carbon
2013-11-02 11:19:08 -07:00
Łukasz Mierzwa fc7026c076 allow disabling retries in carbon 2013-11-02 18:59:25 +01:00
unbit b96581c183 Merge pull request #442 from xrmx/coverityjvm
Add jvm plugins to coverity build profile
2013-11-02 10:35:24 -07:00
Riccardo Magliocchetti 4fa5d72af6 Add jvm plugins to coverity build profile 2013-11-02 18:13:57 +01:00
unbit f4be581666 Merge pull request #441 from xrmx/jvmarch2
plugins/jvm: let override jvm arch
2013-11-02 10:07:39 -07:00
unbit 24fb5518d8 Merge pull request #440 from Kapishin/master
Fix typos
2013-11-02 10:07:08 -07:00
unbit 2e8061d62a Merge pull request #439 from xrmx/coverity0211
More Coverity fixes
2013-11-02 10:06:42 -07:00
Riccardo Magliocchetti 23d70f6936 plugins/jvm: let override jvm arch
On mixed 64 bit kernel / 32 bit userspace linux systems the jvm
does not get recognized automatically if installed.

Permit to force an arch by exporting JVM_ARCH which is way more
easier than exporting the full path for includes and libraries.
2013-11-02 17:54:20 +01:00
Pavlo Kapyshin 95ea88628a Fix typos 2013-11-02 18:40:05 +02:00
Riccardo Magliocchetti 68b411f487 plugins/xslt: correct logical operator
Fixes a null pointer dereference.

Reported by Coverity as CID #1125160
2013-11-02 16:38:10 +01:00
Riccardo Magliocchetti 40bfbc0a44 plugins/pty: Fix a couple of memory issues
Rpoerted by Coverity as CID #1125163 and #1125162
2013-11-02 16:33:48 +01:00
Riccardo Magliocchetti fc9b6ea275 plugins/xslt: fix memory leaks
Rpeorted by Coverity as CID #1125164
2013-11-02 16:25:50 +01:00
Riccardo Magliocchetti 522f3bb3a1 plugins/xslt: fix xmlfile lifecycle
Fixes an use after free and a memory leak.

Reported by Coverity as CID #1125165, #1125167
2013-11-02 16:17:53 +01:00
Riccardo Magliocchetti 743c7ceaa6 plugins/v8: fix double free
Reported by Coverity as CID #1125166
2013-11-02 16:09:58 +01:00
Riccardo Magliocchetti c780cd47ce Update coverity build profile
Add a few more plugins and remove go that does not build.
2013-11-02 15:53:23 +01:00
unbit 54e7e01c05 Merge pull request #437 from prymitive/stats_pusher_retry
Restore retry handling in carbon
2013-11-01 22:35:22 -07:00
Łukasz Mierzwa 7d422d11e4 port carbon plugin to support retries in stats pusher, replaces old non-functional retry handling 2013-11-01 20:07:08 +01:00
Łukasz Mierzwa 5c35b60d1d add retry support to stats pusher 2013-11-01 19:43:15 +01:00
Unbit 94353efb3f correctly support python2.4 2013-11-01 10:02:35 +01:00
Roberto De Ioris 0586a2ba47 fixed #436 2013-11-01 09:54:01 +01:00
Roberto De Ioris be6081c6f7 port the carbon metric feature to latest api 2013-11-01 09:51:00 +01:00
unbit 955fb6479e Merge pull request #435 from prymitive/carbon_use_metrics
enable switching stats source from carbon's own loop to metrics data
2013-11-01 01:50:09 -07:00
Łukasz Mierzwa 1b334e8cf7 enable switching stats source from carbon's own loop to metrics data, fixes #417 2013-10-31 18:38:54 +01:00
Unbit 718e198ac8 little optimization in master fifo 2013-10-28 22:14:50 +01:00
unbit 3757e5a8bb Merge pull request #433 from xrmx/coverity2810-2
More Coverity fixes
2013-10-28 14:13:25 -07:00
Riccardo Magliocchetti d505964321 plugins/gevent: don't dereference null pointer
We should not pass a NULL pointer to Py_DECREF. This is possible
if wsgi_req->socket->edge_trigger is true.

Reported by Coverity as CID #970981.
2013-10-28 19:38:02 +01:00
Riccardo Magliocchetti 1114c1a429 core/fifo: check array index read before dereferencing uwsgi_master_fifo_manage
Reported by Coverity as CID #1100821
2013-10-28 19:29:25 +01:00
Riccardo Magliocchetti f58a9c6119 plugins/router_hash: don't dereference a null pointer
In case this condition is true:

    if (urhc->items[i] == ';') {

but this is false:

    if (found == hashed_result)

for the latest loop iteration value would be set as NULL

This is a bit unfortunate because later we can:
- use it in arithmetics
- dereference it in uwsgi_req_append

To fix that update vallen only if value is not null.

Reported by Coverity sa CID #1100805.
2013-10-28 19:27:06 +01:00
Riccardo Magliocchetti e791cb2c00 core/utils: cleanup if condition
uwsgi.ksm_mappings_current_size cannot be 0 here.
A couple of lines above:

1219 if (uwsgi.ksm_mappings_current_size <= 0) {
1220     uwsgi_log("[uwsgi-KSM] unable to read /proc/self/maps data\n");
1221     return;
1222 }
2013-10-28 19:26:51 +01:00
Unbit f741dbb01b added options for metric thresholds 2013-10-28 17:18:45 +01:00
Unbit d5f0741e8d metrics threshold structures 2013-10-28 17:16:17 +01:00
Unbit b265ed8313 avoid kevent storm for stats pusher thread 2013-10-28 17:09:27 +01:00
Unbit 6cb160bb26 support for WSGI genrators in tornado 2013-10-28 09:55:06 +01:00
Unbit 009a3f2c0d fixed greenlet memory leaks 2013-10-28 07:59:45 +01:00
Unbit 11b3d1fb94 greenlet plugin still need a bit of checks for reference counting 2013-10-27 19:06:18 +01:00
Unbit 7a39472700 various improvements in greenlet plugin 2013-10-27 18:31:31 +01:00
Unbit 4489b48603 added tornado loop engine 2013-10-27 18:08:34 +01:00
Unbit d2f69af964 fixed #428 2013-10-26 05:47:47 +02:00
unbit 34e9dabffc Merge pull request #430 from xrmx/coverity2510
Fix some leaks reported by coverity
2013-10-25 19:14:19 -07:00
unbit 6a4f46639e Merge pull request #432 from TheRealBill/master
Fixing argument for length of the string 'destroy'
2013-10-25 19:09:56 -07:00
Bill Anderson 0d07ff25f9 Fixing argument for length of the string 'destroy' 2013-10-25 13:20:11 -05:00
Riccardo Magliocchetti c1d9c4ef12 core/utils: fix resource leak in uwsgi_write_intfile
The more error condition you squeeze in one line the more chances
to leak :)

Reported by Coverity as CID #1100812
2013-10-25 19:53:04 +02:00
Riccardo Magliocchetti 0227ff7a9b core/utils: fix resource leak
Reported by Coverity as CID #1100814
2013-10-25 19:45:51 +02:00
Riccardo Magliocchetti 082b178ae3 core/io: Fix resource leak
Reported by Coverity as CID #1100815
2013-10-25 19:41:27 +02:00
Riccardo Magliocchetti 0e695cbd6e core/fsmon: fix memory leak
Reported by Coverity as CID #1100817
2013-10-25 19:35:38 +02:00
Riccardo Magliocchetti be2ed4dc4a core/snmp: fix usage of pointer outside of scope
Reported by Coverity as CID #1112122
2013-10-25 19:30:08 +02:00
Riccardo Magliocchetti 4777666588 plugins/rrdtools: don't leak filename
Reported by coverity as CID #1112121
2013-10-25 19:26:58 +02:00
Unbit 5647057ecc fixed UWSGI_PROFILE usage 2013-10-25 09:27:45 +02:00
Unbit 94cb950058 better error reporting for cgroups 2013-10-25 08:26:51 +02:00
Unbit 8d65371bf6 completely skip cgroups initialization when non-root 2013-10-24 21:34:07 +02:00
Unbit c747a36ae1 added PROFILE to Makefile 2013-10-24 18:55:55 +02:00
Unbit e51cb65857 fixed #427 2013-10-24 18:52:03 +02:00
unbit 8fa4fdb8c8 Merge pull request #426 from apoh/master
set python-bin from enviroment variable in Makefile
2013-10-24 06:16:12 -07:00
apoh d584857c78 set python-bin from enviroment variable in Makefile
currently the Makefile can only deal with the python-binary
wich is link to python. If you like to compile uwsgi with a
different pyhton-version you can just use

export PYTHON_BIN=/path/to/your/python
2013-10-23 17:32:36 +02:00
Unbit f0b1d79f8b added metrics api to pypy 2013-10-22 19:37:21 +02:00
Unbit 28566ad772 threads must be implicit in PyPy 2013-10-22 19:29:12 +02:00
Unbit 40c0e139d4 added metric api to python plugin 2013-10-22 16:25:56 +02:00
Unbit 04f2444ea0 added --zabbix-template 2013-10-22 12:11:19 +02:00
Unbit 9f71d28afa snmp integration with metrics subsystem 2013-10-22 10:18:09 +02:00
Unbit af262fb325 completed metric file collector 2013-10-22 07:08:12 +02:00
Unbit 243657b5aa added pluggables metric collectors 2013-10-22 06:29:01 +02:00
Unbit 032302edaa fixed #425 2013-10-22 05:18:57 +02:00
Unbit d4bd658d84 added restorable metrics 2013-10-21 19:01:06 +02:00
Unbit 78843c3e06 added --vassal-set 2013-10-21 18:21:59 +02:00
Unbit 692ba1f6b3 added shortcut mode for --metric 2013-10-21 16:13:33 +02:00
Unbit 400a9d72ef reimplemented metrics initial_value 2013-10-21 15:59:25 +02:00
Unbit 11f8f0385a added router_metrics plugin 2013-10-21 15:48:37 +02:00
Unbit c40d15981c exposed the metric routing var 2013-10-21 14:32:59 +02:00
Unbit baa1bf21f1 expose metrics to request logging 2013-10-21 10:54:19 +02:00
Unbit 3dd3122236 ported rrdtool to the metric api 2013-10-21 10:37:50 +02:00
Unbit 927ef2ccde added sockets metrics 2013-10-19 18:33:41 +02:00
Unbit af6eaf6737 completed perl metric api 2013-10-19 09:54:28 +02:00
unbit 7c543f5627 Merge pull request #424 from prymitive/daemon_fix
daemon throttle code could pass values < 0 to sleep()
2013-10-18 14:11:52 -07:00
Łukasz Mierzwa b06e35c610 fixed sleep in daemons throttle code, sleep() only accepts unsigned int, but in some cases uWSGI could pass value < 0 2013-10-18 22:33:48 +02:00
unbit 842c2148d7 fixed websocket example 2013-10-18 20:18:51 +02:00
unbit a2a94bd78e fixed websocket example for python3 2013-10-18 19:28:55 +02:00
Unbit 4452c30fc8 fixed typecasting 2013-10-18 18:46:17 +02:00
Unbit f462792c8e fixed uwgsi-docs bug 98 2013-10-18 12:13:02 +02:00
Unbit 03879fdc0c first test for metric api from apps (perl only) 2013-10-18 09:35:04 +02:00
Unbit 389d0b95d5 added the zabbix plugin (metrics based) 2013-10-17 16:30:19 +02:00
Unbit 6ec32e192f added puwsgi protocol 2013-10-17 10:15:34 +02:00
Roberto De Ioris 22c034cdca removed uwsgidump protocol 2013-10-17 05:57:43 +02:00
unbit 396d8c3022 Merge pull request #422 from prymitive/metrics_cast
missing cast to long long in metrics
2013-10-16 15:26:13 -07:00
Łukasz Mierzwa a535ecbe17 missing cast to long long in metrics 2013-10-16 22:56:31 +02:00
Unbit fd436c3e4f starting 1.9.19-dev 2013-10-16 20:59:15 +02:00
Unbit e5c245ea2f fixed stdin and embed configs 2013-10-16 20:51:26 +02:00
Unbit 3008b7c83b fixed #420 2013-10-16 05:39:28 +02:00
Unbit eca6cd3066 added --iprint 2013-10-15 20:11:22 +02:00
Unbit 691a41f290 ignore specific vars with prefix UWSGI_ 2013-10-15 18:16:03 +02:00
Unbit df4cf539a1 automatically enable metrics with stats pushers 2013-10-15 16:11:59 +02:00
Unbit baa1167dfe exposed metric api functions 2013-10-15 16:02:52 +02:00
Unbit d8a83ab7cf added metric aliases 2013-10-15 15:04:10 +02:00
Unbit 8184351b3b implemented SUM metrics and parent/child relationship 2013-10-15 14:46:53 +02:00
Unbit 4a4dbbcf69 ported the stats plugin to the metric subsystem 2013-10-15 14:08:01 +02:00
Unbit 56f79efc74 fixed json format for metrics 2013-10-15 11:13:14 +02:00
Unbit ea073a9bbd exposes metrics to stats 2013-10-15 11:11:18 +02:00
Unbit c5b2ca4b20 added delta_requests and write_errors to metrics 2013-10-15 09:02:43 +02:00
Unbit c0f9d8d2ff prepare for file as metric source 2013-10-14 19:19:05 +02:00
Unbit 497660279f Merge branch 'master' of github.com:unbit/uwsgi 2013-10-14 15:11:09 +02:00
Unbit 625395bd26 preliminary metrics subsystem code 2013-10-14 15:10:53 +02:00
Unbit 79a7797409 fixed #415 2013-10-12 08:05:56 +02:00
Unbit 3b13de3e6e check for NULL dictionary values in python autoreloader 2013-10-12 00:34:31 +02:00
Unbit 7f99855527 1.9.18.1 2013-10-11 14:27:26 +02:00
Unbit 8c29178f81 fixed kFreeBSD support 2013-10-11 16:24:46 +02:00
Unbit ed71000033 fixed FreeBSD compilation 2013-10-11 09:44:50 +02:00
Unbit 20860ed069 fixed python3 build 2013-10-11 14:07:02 +02:00
Unbit 2e62f13917 fixed mono options parsing 2013-10-11 05:59:20 +02:00
Unbit 1b2a83ce70 updated gemspec for 1.9.18 2013-10-11 05:51:19 +02:00
Unbit 113ec5ae9e added minimal profiles 2013-10-11 05:05:07 +02:00
root 68e81828d1 finally fixed the problem with python and arm (raspberrypi/sheevaplug) 2013-10-11 02:50:40 +00:00
Unbit 543790dc83 auto-modifier1 only if modifier1 is 0 2013-10-10 09:29:28 +02:00
unbit be24060578 Merge pull request #414 from arkaitzj/master
Still need to loop again when EAGAIN after a read triggered by an event, Fixes #363
2013-10-09 20:14:05 -07:00
Arkaitz Jimenez bdedc1c94c Still need to loop again when EAGAIN after a read triggered by an event 2013-10-10 00:12:57 +02:00
unbit e2454aa898 Merge pull request #413 from prymitive/backlog2
fixed backlog2 example plugin
2013-10-08 18:55:10 -07:00
Łukasz Mierzwa dfa4834be3 fixed backlog2 example plugin 2013-10-08 23:16:03 +02:00
Unbit f204249110 better fallback for non-zero modifiers 2013-10-07 17:50:43 +02:00
Unbit f4c25a6cd1 prepare for 1.9.18 release 2013-10-07 13:23:05 +02:00
Unbit fbfbacce14 fixed attach.py 2013-10-07 13:03:50 +02:00
Unbit a0eed32b3f move uWSGI 1.9 to GPL2 + linking exception 2013-10-07 12:19:33 +02:00
Unbit 9fe9fe1bb6 fixed data:// scheme 2013-10-07 11:37:52 +02:00
Unbit 192312e3ea avoid crashing on non-conformant PSGI response headers 2013-10-07 10:21:39 +02:00
Unbit ee46fe6ba6 Merge branch 'master' of github.com:unbit/uwsgi 2013-10-07 10:11:59 +02:00
Unbit 58abd07a88 support remote sources for perl scripts 2013-10-07 10:11:50 +02:00
Unbit c246a6008e correctly returns http error on connect 2013-10-07 10:11:23 +02:00
Unbit 706f1b59c3 make clang happy 2013-10-07 09:52:32 +02:00
Unbit ddbc8920f7 use uwsgi_open_and_read for perl files 2013-10-07 09:50:56 +02:00
Roberto De Ioris 7e3bf6868e fixed perl autoreload when under clang 2013-10-06 11:01:12 +02:00
Unbit 4c7ecef577 added perl auto reloader 2013-10-06 10:52:27 +02:00
Unbit e3da0aaad4 automatically returns the default app even if the modifier is wrong 2013-10-06 09:26:08 +02:00
Unbit 99e576e40c support pty on NetBSD 2013-10-06 07:04:12 +02:00
Unbit 7604ce3441 --wsgi-accept-buffers 2013-10-05 12:34:57 +02:00
Unbit a0082b5b98 accepting buffer is an option: --wsgi-accept-buffer 2013-10-05 12:32:49 +02:00
Unbit c90c639348 --wsgi-strict disable string/bytes optimizations too 2013-10-05 09:09:53 +02:00
Unbit 2e188dc25a fixed big endian support for uwsgi protocol 2013-10-05 07:15:36 +02:00
Unbit 312d21cb3f added 'before' variants for vassals templating 2013-10-05 07:07:48 +02:00
unbit 4ee138be7c Merge pull request #411 from thekad/master
updating so jvm plugin can compile in arm
2013-10-04 21:22:01 -07:00
Jorge Gallegos 299aef99b3 updating so jvm plugin can compile in arm
This *should* work for all arm versions so far and still works for i386/x86_64
2013-10-04 16:39:54 -07:00
Unbit 06953e4547 fixed uwsgiconfig.py for embed_config 2013-10-04 17:13:10 +02:00
Unbit 7565ee8740 fixed a memleak spotted by cppcheck 2013-10-04 12:29:16 +02:00
Unbit 10377f02a3 run the autoreloader even in non-apps mode when non-lazy 2013-10-04 06:22:06 +02:00
Unbit a41e6e2c61 added --emperor-cap 2013-10-04 06:11:29 +02:00
Unbit 6b2b909d33 apply PR_SET_PDEATHSIG to vassals on linux 2013-10-03 19:46:33 +02:00
Unbit 70cd18bffb added --unshare2 2013-10-03 19:43:43 +02:00
Unbit d6be4bcad9 added --mountpoint-check 2013-10-03 14:42:52 +02:00
Unbit 85530b5d8e added --exit 2013-10-03 11:38:51 +02:00
Unbit e3848e84d3 expose more clone() flags 2013-10-03 10:42:55 +02:00
Unbit 4ec9312b10 pivot_root improvements 2013-10-02 16:52:14 +02:00
Unbit aedf3b2455 reindented core/utils.c 2013-10-02 13:58:18 +02:00
Unbit 2210ec7f71 added call scheme 2013-10-02 10:58:27 +02:00
Unbit a9bee41707 added UWSGI_ADDITIONAL_SOURCES env var and additional_sources buildconf option 2013-10-02 10:52:53 +02:00
Unbit 3adbfd100f allow overriding schemes 2013-10-02 10:39:41 +02:00
Unbit 8d8de4b8da pluginized uwsgi_open_and_read 2013-10-02 10:37:39 +02:00
Unbit 099403d554 fixed #409 2013-10-02 09:39:33 +02:00
Unbit 13938a6aa7 more consistent placeholders support 2013-10-02 09:31:48 +02:00
Unbit 9be3a4aaf8 various consistency fixes for strict mode + autoload 2013-10-02 08:41:43 +02:00
Unbit 009e42f349 fixed #409 2013-10-02 07:42:41 +02:00
Unbit 207dd3bc77 fixed #407 2013-10-02 07:36:14 +02:00
Unbit feec6b3151 do not set upper magic vars in --inherit or --include mode 2013-10-01 18:42:30 +02:00
Unbit bf8207f0f1 added magic vars for original config file 2013-10-01 18:16:01 +02:00
Unbit 9fcbc6ee68 added --set-placeholder/--set-ph 2013-10-01 15:50:46 +02:00
Unbit dcb58aaa34 added UWSGI_EMBED_CONFIG variable 2013-10-01 15:39:07 +02:00
Unbit 7163d8ddd4 fixed #406 2013-10-01 15:30:39 +02:00
Unbit c7b24eec45 fixed regression in --set as a workaround for broken getopt_long 2013-10-01 15:02:33 +02:00
Unbit 1e7098f787 fixed #405 2013-10-01 13:27:50 +02:00
Unbit b28f0d9863 fixed #405 2013-10-01 12:22:30 +02:00
Unbit b49c4f4af9 chdir at every emperor glob interaction 2013-10-01 11:38:29 +02:00
Unbit 2c39aafb0b honour --force-cwd 2013-10-01 11:32:17 +02:00
unbit 1036d9c18b Merge pull request #402 from xrmx/ia64
Ia64 fixes
2013-09-30 08:31:03 -07:00
Unbit f0c8cbf190 try specified rvm paths first 2013-09-30 17:12:54 +02:00
Unbit f51db4481b added sendfile support to raw mode 2013-09-30 15:45:27 +02:00
Unbit 717eba7ab3 implemented raw response for python 2013-09-30 15:25:00 +02:00
Unbit 3cc971ba55 raw sockets must be undeferred 2013-09-30 15:01:58 +02:00
Unbit 23b3d7483f introducing raw mode 2013-09-30 13:43:13 +02:00
unbit ba03837e29 Merge pull request #297 from prymitive/dfix
fixed dump daemon process termination
2013-09-30 04:41:37 -07:00
Łukasz Mierzwa 06952fbaff wait for deamon pid after SIGTERM to prevent it from becoming zombie 2013-09-30 12:56:01 +02:00
Unbit 27be00b4cc fixed #399 2013-09-30 11:47:14 +02:00
unbit b50a377190 Merge pull request #217 from prymitive/idle_fix
zero pids after worker killed due to --idle usage
2013-09-30 01:51:22 -07:00
Unbit 1ed9cb0bec prepare for 1.9.18 2013-09-30 09:46:17 +02:00
unbit a548ede3c7 Merge pull request #400 from xrmx/config-cleanup
Some uwsgiconfig.py cleanups
2013-09-30 00:44:38 -07:00
unbit de26c09030 Merge pull request #401 from prymitive/cheaper_fix_limit
adapted cheaper algos to work properly with cheaper limits
2013-09-30 00:41:45 -07:00
Unbit 19aa7c2560 clear exception on PyObject_CheckReadBuffer error 2013-09-30 09:40:40 +02:00
Unbit 215e0c4cbc typos 2013-09-30 09:26:58 +02:00
Unbit d484acefa4 use buffer protocol in WSGI response 2013-09-30 09:25:25 +02:00
Riccardo Magliocchetti 4032efd3e8 Add proper ifdefery for namespaces on ia64
Fix #398
2013-09-29 21:45:07 +02:00
Riccardo Magliocchetti f9d412bcca uwsgiconfig: restore obsolete linux check on ia64
Fix #397
2013-09-29 21:35:38 +02:00
Łukasz Mierzwa 5f52063b9e cheaper API change to allow signaling cheaper algo if it can spawn new workers or only cheap them. Fixes #394 2013-09-29 20:30:29 +02:00
Riccardo Magliocchetti 87833abb42 uwsgiconfig: add --debug and --asan options
--debug compiles with debug symbols
--asan adds support for compiling with address sanitizer, see
http://clang.llvm.org/docs/AddressSanitizer.html#usage
Should work with clang and gcc 4.8. Does not find as many issues
as valgrind but having lot less overhead could be enabled in more
situations.

While at it handle --cflags and --build together instead of
duplicating code.
2013-09-29 18:29:14 +02:00
Riccardo Magliocchetti 0fcbd5e334 uwsgiconfig: add --verbose switch
Print the whole compilation commandlines

Based on a patch from Jonas Smedegaard
2013-09-29 17:36:26 +02:00
Riccardo Magliocchetti 5b55bf5f5c uwsgiconfig: use optparse for arguments passing
This opens the possibility (if desired) to have multiple options
passed at the same time, the same options repeated, etc...
Also it gives an help for free.
2013-09-29 17:28:45 +02:00
Riccardo Magliocchetti b8cc1d962f uwsgiconfig: cleanup report initialization 2013-09-29 13:57:06 +02:00
Unbit 762c73e2ac close workers sockets in gateways 2013-09-28 12:06:22 +02:00
Unbit 57cd0e9135 closed #391 and #392 2013-09-28 12:01:59 +02:00
Roberto De Ioris 5e0a85bff0 use execv instead of execve 2013-09-28 05:56:13 +02:00
unbit d2eaef524c Merge pull request #393 from prymitive/cheaper_limit_typo
fixed stupid typo in cheaper rss limits options validation
2013-09-27 19:51:18 -07:00
Łukasz Mierzwa a98c5a3931 fixed stupid typo in cheaper rss limits options validation 2013-09-27 23:21:45 +02:00
Unbit 040da07323 added forkptyrouter-rows and forkptyrouter-cols 2013-09-27 16:10:55 +02:00
Unbit 34f43ec97b support pty in Debian kFreeBSD 2013-09-27 08:12:45 +02:00
Unbit 7e3cfe94d6 improved forkptyrouter 2013-09-26 20:29:04 +02:00
Unbit e2c3b650a1 completed --pty-uconnect 2013-09-26 20:03:02 +02:00
Unbit 404dfaeda7 fixed initial logging 2013-09-26 19:59:49 +02:00
Unbit a1ec530945 implemented uwsgi protocol for forkptyrouter 2013-09-26 19:28:09 +02:00
Unbit b8dfd617f2 minor fixes 2013-09-26 10:18:16 +02:00
Unbit f34ed4dc47 added --attach-control-daemon 2013-09-26 09:36:31 +02:00
Unbit cd2ff0e585 emperor proxy 2013-09-26 07:51:13 +02:00
Unbit 449955562f expose 'cursed' field in emperor stats 2013-09-26 07:09:57 +02:00
Unbit 41a4bbccfc added Emperor curse support 2013-09-26 07:04:08 +02:00
Unbit 87b17c001d some typo 2013-09-26 05:32:27 +02:00
Unbit 67b7753814 use MAP_FAILED check for mmap() 2013-09-25 16:24:20 +02:00
Unbit b190744b77 on kFreeBSD python atexit will make mess, disable it for now 2013-09-25 09:20:20 +02:00
Unbit 4b603071d8 preliminary support for Debian kFreeBSD 2013-09-25 07:18:17 +02:00
Unbit 16c55f0217 preliminary libffi plugin 2013-09-24 17:45:34 +02:00
Unbit c989f2fb33 added api func uwsgi_split_quoted 2013-09-24 17:45:03 +02:00
Unbit 6429a47b0d 1.9.17.1 2013-09-24 09:56:40 +02:00
Unbit f8a48a3ae9 fixed a bug with fd 0 2013-09-24 09:52:49 +02:00
Unbit fb3272d165 fixed a stupid bug with router_http 2013-09-23 16:33:41 +02:00
Unbit be5f67906e added --emperor-wrapper 2013-09-23 14:38:42 +02:00
Unbit f730023e88 fixed a typo 2013-09-23 09:18:43 +02:00
Unbit 50954d34db prepare for 1.9.17 2013-09-22 19:32:11 +02:00
Unbit ef2d9e781f implemented fifo slots and fixed chain reloading 2013-09-22 18:36:28 +02:00
Unbit a9bb310a20 various pty improvements 2013-09-19 11:21:10 +02:00
Unbit 86f37556da fixed logpipe 2013-09-19 11:08:28 +02:00
Unbit a57617c09a added fd: logger and routable log encoders 2013-09-19 06:41:09 +02:00
Unbit 63ac62cf1d allows ANSI sequences in config files via %[ 2013-09-19 05:55:20 +02:00
Unbit ac371730fd rename pypyuwsgi.py to pyuwsgi.py 2013-09-19 04:01:31 +02:00
Unbit 4ed6588c80 fixed #99 2013-09-19 03:59:15 +02:00
Unbit 81d20edc4c more cleanup 2013-09-19 03:55:27 +02:00
Unbit a9fc6adccf fixed #386 2013-09-19 03:41:23 +02:00
Unbit 21ad94ba4e implemented C fifo command 2013-09-18 17:40:02 +02:00
Unbit 571b9f27e1 added + and - fifo commands 2013-09-18 14:44:30 +02:00
Unbit cbf9ccf062 more brutal heartbeat emperor management 2013-09-18 12:03:35 +02:00
Unbit dd8fd8f19c implemented fifo command 'W' 2013-09-18 11:38:39 +02:00
Unbit 1535b8ee13 implemented graceful shutdown 2013-09-18 11:33:50 +02:00
Unbit f2491536dd implemented fifo command P 2013-09-18 11:20:55 +02:00
Unbit 88ce0181b3 added master fifo [2] 2013-09-18 11:16:15 +02:00
Unbit 4ad2658090 added master fifo 2013-09-18 11:08:56 +02:00
unbit 8d80c5e84d Merge pull request #388 from xtfxme/patch-1
pty.c: `--pty-exec` should have a `required_argument`
2013-09-17 23:49:29 -07:00
Unbit bae9235103 added the libtcc plugin (only for hooks) 2013-09-18 07:32:12 +02:00
C Anthony Risinger 8ae2d0d00c pty.c: --pty-exec should have a required_argument 2013-09-17 14:57:15 -05:00
Unbit 373b89e70c finally removed strtok() 2013-09-17 16:03:40 +02:00
Unbit c14e18b270 another round of strtok removals 2013-09-17 15:25:06 +02:00
Unbit 68ec3afd1a another round of strtok removal 2013-09-17 15:14:55 +02:00
Unbit 8918e81256 first attempt to change from strtok to strtok_r 2013-09-17 15:00:33 +02:00
Unbit 469fd697cb fixed #383 2013-09-17 14:16:41 +02:00
Unbit 20844ebfca Merge branch 'master' of github.com:unbit/uwsgi 2013-09-17 14:09:44 +02:00
Unbit 38652076d3 fixed #384 2013-09-17 14:09:00 +02:00
unbit f13ae47fc0 Merge pull request #382 from gdamjan/master
improve php build script
2013-09-16 05:17:39 -07:00
Damjan Georgievski ad4ee9d5c3 improve php build script
use UWSGICONFIG_PHPLIBDIR to specify the directory of the php library,
useful for Debian Wheezy which puts php5.so in /usr/lib/php5

small change: don't use exceptions for flow control
2013-09-16 12:49:14 +02:00
Unbit 03a4e900ea fixed #378 2013-09-16 11:50:37 +02:00
Unbit b52dbf2aa0 added forkptyrouter 2013-09-16 06:38:29 +02:00
Unbit c7a22c3b53 improved logpipe 2013-09-15 12:02:14 +02:00
unbit 775aae3f1e Merge pull request #380 from KLab/logpipe
Add pipe logger.
2013-09-15 03:09:53 -07:00
INADA Naoki 862731ba91 Add pipe logger. 2013-09-15 16:47:58 +09:00
Unbit 8c302eee51 start 1.9.17 now 2013-09-14 15:30:23 +02:00
Łukasz Mierzwa edbff83fd6 zero pids after worker killed due to --idle usage 2013-04-08 10:32:39 +02:00
203 changed files with 11741 additions and 3628 deletions
+16
View File
@@ -1,3 +1,19 @@
----------------------------------------------------------------------
LINKING EXCEPTION
In addition to the permissions in the GNU General Public License,
the authors give you unlimited permission to link the compiled
version of this library into combinations with other programs,
and to distribute those combinations without any restriction
coming from the use of this file. (The General Public License
restrictions do apply in other respects; for example, they cover
modification of the file, and distribution when not linked into
a combined executable.)
----------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
+11 -3
View File
@@ -1,8 +1,16 @@
PYTHON := python
all:
python uwsgiconfig.py --build
$(PYTHON) uwsgiconfig.py --build $(PROFILE)
clean:
python uwsgiconfig.py --clean
$(PYTHON) uwsgiconfig.py --clean
check:
python uwsgiconfig.py --check
$(PYTHON) uwsgiconfig.py --check
plugin.%:
$(PYTHON) uwsgiconfig.py --plugin plugins/$* $(PROFILE)
%:
$(PYTHON) uwsgiconfig.py --build $@
+4 -2
View File
@@ -1,3 +1,5 @@
surprise i am empty !
The uWSGI project
Look in the online documentation on https://uwsgi-docs.readthedocs.org/en/latest/
For official documentation check: https://uwsgi-docs.readthedocs.org/en/latest/
For commercial support check: http://unbit.com/
+2 -2
View File
@@ -7,7 +7,7 @@ filename = sys.argv[1]
size = os.path.getsize(filename)
f = open(filename, 'r')
print(f.read())
os.write(1, f.read())
f.close()
print(struct.pack("<Q", size))
os.write(1, (struct.pack("<Q", size)))
+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
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados,pypy
inherit = base
+1 -3
View File
@@ -2,11 +2,9 @@
xml = auto
yaml = true
json = auto
zeromq = auto
ssl = auto
pcre = auto
routing = auto
matheval = auto
debug = false
unbit = false
xml_implementation = libxml2
@@ -17,7 +15,7 @@ plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires, router_metrics, transformation_template, stats_pusher_socket
as_shared_library = false
locking = auto
+1 -2
View File
@@ -1,4 +1,3 @@
[uwsgi]
# pypy,jvm,ring,jwsgi
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
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
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = gccgo
inherit = base
-1
View File
@@ -1,4 +1,3 @@
[uwsgi]
main_plugin = glusterfs
inherit = base
matheval = false
-5
View File
@@ -1,5 +0,0 @@
[uwsgi]
main_plugin = go
inherit = base
bin_name = libuwsgi.so
as_shared_library = true
+31
View File
@@ -0,0 +1,31 @@
[uwsgi]
xml = false
yaml = false
json = false
ssl = false
pcre = false
routing = false
debug = false
unbit = false
xml_implementation = none
yaml_implementation = none
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = psgi
inherit = minimal
-1
View File
@@ -2,7 +2,6 @@
xml = true
yaml = true
json = true
zeromq = true
ssl = true
pcre = true
routing = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = python
inherit = minimal
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = pypy
inherit = minimal
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = rack
inherit = minimal
-1
View File
@@ -2,7 +2,6 @@
xml = true
yaml = true
json = false
zeromq = false
ssl = true
pcre = true
routing = true
View File
+2 -3
View File
@@ -184,8 +184,8 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
// map instances to the log
char *list = uwsgi_str(alarms);
char *p = strtok(list, ",");
while (p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(list, ",", p, ctx) {
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
if (!uai) {
free(list);
@@ -205,7 +205,6 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
else {
ual->alarms = uall;
}
p = strtok(NULL, ",");
}
free(list);
return 0;
+86 -37
View File
@@ -4,18 +4,18 @@ extern struct uwsgi_server uwsgi;
/*
This is a general purpose async loop engine (it expects a coroutine based approach)
This is a general-purpose async loop engine (it expects a coroutine-based approach)
You can see it as an hub holding the following structures:
1) the runqueue, cores ready to be run are appended in this list
1) the runqueue, cores ready to be run are appended to this list
2) the fd list, this is a list of monitored file descriptors, a core can wait for all the file descriptors it needs
3) the timeout value, if set the current core will timeout aftert he specified number of seconds (unless an event cancel it)
3) the timeout value, if set, the current core will timeout after the specified number of seconds (unless an event cancels it)
IMPORTANT: this is not a callback based engine !!!
IMPORTANT: this is not a callback-based engine !!!
*/
@@ -28,7 +28,6 @@ void uwsgi_async_queue_is_full(time_t now) {
}
void uwsgi_async_init() {
int i;
uwsgi.async_queue = event_queue_init();
@@ -40,16 +39,9 @@ void uwsgi_async_init() {
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
// a stack of unused cores
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
// fill it with default values
for (i = 0; i < uwsgi.async; i++) {
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
}
// the first available core is the last one
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
// optimization, this array maps file descriptor to requests
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
}
@@ -159,7 +151,7 @@ static void async_expire_timeouts(uint64_t now) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
// reset teh request
// reset the request
async_reset_request(wsgi_req);
// push it in the runqueue
runqueue_push(wsgi_req);
@@ -173,6 +165,11 @@ 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){
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return -1;
}
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0)
@@ -224,8 +221,47 @@ static int async_wait_fd_read(int fd, int timeout) {
return 1;
}
static int async_wait_fd_read2(int fd0, int fd1, int timeout, int *fd) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_read(wsgi_req, fd0, timeout)) {
return -1;
}
if (async_add_fd_read(wsgi_req, fd1, timeout)) {
// reset already registered fd
async_reset_request(wsgi_req);
return -1;
}
if (uwsgi.schedule_to_main) {
uwsgi.schedule_to_main(wsgi_req);
}
if (wsgi_req->async_timed_out) {
wsgi_req->async_timed_out = 0;
return 0;
}
if (wsgi_req->async_ready_fd) {
*fd = wsgi_req->async_last_ready_fd;
return 1;
}
return -1;
}
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
if (uwsgi.async < 2 || !uwsgi.rb_async_timeouts) {
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return;
}
wsgi_req->async_ready_fd = 0;
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
@@ -236,6 +272,11 @@ 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) {
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return -1;
}
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0)
@@ -295,9 +336,8 @@ void async_schedule_to_req(void) {
// a trick to avoid calling routes again
uwsgi.wsgi_req->is_routing = 1;
#endif
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
goto end;
}
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) goto end;
if (uwsgi.schedule_to_main) {
uwsgi.schedule_to_main(uwsgi.wsgi_req);
@@ -308,29 +348,42 @@ end:
async_reset_request(uwsgi.wsgi_req);
uwsgi_close_request(uwsgi.wsgi_req);
uwsgi.wsgi_req->async_status = UWSGI_OK;
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
void async_schedule_to_req_green(void) {
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
goto end;
}
#endif
for(;;) {
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
break;
}
uwsgi.wsgi_req->switches++;
wsgi_req->switches++;
if (uwsgi.schedule_fix) {
uwsgi.schedule_fix(wsgi_req);
}
// switch after each yield
uwsgi.schedule_to_main(uwsgi.wsgi_req);
uwsgi.schedule_to_main(wsgi_req);
}
#ifdef UWSGI_ROUTING
end:
#endif
async_reset_request(uwsgi.wsgi_req);
uwsgi_close_request(uwsgi.wsgi_req);
uwsgi.wsgi_req->async_status = UWSGI_OK;
// re-set the global state
uwsgi.wsgi_req = wsgi_req;
async_reset_request(wsgi_req);
uwsgi_close_request(wsgi_req);
// re-set the global state (routing could have changed it)
uwsgi.wsgi_req = wsgi_req;
wsgi_req->async_status = UWSGI_OK;
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req;
}
void async_loop() {
@@ -353,10 +406,13 @@ void async_loop() {
void *events = event_queue_alloc(64);
struct uwsgi_socket *uwsgi_sock;
uwsgi_async_init();
uwsgi.async_runqueue = NULL;
uwsgi.wait_write_hook = async_wait_fd_write;
uwsgi.wait_read_hook = async_wait_fd_read;
uwsgi.wait_read2_hook = async_wait_fd_read2;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
@@ -465,7 +521,8 @@ void async_loop() {
// remove fd from event poll and fd proto table
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
// put request in the runqueue
// put request in the runqueue (set it as UWSGI_OK to signal the first run)
uwsgi.wsgi_req->async_status = UWSGI_OK;
runqueue_push(uwsgi.wsgi_req);
continue;
}
@@ -511,19 +568,11 @@ void async_loop() {
uwsgi.wsgi_req->switches++;
// request ended ?
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
if (uwsgi.wsgi_req->async_status <= UWSGI_OK ||
uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove from the runqueue
runqueue_remove(current_request);
// push wsgi_request in the unused stack
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from the runqueue
runqueue_remove(current_request);
}
current_request = next_request;
}
+13
View File
@@ -204,6 +204,19 @@ int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
return uwsgi_buffer_append(ub, (char *) buf, 8);
}
int uwsgi_buffer_u64le(struct uwsgi_buffer *ub, uint64_t num) {
uint8_t buf[8];
buf[0] = (uint8_t) (num & 0xff);
buf[1] = (uint8_t) ((num >> 8) & 0xff);
buf[2] = (uint8_t) ((num >> 16) & 0xff);
buf[3] = (uint8_t) ((num >> 24) & 0xff);
buf[4] = (uint8_t) ((num >> 32) & 0xff);
buf[5] = (uint8_t) ((num >> 40) & 0xff);
buf[6] = (uint8_t) ((num >> 48) & 0xff);
buf[7] = (uint8_t) ((num >> 56) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 8);
}
int uwsgi_buffer_f64be(struct uwsgi_buffer *ub, double num) {
uint8_t buf[8];
+13 -16
View File
@@ -7,7 +7,7 @@ extern struct uwsgi_server uwsgi;
/* how the cache bitmap works:
a bitmap is a shared mempry area allocated when requested by the user with --cache2
a bitmap is a shared memory area allocated when requested by the user with --cache2
Each block maps to a bit in the bitmap. If the corresponding bit is cleared
the block is usable otherwise the block scanner will search for the next one.
@@ -325,7 +325,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
exit(1);
}
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
if (!uc->items) {
if (uc->items == MAP_FAILED) {
uwsgi_error("uwsgi_cache_init()/mmap() [with store]");
exit(1);
}
@@ -335,7 +335,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
}
else {
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uc->items) {
if (uc->items == MAP_FAILED) {
uwsgi_error("uwsgi_cache_init()/mmap()");
exit(1);
}
@@ -762,7 +762,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
}
// mark used blocks;
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
// optimize teh scan
// optimize the scan
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
uc->blocks_bitmap_pos = 0;
}
@@ -773,7 +773,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
cache_unmark_blocks(uc, uci->first_block, uci->valsize);
}
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
memcpy(uc->data + (uci->first_block * uc->blocksize), val, vallen);
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
}
else {
int64_t *num = (int64_t *)(((char *) uc->data) + (uci->first_block * uc->blocksize));
@@ -1191,26 +1191,23 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
uc->store = c_store;
if (c_nodes) {
char *p = strtok(c_nodes, ";");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(c_nodes, ";", p, ctx) {
uwsgi_string_new_list(&uc->nodes, p);
p = strtok(NULL, ";");
}
}
if (c_sync) {
char *p = strtok(c_sync, ";");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(c_sync, ";", p, ctx) {
uwsgi_string_new_list(&uc->sync_nodes, p);
p = strtok(NULL, ";");
}
}
if (c_udp_servers) {
char *p = strtok(c_udp_servers, ";");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(c_udp_servers, ";", p, ctx) {
uwsgi_string_new_list(&uc->udp_servers, p);
p = strtok(NULL, ";");
}
}
@@ -1435,7 +1432,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
// ok now wait for the response, using the same buffer of the request
// NOTE: after using a uwsgi_buffer in that way we basically destroy (even if we can safely free it)
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout)) return -1;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout, NULL, NULL)) return -1;
// try to fix the buffer to maintain size info
ub->pos = rlen;
@@ -1870,7 +1867,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
}
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL, NULL)) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
close(fd);
+5
View File
@@ -2,6 +2,11 @@
extern struct uwsgi_server uwsgi;
int uwsgi_simple_wait_milliseconds_hook(int timeout) {
return poll(NULL, 0, timeout);
}
// in the future we will need to use the best clock source for each os/system
time_t uwsgi_now() {
return uwsgi.clock->seconds();
+330 -9
View File
@@ -55,10 +55,9 @@ int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
int uwsgi_logic_opt_for(char *key, char *value) {
char *p = strtok(uwsgi.logic_opt_data, " ");
while (p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(uwsgi.logic_opt_data, " ", p, ctx) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
p = strtok(NULL, " ");
}
return 1;
@@ -294,8 +293,25 @@ int uwsgi_count_options(struct uwsgi_option *uopt) {
return count;
}
int uwsgi_opt_exists(char *name) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) return 1;
op++;
}
return 0;
}
/*
avoid loops here !!!
*/
struct uwsgi_option *uwsgi_opt_get(char *name) {
struct uwsgi_option *op = uwsgi.options;
struct uwsgi_option *op;
int round = 0;
retry:
round++;
if (round > 2) goto end;
op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) {
@@ -304,10 +320,26 @@ struct uwsgi_option *uwsgi_opt_get(char *name) {
op++;
}
if (uwsgi.autoload) {
if (uwsgi_try_autoload(name)) goto retry;
}
end:
if (uwsgi.strict) {
uwsgi_log("[strict-mode] unknown config directive: %s\n", name);
exit(1);
}
return NULL;
}
void add_exported_option(char *key, char *value, int configured) {
add_exported_option_do(key, value, configured, 0);
}
void add_exported_option_do(char *key, char *value, int configured, int placeholder_only) {
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
struct uwsgi_string_list *whitelist = uwsgi.whitelist;
@@ -395,6 +427,15 @@ add:
uwsgi.exported_opts_cnt++;
uwsgi.dirty_config = 1;
if (placeholder_only) {
if (uwsgi_opt_exists(key)) {
uwsgi_log("you cannot use %s as a placeholder, it is already available as an option\n");
exit(1);
}
uwsgi.exported_opts[id]->configured = 1;
return;
}
struct uwsgi_option *op = uwsgi_opt_get(key);
if (op) {
// requires master ?
@@ -452,17 +493,16 @@ add:
if (op->flags & UWSGI_OPT_MIME) {
uwsgi.build_mime_dict = 1;
}
// enable metrics ?
if (op->flags & UWSGI_OPT_METRICS) {
uwsgi.has_metrics = 1;
}
// immediate ?
if (op->flags & UWSGI_OPT_IMMEDIATE) {
op->func(key, value, op->data);
uwsgi.exported_opts[id]->configured = 1;
}
}
else if (uwsgi.strict) {
uwsgi_log("[strict-mode] unknown config directive: %s\n", key);
exit(1);
}
}
void uwsgi_fallback_config() {
@@ -478,3 +518,284 @@ void uwsgi_fallback_config() {
// never here
}
}
int uwsgi_manage_opt(char *key, char *value) {
struct uwsgi_option *op = uwsgi_opt_get(key);
if (op) {
op->func(key, value, op->data);
return 1;
}
return 0;
}
void uwsgi_configure() {
int i;
// and now apply the remaining configs
restart:
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (uwsgi.exported_opts[i]->configured)
continue;
uwsgi.dirty_config = 0;
uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
// some option could cause a dirty config tree
if (uwsgi.dirty_config)
goto restart;
}
}
void uwsgi_opt_custom(char *key, char *value, void *data ) {
struct uwsgi_custom_option *uco = (struct uwsgi_custom_option *)data;
size_t i, count = 1;
size_t value_len = 0;
if (value)
value_len = strlen(value);
off_t pos = 0;
char **opt_argv;
char *tmp_val = NULL, *p = NULL;
// now count the number of args
for (i = 0; i < value_len; i++) {
if (value[i] == ' ') {
count++;
}
}
// allocate a tmp array
opt_argv = uwsgi_calloc(sizeof(char *) * count);
//make a copy of the value;
if (value_len > 0) {
tmp_val = uwsgi_str(value);
// fill the array of options
char *p, *ctx = NULL;
uwsgi_foreach_token(tmp_val, " ", p, ctx) {
opt_argv[pos] = p;
pos++;
}
}
else {
// no argument specified
opt_argv[0] = "";
}
#ifdef UWSGI_DEBUG
uwsgi_log("found custom option %s with %d args\n", key, count);
#endif
// now make a copy of the option template
char *tmp_opt = uwsgi_str(uco->value);
// split it
char *ctx = NULL;
uwsgi_foreach_token(tmp_opt, ";", p, ctx) {
char *equal = strchr(p, '=');
if (!equal)
goto clear;
*equal = '\0';
// build the key
char *new_key = uwsgi_str(p);
for (i = 0; i < count; i++) {
char *old_key = new_key;
char *tmp_num = uwsgi_num2str(i + 1);
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
free(tmp_num);
new_key = uwsgi_substitute(old_key, placeholder, opt_argv[i]);
if (new_key != old_key)
free(old_key);
free(placeholder);
}
// build the value
char *new_value = uwsgi_str(equal + 1);
for (i = 0; i < count; i++) {
char *old_value = new_value;
char *tmp_num = uwsgi_num2str(i + 1);
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
free(tmp_num);
new_value = uwsgi_substitute(old_value, placeholder, opt_argv[i]);
if (new_value != old_value)
free(old_value);
free(placeholder);
}
// ignore return value here
uwsgi_manage_opt(new_key, new_value);
}
clear:
free(tmp_val);
free(tmp_opt);
free(opt_argv);
}
char *uwsgi_get_exported_opt(char *key) {
int i;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (!strcmp(uwsgi.exported_opts[i]->key, key)) {
return uwsgi.exported_opts[i]->value;
}
}
return NULL;
}
char *uwsgi_get_optname_by_index(int index) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (op->shortcut == index) {
return op->name;
}
op++;
}
return NULL;
}
/*
this works as a pipeline
processes = 2
cpu_cores = 8
foobar = %(processes cpu_cores + 2)
translate as:
step1 = proceses cpu_cores = 2 8 = 28 (string concatenation)
step1 + = step1_apply_func_plus (func token)
step1_apply_func_plus 2 = 28 + 2 = 30 (math)
*/
char *uwsgi_manage_placeholder(char *key) {
enum {
concat = 0,
sum,
sub,
mul,
div,
} state;
state = concat;
char *current_value = NULL;
char *space = strchr(key, ' ');
if (!space) {
return uwsgi_get_exported_opt(key);
}
// let's start the heavy metal here
char *tmp_value = uwsgi_str(key);
char *p, *ctx = NULL;
uwsgi_foreach_token(tmp_value, " ", p, ctx) {
char *value = NULL;
if (is_a_number(p)) {
value = uwsgi_str(p);
}
else if (!strcmp(p, "+")) {
state = sum;
continue;
}
else if (!strcmp(p, "-")) {
state = sub;
continue;
}
else if (!strcmp(p, "*")) {
state = mul;
continue;
}
else if (!strcmp(p, "/")) {
state = div;
continue;
}
else if (!strcmp(p, "++")) {
if (current_value) {
int64_t tmp_num = strtoll(current_value, NULL, 10);
free(current_value);
current_value = uwsgi_64bit2str(tmp_num+1);
}
state = concat;
continue;
}
else if (!strcmp(p, "--")) {
if (current_value) {
int64_t tmp_num = strtoll(current_value, NULL, 10);
free(current_value);
current_value = uwsgi_64bit2str(tmp_num-1);
}
state = concat;
continue;
}
// find the option
else {
char *ov = uwsgi_get_exported_opt(p);
if (!ov) ov = "";
value = uwsgi_str(ov);
}
int64_t arg1n = 0, arg2n = 0;
char *arg1 = "", *arg2 = "";
switch(state) {
case concat:
if (current_value) arg1 = current_value;
if (value) arg2 = value;
char *ret = uwsgi_concat2(arg1, arg2);
if (current_value) free(current_value);
current_value = ret;
break;
case sum:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n + arg2n);
break;
case sub:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n - arg2n);
break;
case mul:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n * arg2n);
break;
case div:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
// avoid division by zero
if (arg2n == 0) {
current_value = uwsgi_64bit2str(0);
}
else {
current_value = uwsgi_64bit2str(arg1n / arg2n);
}
break;
default:
break;
}
// over engineering
if (value)
free(value);
// reset state to concat
state = concat;
}
free(tmp_value);
return current_value;
}
+23 -23
View File
@@ -6,7 +6,7 @@ extern struct uwsgi_server uwsgi;
External uwsgi daemons
There are 3 kind of daemons (read: external applications) that can be managed
There are 3 kinds of daemons (read: external applications) that can be managed
by uWSGI.
1) dumb daemons (attached with --attach-daemon)
@@ -14,12 +14,12 @@ extern struct uwsgi_server uwsgi;
and the process is respawned
2) smart daemons with daemonization
you specify a pidfile and a command
- on startup - if the pidfile does not exists or contains a not-available pid (checked with kill(pid, 0))
the daemon is respawned
- on master ckeck - if the pidfile does not exist or if it point to a non-existent pid
the daemon is respawned
- on startup - if the pidfile does not exist or contains a non-available pid (checked with kill(pid, 0))
the daemon is respawned
- on master check - if the pidfile does not exist or if it points to a non-existent pid
the daemon is respawned
3) smart daemons without daemonization
same as 2, but the daemonization and pidfile creation is managed by uWSGI
same as 2, but the daemonization and pidfile creation are managed by uWSGI
status:
@@ -139,6 +139,10 @@ int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
}
#endif
if (ud->pid == diedpid && !ud->pidfile) {
if (ud->control) {
gracefully_kill_them_all(0);
return 0;
}
uwsgi_spawn_daemon(ud);
return 1;
}
@@ -228,14 +232,16 @@ void uwsgi_detach_daemons() {
if (ud->pid > 0 && !ud->pidfile) {
#endif
uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
// try to gracefully stop daemon, kill it if it won't die
// if mercy is not set than wait up to 3 seconds
// try to stop daemon gracefully, kill it if it won't die
// if mercy is not set then wait up to 3 seconds
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
int waitpid_status;
while (!kill(ud->pid, 0)) {
kill(-ud->pid, SIGTERM);
sleep(1);
waitpid(-ud->pid, &waitpid_status, WNOHANG);
if (uwsgi_now() >= timeout) {
uwsgi_log("[uwsgi-daemons] daemon did not died in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
kill(-ud->pid, SIGKILL);
break;
}
@@ -253,11 +259,12 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
// skip unregistered daemons
if (!ud->registered) return;
int devnull = -1;
int throttle = 0;
if (uwsgi.current_time - ud->last_spawn <= 3) {
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
// if ud->respawns == 0 then we can end up with throttle < 0
if (throttle <= 0) throttle = 1;
}
pid_t pid = uwsgi_fork("uWSGI external daemon");
@@ -299,18 +306,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
if (!uwsgi.daemons_honour_stdin) {
// /dev/null will became stdin
devnull = open("/dev/null", O_RDONLY);
if (devnull < 0) {
uwsgi_error("/dev/null open()");
exit(1);
}
if (devnull != 0) {
if (dup2(devnull, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(devnull);
}
uwsgi_remap_fd(0, "/dev/null");
}
if (setsid() < 0) {
@@ -329,7 +325,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
if (throttle) {
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
sleep(throttle);
sleep((unsigned int) throttle);
}
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
@@ -412,6 +408,10 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
uwsgi_ud->last_spawn = 0;
uwsgi_ud->daemonize = daemonize;
uwsgi_ud->pidfile = pidfile;
uwsgi_ud->control = 0;
if (!strcmp(opt, "attach-control-daemon")) {
uwsgi_ud->control = 1;
}
#ifdef UWSGI_SSL
uwsgi_ud->legion = legion;
#endif
+321 -60
View File
@@ -59,12 +59,12 @@ void uwsgi_emperor_blacklist_add(char *id) {
uebi->throttle_level += (uwsgi.emperor_throttle * 1000);
}
else {
uwsgi_log("[emperor] maximum throttle level for vassal %s reached !!!\n", id);
uwsgi_log_verbose("[emperor] maximum throttle level for vassal %s reached !!!\n", id);
uebi->throttle_level = uebi->throttle_level / 2;
}
uebi->attempt++;
if (uebi->attempt == 2) {
uwsgi_log("[emperor] unloyal bad behaving vassal found: %s throttling it...\n", id);
uwsgi_log_verbose("[emperor] unloyal bad behaving vassal found: %s throttling it...\n", id);
}
return;
}
@@ -339,8 +339,13 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
struct stat st;
struct uwsgi_instance *ui_current;
if (chdir(uwsgi.cwd)) {
uwsgi_error("uwsgi_imperial_monitor_glob()/chdir()");
exit(1);
}
if (glob(ues->arg, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("glob()");
uwsgi_error("uwsgi_imperial_monitor_glob()/glob()");
return;
}
@@ -598,7 +603,7 @@ void emperor_del(struct uwsgi_instance *c_ui) {
uwsgi_log("[emperor] %s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
}
uwsgi_log("[emperor] removed uwsgi instance %s\n", c_ui->name);
uwsgi_log_verbose("[emperor] removed uwsgi instance %s\n", c_ui->name);
// put the instance in the blacklist (or update its throttling value)
if (!c_ui->loyal) {
uwsgi_emperor_blacklist_add(c_ui->name);
@@ -617,6 +622,7 @@ void emperor_del(struct uwsgi_instance *c_ui) {
}
void emperor_stop(struct uwsgi_instance *c_ui) {
if (c_ui->status == 1) return;
// remove uWSGI instance
if (write(c_ui->pipe[0], "\0", 1) != 1) {
@@ -624,10 +630,23 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
}
c_ui->status = 1;
c_ui->cursed_at = uwsgi_now();
uwsgi_log("[emperor] stop the uwsgi instance %s\n", c_ui->name);
uwsgi_log_verbose("[emperor] stop the uwsgi instance %s\n", c_ui->name);
}
void emperor_curse(struct uwsgi_instance *c_ui) {
if (c_ui->status == 1) return;
// curse uWSGI instance
c_ui->status = 1;
c_ui->cursed_at = uwsgi_now();
uwsgi_log_verbose("[emperor] curse the uwsgi instance %s (pid: %d)\n", c_ui->name, (int) c_ui->pid);
}
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
struct uwsgi_header uh;
@@ -656,8 +675,12 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
c_ui->respawns++;
c_ui->last_mod = mod;
c_ui->last_run = uwsgi_now();
// reset readyness
c_ui->ready = 0;
// reset accepting
c_ui->accepting = 0;
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
uwsgi_log_verbose("[emperor] reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid, char *socket_name) {
@@ -744,6 +767,9 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
n_ui->uid = uid;
n_ui->gid = gid;
n_ui->last_mod = born;
// start non-ready
n_ui->last_ready = 0;
n_ui->ready = 0;
// start without loyalty
n_ui->last_loyal = 0;
n_ui->loyal = 0;
@@ -817,7 +843,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
// TODO pre-start hook
// a new uWSGI instance will start
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
if (uwsgi.emperor_clone) {
char stack[PTHREAD_STACK_MIN];
pid = clone((int (*)(void *))uwsgi_emperor_spawn_vassal, stack + PTHREAD_STACK_MIN, SIGCHLD | uwsgi.emperor_clone, (void *) n_ui);
@@ -825,7 +851,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
else {
#endif
pid = fork();
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
}
#endif
if (pid < 0) {
@@ -940,6 +966,61 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#ifdef CLONE_NEWUSER
if (uwsgi.emperor_clone & CLONE_NEWUSER) {
if (setuid(0)) {
uwsgi_error("uwsgi_emperor_spawn_vassal()/setuid(0)");
exit(1);
}
}
#endif
#ifdef UWSGI_CAP
#if defined(CAP_LAST_CAP) && defined(PR_CAPBSET_READ) && defined(PR_CAPBSET_DROP)
if (uwsgi.emperor_cap && uwsgi.emperor_cap_count > 0) {
int i;
for(i=0;i<=CAP_LAST_CAP;i++) {
int has_cap = prctl(PR_CAPBSET_READ, i, 0, 0, 0);
if (has_cap == 1) {
if (i == CAP_SETPCAP) continue;
int j;int found = 0;
for(j=0;j<uwsgi.emperor_cap_count;j++) {
if (uwsgi.emperor_cap[j] == (int) i) {
found = 1; break;
}
}
if (found) continue;
if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0)) {
uwsgi_error("uwsgi_emperor_spawn_vassal()/prctl()");
uwsgi_log_verbose("unable to drop capability %lu\n", i);
exit(1);
}
}
}
// just for being paranoid
#ifdef SECBIT_KEEP_CAPS
if (prctl(SECBIT_KEEP_CAPS, 1, 0, 0, 0) < 0) {
uwsgi_error("prctl()");
exit(1);
}
#else
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
uwsgi_error("prctl()");
exit(1);
}
#endif
uwsgi_log("capabilities applied for vassal %s (pid: %d)\n", n_ui->name, (int) getpid());
}
#endif
#endif
#endif
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
if (setgid(n_ui->gid)) {
@@ -1025,18 +1106,39 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
}
int counter = 4;
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
while (uct) {
counter += 2;
uct = uct->next;
}
struct uwsgi_string_list *uct;
uwsgi_foreach(uct, uwsgi.vassals_templates_before) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_includes_before) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_set) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_templates) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_includes) counter += 2;
char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
vassal_argv[0] = uwsgi.binary_path;
vassal_argv[0] = uwsgi.emperor_wrapper ? uwsgi.emperor_wrapper: uwsgi.binary_path;
// reset counter
counter = 1;
uwsgi_foreach(uct, uwsgi.vassals_templates_before) {
vassal_argv[counter] = "--inherit";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
uwsgi_foreach (uct, uwsgi.vassals_includes_before) {
vassal_argv[counter] = "--include";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
uwsgi_foreach (uct, uwsgi.vassals_set) {
vassal_argv[counter] = "--set";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
char *colon = NULL;
if (uwsgi.emperor_broodlord) {
colon = strchr(n_ui->name, ':');
if (colon) {
@@ -1044,55 +1146,60 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
}
}
// initialize to a default value
vassal_argv[1] = "--inherit";
vassal_argv[counter] = "--inherit";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
vassal_argv[1] = "--xml";
vassal_argv[counter] = "--xml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
vassal_argv[1] = "--ini";
vassal_argv[counter] = "--ini";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
vassal_argv[1] = "--yaml";
vassal_argv[counter] = "--yaml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
vassal_argv[1] = "--yaml";
vassal_argv[counter] = "--yaml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
vassal_argv[1] = "--json";
vassal_argv[counter] = "--json";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
vassal_argv[1] = "--json";
vassal_argv[counter] = "--json";
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
while(usl) {
if (uwsgi_endswith(n_ui->name, usl->value)) {
vassal_argv[1] = "--config";
vassal_argv[counter] = "--config";
break;
}
usl = usl->next;
}
if (colon) colon[0] = ':';
if (colon) {
colon[0] = ':';
}
// start config filename...
counter++;
vassal_argv[2] = n_ui->name;
vassal_argv[counter] = n_ui->name;
if (uwsgi.emperor_magic_exec) {
if (!access(n_ui->name, R_OK | X_OK)) {
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
vassal_argv[counter] = uwsgi_concat2("exec://", n_ui->name);
}
}
if (n_ui->use_config) {
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
vassal_argv[counter] = uwsgi_concat2("emperor://", n_ui->name);
}
counter = 3;
uct = uwsgi.vassals_templates;
while (uct) {
// start templates,includes,inherit...
counter++;
uwsgi_foreach(uct, uwsgi.vassals_templates) {
vassal_argv[counter] = "--inherit";
vassal_argv[counter + 1] = uct->value;
counter += 2;
uct = uct->next;
}
uwsgi_foreach (uct, uwsgi.vassals_includes) {
vassal_argv[counter] = "--include";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
vassal_argv[counter] = NULL;
// disable stdin OR map it to the "on demand" socket
@@ -1106,18 +1213,7 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
}
}
else {
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(stdin_fd);
}
uwsgi_remap_fd(0, "/dev/null");
}
// close all of the unneded fd
@@ -1456,13 +1552,14 @@ void emperor_loop() {
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
emperor_del(ui_current);
event_queue_del_fd(uwsgi.emperor_queue, interesting_fd, event_queue_read());
emperor_curse(ui_current);
}
else {
if (byte == 17) {
ui_current->loyal = 1;
ui_current->last_loyal = uwsgi_now();
uwsgi_log("[emperor] vassal %s is now loyal\n", ui_current->name);
uwsgi_log_verbose("[emperor] vassal %s is now loyal\n", ui_current->name);
// remove it from the blacklist
uwsgi_emperor_blacklist_remove(ui_current->name);
// TODO post-start hook
@@ -1475,12 +1572,22 @@ void emperor_loop() {
emperor_stop(ui_current);
}
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
uwsgi_log_verbose("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
// here we discard socket name as broodlord/zerg cannot be on demand
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL);
free(zerg_name);
}
else if (byte == 5) {
ui_current->accepting = 1;
ui_current->last_accepting = uwsgi_now();
uwsgi_log_verbose("[emperor] vassal %s is ready to accept requests\n", ui_current->name);
}
else if (byte == 1) {
ui_current->ready = 1;
ui_current->last_ready = uwsgi_now();
uwsgi_log_verbose("[emperor] vassal %s has been spawned\n", ui_current->name);
}
}
}
else {
@@ -1506,10 +1613,14 @@ void emperor_loop() {
while (ui_current) {
if (ui_current->last_heartbeat > 0) {
if ((ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) {
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, brutally respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
// set last_heartbeat to 0 avoiding races
ui_current->last_heartbeat = 0;
emperor_respawn(ui_current, uwsgi_now());
if (ui_current->pid > 0) {
if (kill(ui_current->pid, SIGKILL)) {
uwsgi_error("[emperor] kill()");
}
}
}
}
ui_current = ui_current->ui_next;
@@ -1558,14 +1669,8 @@ void emperor_loop() {
ui_current = ui;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
if (ui_current->status == 1) {
if (ui_current->config)
free(ui_current->config);
// SAFE
emperor_del(ui_current);
break;
}
else if (ui_current->pid == diedpid) {
time_t now = uwsgi_now();
if (ui_current->pid == diedpid) {
if (ui_current->status == 0) {
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
@@ -1588,6 +1693,13 @@ void emperor_loop() {
break;
}
}
else if (ui_current->cursed_at > 0 && now - ui_current->cursed_at >= uwsgi.emperor_curse_tolerance) {
ui_current->cursed_at = now;
if (kill(ui_current->pid, SIGKILL)) {
uwsgi_error("[emperor] kill");
}
break;
}
}
@@ -1678,12 +1790,22 @@ void emperor_send_stats(int fd) {
goto end0;
if (uwsgi_stats_keylong_comma(us, "loyal", (unsigned long long) c_ui->loyal))
goto end0;
if (uwsgi_stats_keylong_comma(us, "ready", (unsigned long long) c_ui->ready))
goto end0;
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) c_ui->accepting))
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_loyal", (unsigned long long) c_ui->last_loyal))
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_ready", (unsigned long long) c_ui->last_ready))
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_accepting", (unsigned long long) c_ui->last_accepting))
goto end0;
if (uwsgi_stats_keylong_comma(us, "first_run", (unsigned long long) c_ui->first_run))
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_run", (unsigned long long) c_ui->last_run))
goto end0;
if (uwsgi_stats_keylong_comma(us, "cursed", (unsigned long long) c_ui->cursed_at))
goto end0;
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
goto end0;
@@ -1827,6 +1949,46 @@ void uwsgi_emperor_start() {
}
void uwsgi_check_emperor() {
char *emperor_fd_pass = getenv("UWSGI_EMPEROR_PROXY");
if (emperor_fd_pass) {
for(;;) {
int proxy_fd = uwsgi_connect(emperor_fd_pass, 30, 0);
if (proxy_fd < 0) {
uwsgi_error("uwsgi_check_emperor()/uwsgi_connect()");
sleep(1);
continue;
}
int count = 2;
int *fds = uwsgi_attach_fd(proxy_fd, &count, "uwsgi-emperor", 13);
if (fds && count > 0) {
char *env_emperor_fd = uwsgi_num2str(fds[0]);
if (setenv("UWSGI_EMPEROR_FD", env_emperor_fd, 1)) {
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD)");
free(env_emperor_fd);
int i; for(i=0;i<count;i++) close(fds[i]);
goto next;
}
free(env_emperor_fd);
if (count > 1) {
char *env_emperor_fd_config = uwsgi_num2str(fds[1]);
if (setenv("UWSGI_EMPEROR_FD_CONFIG", env_emperor_fd_config, 1)) {
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD_CONFIG)");
free(env_emperor_fd_config);
int i; for(i=0;i<count;i++) close(fds[i]);
goto next;
}
free(env_emperor_fd_config);
}
break;
}
next:
if (fds) free(fds);
close(proxy_fd);
sleep(1);
}
unsetenv("UWSGI_EMPEROR_PROXY");
}
char *emperor_env = getenv("UWSGI_EMPEROR_FD");
if (emperor_env) {
uwsgi.has_emperor = 1;
@@ -1882,3 +2044,102 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
}
}
void uwsgi_master_manage_emperor() {
char byte;
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
if (rlen > 0) {
uwsgi_log_verbose("received message %d from emperor\n", byte);
// remove me
if (byte == 0) {
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
}
// reload me
else if (byte == 1) {
// un-lazy the stack to trigger a real reload
uwsgi.lazy = 0;
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
}
}
else {
uwsgi_log("lost connection with my emperor !!!\n");
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
sleep(2);
exit(1);
}
}
void uwsgi_master_manage_emperor_proxy() {
struct sockaddr_un epsun;
socklen_t epsun_len = sizeof(struct sockaddr_un);
int ep_client = accept(uwsgi.emperor_fd_proxy, (struct sockaddr *) &epsun, &epsun_len);
if (ep_client < 0) {
uwsgi_error("uwsgi_master_manage_emperor_proxy()/accept()");
return;
}
int num_fds = 1;
if (uwsgi.emperor_fd_config > -1) num_fds++;
struct msghdr ep_msg;
void *ep_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
struct iovec ep_iov[2];
struct cmsghdr *cmsg;
ep_iov[0].iov_base = "uwsgi-emperor";
ep_iov[0].iov_len = 13;
ep_iov[1].iov_base = &num_fds;
ep_iov[1].iov_len = sizeof(int);
ep_msg.msg_name = NULL;
ep_msg.msg_namelen = 0;
ep_msg.msg_iov = ep_iov;
ep_msg.msg_iovlen = 2;
ep_msg.msg_flags = 0;
ep_msg.msg_control = ep_msg_control;
ep_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
cmsg = CMSG_FIRSTHDR(&ep_msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
unsigned char *ep_fd_ptr = CMSG_DATA(cmsg);
memcpy(ep_fd_ptr, &uwsgi.emperor_fd, sizeof(int));
if (num_fds > 1) {
memcpy(ep_fd_ptr + sizeof(int), &uwsgi.emperor_fd_config, sizeof(int));
}
if (sendmsg(ep_client, &ep_msg, 0) < 0) {
uwsgi_error("uwsgi_master_manage_emperor_proxy()/sendmsg()");
}
free(ep_msg_control);
close(ep_client);
}
static void emperor_notify_ready() {
if (!uwsgi.has_emperor) return;
char byte = 1;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("emperor_notify_ready()/write()");
}
}
void uwsgi_setup_emperor() {
if (!uwsgi.has_emperor) return;
uwsgi.notify_ready = emperor_notify_ready;
}
+23
View File
@@ -1,9 +1,30 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
static int error_page(struct wsgi_request *wsgi_req, struct uwsgi_string_list *l) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, l) {
struct stat st;
if (!stat(usl->value, &st)) {
int fd = open(usl->value, O_RDONLY);
if (fd >= 0) {
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/html", 9)) { close(fd); return 0;}
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) { close(fd); return 0;}
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st.st_size);
return -1;
}
}
}
return 0;
}
// generate internal server error message
void uwsgi_500(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (error_page(wsgi_req, uwsgi.error_page_500)) return;
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21);
}
@@ -11,6 +32,7 @@ void uwsgi_500(struct wsgi_request *wsgi_req) {
void uwsgi_404(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "404 Not Found", 13)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (error_page(wsgi_req, uwsgi.error_page_404)) return;
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Not Found", 9);
}
@@ -18,6 +40,7 @@ void uwsgi_404(struct wsgi_request *wsgi_req) {
void uwsgi_403(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "403 Forbidden", 13)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (error_page(wsgi_req, uwsgi.error_page_403)) return;
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
}
+6
View File
@@ -1231,6 +1231,8 @@ static int timerfd_create(clockid_t __clock_id, int __flags) {
return syscall(283, __clock_id, __flags);
#elif defined(__i386__)
return syscall(322, __clock_id, __flags);
#elif defined(__arm__)
return syscall(350, __clock_id, __flags);
#else
return -1;
#endif
@@ -1241,6 +1243,10 @@ static int timerfd_settime(int __ufd, int __flags, __const struct itimerspec *__
return syscall(286, __ufd, __flags, __utmr, __otmr);
#elif defined(__i386__)
return syscall(325, __ufd, __flags, __utmr, __otmr);
#elif defined(__arm__)
return syscall(353, __ufd, __flags, __utmr, __otmr);
#else
return -1;
#endif
}
#endif
+136
View File
@@ -0,0 +1,136 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
the --master-fifo option create a unix named pipe (fifo) you can use to send management
commands to the master:
echo r > myfifo
*/
// this var can be accessed by plugins and hooks
void (*uwsgi_fifo_table[256])(int);
static char *uwsgi_fifo_by_slot() {
int count = 0;
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.master_fifo) {
if (count == uwsgi.master_fifo_slot) return usl->value;
count++;
}
return uwsgi.master_fifo->value;
}
#define announce_fifo uwsgi_log_verbose("active master fifo is now %s\n", uwsgi_fifo_by_slot())
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; announce_fifo; }
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; announce_fifo; }
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; announce_fifo; }
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; announce_fifo; }
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; announce_fifo; }
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; announce_fifo; }
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; announce_fifo; }
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; announce_fifo; }
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; announce_fifo; }
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; announce_fifo; }
static void subscriptions_blocker() {
if (uwsgi.subscriptions_blocked) {
uwsgi_log_verbose("subscriptions re-enabled\n");
uwsgi.subscriptions_blocked = 0;
}
else {
uwsgi.subscriptions_blocked = 1;
uwsgi_log_verbose("subscriptions blocked\n");
}
}
/*
this is called as soon as possibile allowing plugins (or hooks) to override it
*/
void uwsgi_master_fifo_prepare() {
int i;
for(i=0;i<256;i++) {
uwsgi_fifo_table[i] = NULL;
}
uwsgi_fifo_table['0'] = uwsgi_fifo_set_slot_zero;
uwsgi_fifo_table['1'] = uwsgi_fifo_set_slot_one;
uwsgi_fifo_table['2'] = uwsgi_fifo_set_slot_two;
uwsgi_fifo_table['3'] = uwsgi_fifo_set_slot_three;
uwsgi_fifo_table['4'] = uwsgi_fifo_set_slot_four;
uwsgi_fifo_table['5'] = uwsgi_fifo_set_slot_five;
uwsgi_fifo_table['6'] = uwsgi_fifo_set_slot_six;
uwsgi_fifo_table['7'] = uwsgi_fifo_set_slot_seven;
uwsgi_fifo_table['8'] = uwsgi_fifo_set_slot_eight;
uwsgi_fifo_table['9'] = uwsgi_fifo_set_slot_nine;
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
uwsgi_fifo_table['c'] = uwsgi_chain_reload;
uwsgi_fifo_table['C'] = uwsgi_go_cheap;
uwsgi_fifo_table['f'] = uwsgi_refork_master;
uwsgi_fifo_table['l'] = uwsgi_log_reopen;
uwsgi_fifo_table['L'] = uwsgi_log_rotate;
uwsgi_fifo_table['p'] = suspend_resume_them_all;
uwsgi_fifo_table['P'] = uwsgi_update_pidfiles;
uwsgi_fifo_table['q'] = gracefully_kill_them_all;
uwsgi_fifo_table['Q'] = kill_them_all;
uwsgi_fifo_table['r'] = grace_them_all;
uwsgi_fifo_table['R'] = reap_them_all;
uwsgi_fifo_table['s'] = stats;
uwsgi_fifo_table['S'] = subscriptions_blocker;
uwsgi_fifo_table['w'] = uwsgi_reload_workers;
uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
}
int uwsgi_master_fifo() {
char *path = uwsgi_fifo_by_slot();
unlink(path);
if (mkfifo(path, S_IRUSR|S_IWUSR)) {
uwsgi_error("uwsgi_master_fifo()/mkfifo()");
exit(1);
}
int fd = open(path, O_RDONLY|O_NONBLOCK);
if (fd < 0) {
uwsgi_error("uwsgi_master_fifo()/open()");
exit(1);
}
uwsgi_socket_nb(fd);
return fd;
}
int uwsgi_master_fifo_manage(int fd) {
unsigned char cmd;
ssize_t rlen = read(fd, &cmd, 1);
if (rlen < 0) {
if (uwsgi_is_again()) return 0;
uwsgi_error("uwsgi_master_fifo_manage()/read()");
exit(1);
}
// fifo destroyed, recreate it
else if (rlen == 0) {
close(fd);
uwsgi.master_fifo_fd = uwsgi_master_fifo();
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
return 0;
}
if (uwsgi_fifo_table[(int) cmd]) {
uwsgi_fifo_table[(int) cmd](0);
}
return 0;
}
+1
View File
@@ -38,6 +38,7 @@ void uwsgi_fsmon_setup() {
char *space = strchr(copy, ' ');
if (!space) {
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
free(copy);
goto next;
}
*space = 0;
+1
View File
@@ -70,6 +70,7 @@ void gateway_respawn(int id) {
if (gw_pid == 0) {
uwsgi_fixup_fds(0, 0, ug);
uwsgi_close_all_sockets();
if (uwsgi.master_as_root)
uwsgi_as_root();
#ifdef __linux__
+21 -1
View File
@@ -17,7 +17,7 @@ uint32_t djb33x_hash(char *key, uint64_t keylen) {
// Murmur2 hash Copyright (C) Austin Appleby
// adapted from nginx
uint32_t murmur2_hash(char *key, uint64_t keylen) {
static uint32_t murmur2_hash(char *key, uint64_t keylen) {
uint32_t h, k;
uint8_t *ukey = (uint8_t *) key;
@@ -56,6 +56,23 @@ uint32_t murmur2_hash(char *key, uint64_t keylen) {
return h;
}
static uint32_t random_hash(char *key, uint64_t keylen) {
return (uint32_t) rand();
}
/*
not atomic, avoid its use in multithreaded modes
*/
static uint32_t rr_hash(char *key, uint64_t keylen) {
static uint32_t rr = 0;
uint32_t max_value = uwsgi_str_num(key, keylen);
uint32_t ret = rr;
rr++;
if (rr > max_value) {
rr = 0;
}
return ret;
}
struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *name) {
struct uwsgi_hash_algo *uha = uwsgi.hash_algos;
@@ -90,4 +107,7 @@ void uwsgi_hash_algo_register(char *name, uint32_t (*func)(char *, uint64_t)) {
void uwsgi_hash_algo_register_all() {
uwsgi_hash_algo_register("djb33x", djb33x_hash);
uwsgi_hash_algo_register("murmur2", murmur2_hash);
uwsgi_hash_algo_register("random", random_hash);
uwsgi_hash_algo_register("rand", random_hash);
uwsgi_hash_algo_register("rr", rr_hash);
}
+65
View File
@@ -78,6 +78,67 @@ static int uwsgi_hook_print(char *arg) {
return 0;
}
static int uwsgi_hook_unlink(char *arg) {
int ret = unlink(arg);
if (ret) {
uwsgi_error("uwsgi_hook_unlink()/unlink()");
}
return ret;
}
static int uwsgi_hook_writefifo(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook writefifo syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_NONBLOCK);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
if (errno == ENODEV) return 0;
#ifdef ENXIO
if (errno == ENXIO) return 0;
#endif
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
if (write(fd, space+1, l) != (ssize_t) l) {
uwsgi_error("uwsgi_hook_writefifo()/write()");
close(fd);
return -1;
}
close(fd);
return 0;
}
static int uwsgi_hook_write(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook write syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
if (write(fd, space+1, l) != (ssize_t) l) {
uwsgi_error("uwsgi_hook_write()/write()");
close(fd);
return -1;
}
close(fd);
return 0;
}
static int uwsgi_hook_callint(char *arg) {
char *space = strchr(arg, ' ');
if (space) {
@@ -177,6 +238,10 @@ void uwsgi_register_base_hooks() {
uwsgi_register_hook("cd", uwsgi_hook_chdir);
uwsgi_register_hook("exec", uwsgi_hook_exec);
uwsgi_register_hook("write", uwsgi_hook_write);
uwsgi_register_hook("writefifo", uwsgi_hook_writefifo);
uwsgi_register_hook("unlink", uwsgi_hook_unlink);
uwsgi_register_hook("mount", uwsgi_mount_hook);
uwsgi_register_hook("umount", uwsgi_umount_hook);
+16 -13
View File
@@ -51,6 +51,7 @@ struct http_status_codes hsc[] = {
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{"509", "Bandwidth Limit Exceeded"},
{"", NULL},
};
@@ -75,10 +76,12 @@ void uwsgi_init_default() {
uwsgi.original_log_fd = -1;
uwsgi.emperor_fd_config = -1;
uwsgi.emperor_fd_proxy = -1;
// default emperor scan frequency
uwsgi.emperor_freq = 3;
uwsgi.emperor_throttle = 1000;
uwsgi.emperor_heartbeat = 30;
uwsgi.emperor_curse_tolerance = 30;
// max 3 minutes throttling
uwsgi.emperor_max_throttle = 1000 * 180;
uwsgi.emperor_pid = -1;
@@ -167,11 +170,19 @@ void uwsgi_init_default() {
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
uwsgi.wait_milliseconds_hook = uwsgi_simple_wait_milliseconds_hook;
uwsgi.wait_read2_hook = uwsgi_simple_wait_read2_hook;
uwsgi_websockets_init();
// 1 MB default limit
uwsgi.chunked_input_limit = 1024*1024;
// clear reforked status
uwsgi.master_is_reforked = 0;
uwsgi.master_fifo_fd = -1;
uwsgi_master_fifo_prepare();
}
void uwsgi_setup_reload() {
@@ -216,21 +227,19 @@ void uwsgi_autoload_plugins_by_name(char *argv_zero) {
p = original_proc_name;
p = strstr(p, "uwsgi_");
if (p != NULL) {
plugins_requested = strtok(uwsgi_str(p + 6), "_");
while (plugins_requested) {
char *ctx = NULL;
uwsgi_foreach_token(uwsgi_str(p + 6), "_", plugins_requested, ctx) {
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
uwsgi_load_plugin(-1, plugins_requested, NULL);
plugins_requested = strtok(NULL, "_");
}
}
plugins_requested = getenv("UWSGI_PLUGINS");
if (plugins_requested) {
plugins_requested = uwsgi_concat2(plugins_requested, "");
char *p = strtok(plugins_requested, ",");
while (p != NULL) {
char *p, *ctx = NULL;
uwsgi_foreach_token(plugins_requested, ",", p, ctx) {
uwsgi_load_plugin(-1, p, NULL);
p = strtok(NULL, ",");
}
}
@@ -339,7 +348,6 @@ void uwsgi_setup_workers() {
uwsgi.workers[i].signal_pipe[0] = -1;
uwsgi.workers[i].signal_pipe[1] = -1;
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
}
uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
@@ -441,11 +449,6 @@ void sanitize_args() {
}
}
if (uwsgi.auto_snapshot > 0 && uwsgi.auto_snapshot > uwsgi.numproc) {
uwsgi_log("invalid auto-snapshot value: must be <= than processes\n");
exit(1);
}
if (uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0 && uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] >= uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]) {
uwsgi_log("invalid min-worker-lifetime value (%d), must be lower than max-worker-lifetime (%d)\n",
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME], uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]);
@@ -460,7 +463,7 @@ void sanitize_args() {
uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
exit(1);
}
if ( uwsgi.cheaper_rss_limit_soft && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
if ( uwsgi.cheaper_rss_limit_hard && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
uwsgi_log("cheaper-rss-limit-hard value must be higher than cheaper-rss-limit-soft value\n");
exit(1);
}
+314 -195
View File
@@ -116,48 +116,31 @@ end:
}
/*
extremely complex function for reading resources (files, url...)
need a lot of refactoring...
*/
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
static char *uwsgi_scheme_fd(char *url, size_t *size, int add_zero) {
int fd = atoi(url);
return uwsgi_read_fd(fd, size, add_zero);
}
int fd;
struct stat sb;
char *buffer = NULL;
static char *uwsgi_scheme_exec(char *url, size_t *size, int add_zero) {
int cpipe[2];
if (pipe(cpipe)) {
uwsgi_error("pipe()");
exit(1);
}
uwsgi_run_command(url, NULL, cpipe[1]);
char *buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
close(cpipe[0]);
close(cpipe[1]);
return buffer;
}
static char *uwsgi_scheme_http(char *url, size_t *size, int add_zero) {
char byte;
ssize_t len;
char *uri, *colon;
char *domain;
char *ip;
int body = 0;
char *magic_buf;
int body = 0;
char *buffer = NULL;
// stdin ?
if (!strcmp(url, "-")) {
buffer = uwsgi_read_fd(0, size, add_zero);
}
// fd ?
else if (!strncmp("fd://", url, 5)) {
fd = atoi(url + 5);
buffer = uwsgi_read_fd(fd, size, add_zero);
}
// exec ?
else if (!strncmp("exec://", url, 5)) {
int cpipe[2];
if (pipe(cpipe)) {
uwsgi_error("pipe()");
exit(1);
}
uwsgi_run_command(url + 7, NULL, cpipe[1]);
buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
close(cpipe[0]);
close(cpipe[1]);
}
// http url ?
else if (!strncmp("http://", url, 7)) {
domain = url + 7;
uri = strchr(domain, '/');
char *domain = url;
char *uri = strchr(domain, '/');
if (!uri) {
uwsgi_log("invalid http url\n");
exit(1);
@@ -165,14 +148,14 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
uri[0] = 0;
uwsgi_log("domain: %s\n", domain);
colon = uwsgi_get_last_char(domain, ':');
char *colon = uwsgi_get_last_char(domain, ':');
if (colon) {
colon[0] = 0;
}
ip = uwsgi_resolve_ip(domain);
char *ip = uwsgi_resolve_ip(domain);
if (!ip) {
uwsgi_log("unable to resolve address %s\n", domain);
exit(1);
@@ -186,9 +169,10 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
ip = uwsgi_concat2(ip, ":80");
}
fd = uwsgi_connect(ip, 0, 0);
int fd = uwsgi_connect(ip, 0, 0);
if (fd < 0) {
uwsgi_error("uwsgi_scheme_http()/connect()");
exit(1);
}
@@ -196,18 +180,18 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
uri[0] = '/';
len = write(fd, "GET ", 4);
len = write(fd, uri, strlen(uri));
len = write(fd, " HTTP/1.0\r\n", 11);
len = write(fd, "Host: ", 6);
if (write(fd, "GET ", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, uri, strlen(uri)) != (ssize_t) strlen(uri)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, " HTTP/1.0\r\n", 11) != 11) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, "Host: ", 6) != 6) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
uri[0] = 0;
len = write(fd, domain, strlen(domain));
if (write(fd, domain, strlen(domain)) != (ssize_t) strlen(domain)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
uri[0] = '/';
len = write(fd, "\r\nUser-Agent: uWSGI on ", 23);
len = write(fd, uwsgi.hostname, uwsgi.hostname_len);
len = write(fd, "\r\n\r\n", 4);
if (write(fd, "\r\nUser-Agent: uWSGI on ", 23) != 23) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, uwsgi.hostname, uwsgi.hostname_len) != uwsgi.hostname_len) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, "\r\n\r\n", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
int http_status_code_ptr = 0;
@@ -264,57 +248,233 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
buffer[*size - 1] = 0;
}
return buffer;
}
static char *uwsgi_scheme_emperor(char *url, size_t *size, int add_zero) {
if (uwsgi.emperor_fd_config < 0) {
uwsgi_log("this is not a vassal instance\n");
exit(1);
}
else if (!strncmp("emperor://", url, 10)) {
if (uwsgi.emperor_fd_config < 0) {
uwsgi_log("this is not a vassal instance\n");
ssize_t rlen;
struct uwsgi_header uh;
size_t remains = 4;
char *ptr = (char *) &uh;
while(remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
exit(1);
}
ssize_t rlen;
*size = 0;
struct uwsgi_header uh;
size_t remains = 4;
char *ptr = (char *) &uh;
while(remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
exit(1);
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config header from %s !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
}
remains = uh.pktsize;
if (!remains) {
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
remains = uh.pktsize;
if (!remains) {
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
exit(1);
}
char *buffer = uwsgi_calloc(remains + add_zero);
ptr = buffer;
while (remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
exit(1);
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config from %s !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
}
*size = uh.pktsize + add_zero;
return buffer;
}
static char *uwsgi_scheme_data(char *url, size_t *size, int add_zero) {
char *buffer = NULL;
int fd = open(uwsgi.binary_path, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(uwsgi.binary_path);
exit(1);
}
int slot = atoi(url);
if (slot < 0) {
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
uwsgi_log("requesting binary data slot %d\n", slot);
off_t fo = lseek(fd, 0, SEEK_END);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
int i = 0;
uint64_t datasize = 0;
for (i = 0; i <= slot; i++) {
fo = lseek(fd, -8, SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
ssize_t len = read(fd, &datasize, 8);
if (len != 8) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
if (datasize == 0) {
uwsgi_log("0 size binary data !!!\n");
exit(1);
}
fo = lseek(fd, -(datasize + 8), SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
buffer = uwsgi_calloc(remains + add_zero);
ptr = buffer;
while (remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
exit(1);
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
if (i == slot) {
*size = datasize;
if (add_zero) {
*size += 1;
}
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
len = read(fd, buffer, datasize);
if (len != (ssize_t) datasize) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
}
*size = uh.pktsize + add_zero;
}
close(fd);
return buffer;
}
static char *uwsgi_scheme_call(char *url, size_t *size, int add_zero) {
char *(*func)(void) = dlsym(RTLD_DEFAULT, url);
if (!func) {
uwsgi_log("unable to find symbol %s\n", url);
exit(1);
}
char *s = func();
if (!s) {
uwsgi_log("called symbol %s did not return a string\n", url);
exit(1);
}
*size = strlen(s);
if (add_zero) {
*size += 1;
}
char *buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, s, strlen(s));
return buffer;
}
static char *uwsgi_scheme_sym(char *url, size_t *size, int add_zero) {
void *sym_start_ptr = NULL, *sym_end_ptr = NULL;
char **raw_symbol = dlsym(RTLD_DEFAULT, url);
if (raw_symbol) {
sym_start_ptr = *raw_symbol;
sym_end_ptr = sym_start_ptr + strlen(sym_start_ptr);
goto found;
}
char *symbol = uwsgi_concat3("_binary_", url, "_start");
sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_start_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
symbol = uwsgi_concat3("_binary_", url, "_end");
sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_end_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
found:
*size = sym_end_ptr - sym_start_ptr;
if (add_zero) {
*size += 1;
}
char *buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
return buffer;
}
static char *uwsgi_scheme_section(char *url, size_t *size, int add_zero) {
#ifdef UWSGI_ELF
size_t s_len = 0;
char *buffer = uwsgi_elf_section(uwsgi.binary_path, url, &s_len);
if (!buffer) {
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
exit(1);
}
*size = s_len;
if (add_zero)
*size += 1;
return buffer;
#else
uwsgi_log("section:// scheme not supported on this platform\n");
exit(1);
#endif
}
struct uwsgi_string_list *uwsgi_register_scheme(char *name, char * (*func)(char *, size_t *, int)) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.schemes) {
if (!strcmp(usl->value, name)) goto found;
}
usl = uwsgi_string_new_list(&uwsgi.schemes, name);
found:
usl->custom_ptr = func;
return usl;
}
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
struct stat sb;
char *buffer = NULL;
ssize_t len;
char *magic_buf;
int fd;
*size = 0;
// stdin ?
if (!strcmp(url, "-")) {
buffer = uwsgi_read_fd(0, size, add_zero);
goto end;
}
#ifdef UWSGI_EMBED_CONFIG
else if (url[0] == 0) {
*size = &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG;
@@ -324,108 +484,22 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, &UWSGI_EMBED_CONFIG, &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG);
goto end;
}
#endif
else if (!strncmp("data://", url, 7)) {
fd = open(uwsgi.binary_path, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(uwsgi.binary_path);
exit(1);
}
int slot = atoi(url + 7);
if (slot < 0) {
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
uwsgi_log("requesting binary data slot %d\n", slot);
off_t fo = lseek(fd, 0, SEEK_END);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
int i = 0;
uint64_t datasize = 0;
for (i = 0; i <= slot; i++) {
fo = lseek(fd, -9, SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
ssize_t len = read(fd, &datasize, 8);
if (len != 8) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
if (datasize == 0) {
uwsgi_log("0 size binary data !!!\n");
exit(1);
}
fo = lseek(fd, -(datasize + 9), SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
if (i == slot) {
*size = datasize;
if (add_zero) {
*size += 1;
}
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
len = read(fd, buffer, datasize);
if (len != (ssize_t) datasize) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
}
}
}
else if (!strncmp("sym://", url, 6)) {
char *symbol = uwsgi_concat3("_binary_", url + 6, "_start");
void *sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_start_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
symbol = uwsgi_concat3("_binary_", url + 6, "_end");
void *sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_end_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
struct uwsgi_string_list *usl = uwsgi_check_scheme(url);
if (!usl) goto fallback;
*size = sym_end_ptr - sym_start_ptr;
if (add_zero) {
*size += 1;
}
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
}
#ifdef UWSGI_ELF
else if (!strncmp("section://", url, 10)) {
size_t s_len = 0;
buffer = uwsgi_elf_section(uwsgi.binary_path, url + 10, &s_len);
if (!buffer) {
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
exit(1);
}
*size = s_len;
if (add_zero)
*size += 1;
}
#endif
char *(*func)(char *, size_t *, int) = (char *(*)(char *, size_t *, int)) usl->custom_ptr;
buffer = func(url + usl->len + 3, size, add_zero);
if (buffer) goto end;
// never here !!!
uwsgi_log("unable to parse config file %s\n", url);
exit(1);
// fallback to file
else {
fallback:
fd = open(url, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(url);
@@ -457,7 +531,6 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
if (add_zero)
buffer[sb.st_size] = 0;
}
end:
@@ -683,11 +756,12 @@ int uwsgi_write_true_nb(int fd, char *buf, size_t remains, int timeout) {
int ret;
while(remains > 0) {
errno = 0;
ssize_t len = write(fd, ptr, remains);
if (len > 0) goto written;
if (len == 0) return -1;
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
if (uwsgi_is_again()) goto wait;
return -1;
}
wait:
@@ -838,7 +912,7 @@ ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) {
}
if (rlen == 0) return -1;
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
if (uwsgi_is_again()) goto wait;
}
return -1;
wait:
@@ -870,12 +944,12 @@ int uwsgi_read_whole_true_nb(int fd, char *buf, size_t remains, int timeout) {
}
/*
this is a pretty magic function used for read a full uwsgi response
this is a pretty magic function used for reading a full uwsgi response
it is true non blocking, so you can use it in request plugins
buffer is expected to be at least 4 bytes, rlen is a get/set value
*/
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout) {
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout, uint8_t *modifier1, uint8_t *modifier2) {
if (*rlen < 4) return -1;
char *buf = *buffer;
int ret;
@@ -888,7 +962,7 @@ int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout) {
if (len > 0) goto readok;
if (len == 0) return -1;
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
if (uwsgi_is_again()) goto wait;
return -1;
}
wait:
@@ -906,6 +980,10 @@ readok:
struct uwsgi_header *uh = (struct uwsgi_header *) buf;
uint16_t pktsize = uh->pktsize;
if (modifier1)
*modifier1 = uh->modifier1;
if (modifier2)
*modifier2 = uh->modifier2;
if (pktsize > *rlen) {
char *tmp_buf = realloc(buf, pktsize);
@@ -926,7 +1004,7 @@ readok:
if (len > 0) goto readok2;
if (len == 0) return -1;
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait2;
if (uwsgi_is_again()) goto wait2;
return -1;
}
wait2:
@@ -1097,3 +1175,44 @@ int uwsgi_ready_fd(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_ready_fd) return wsgi_req->async_last_ready_fd;
return -1;
}
void uwsgi_setup_schemes() {
uwsgi_register_scheme("emperor", uwsgi_scheme_emperor);
uwsgi_register_scheme("http", uwsgi_scheme_http);
uwsgi_register_scheme("data", uwsgi_scheme_data);
uwsgi_register_scheme("sym", uwsgi_scheme_sym);
uwsgi_register_scheme("section", uwsgi_scheme_section);
uwsgi_register_scheme("fd", uwsgi_scheme_fd);
uwsgi_register_scheme("exec", uwsgi_scheme_exec);
uwsgi_register_scheme("call", uwsgi_scheme_call);
}
struct uwsgi_string_list *uwsgi_check_scheme(char *file) {
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.schemes) {
char *url = uwsgi_concat2(usl->value, "://");
int ret = uwsgi_startswith(file, url, strlen(url));
free(url);
if (!ret) return usl;
}
return NULL;
}
void uwsgi_remap_fd(int fd, char *filename) {
int fdin = open(filename, O_RDWR);
if (fdin < 0) {
uwsgi_error_open(filename);
exit(1);
}
/* stdin */
if (fdin != fd) {
if (dup2(fdin, fd) < 0) {
uwsgi_error("uwsgi_remap_fd()/dup2()");
exit(1);
}
close(fdin);
}
}
+2
View File
@@ -106,6 +106,8 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
config_iter = json_object_iter_next(config, config_iter);
}
if (colon) colon[0] = ':';
}
#endif
+1
View File
@@ -647,6 +647,7 @@ void *uwsgi_robust_mutexes_watchdog_loop(void *arg) {
for(;;) {
uwsgi_lock(uwsgi.the_thunder_lock);
uwsgi_unlock(uwsgi.the_thunder_lock);
sleep(1);
}
return NULL;
}
+250 -272
View File
@@ -211,49 +211,6 @@ void create_logpipe(void) {
}
#ifdef UWSGI_ZEROMQ
// the zeromq logger
ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *ul, char *message, size_t len) {
if (!ul->configured) {
if (!ul->arg) {
uwsgi_log_safe("invalid zeromq syntax\n");
exit(1);
}
void *ctx = uwsgi_zeromq_init();
ul->data = zmq_socket(ctx, ZMQ_PUSH);
if (ul->data == NULL) {
uwsgi_error_safe("zmq_socket()");
exit(1);
}
if (zmq_connect(ul->data, ul->arg) < 0) {
uwsgi_error_safe("zmq_connect()");
exit(1);
}
ul->configured = 1;
}
zmq_msg_t msg;
if (zmq_msg_init_size(&msg, len) == 0) {
memcpy(zmq_msg_data(&msg), message, len);
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
zmq_sendmsg(ul->data, &msg, 0);
#else
zmq_send(ul->data, &msg, 0);
#endif
zmq_msg_close(&msg);
}
return 0;
}
#endif
// log to the specified file or udp address
void logto(char *logfile) {
@@ -488,7 +445,6 @@ void uwsgi_logvar_add(struct wsgi_request *wsgi_req, char *key, uint8_t keylen,
void uwsgi_check_logrotate(void) {
char message[1024];
int need_rotation = 0;
int need_reopen = 0;
@@ -499,7 +455,7 @@ void uwsgi_check_logrotate(void) {
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
}
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
if (uwsgi.log_maxsize > 0 && (uint64_t) uwsgi.shared->logsize > uwsgi.log_maxsize) {
need_rotation = 1;
}
@@ -512,70 +468,82 @@ void uwsgi_check_logrotate(void) {
}
if (need_rotation) {
char *rot_name = uwsgi.log_backupname;
int need_free = 0;
if (rot_name == NULL) {
char *ts_str = uwsgi_num2str((int) uwsgi_now());
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
free(ts_str);
need_free = 1;
}
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
if (rename(uwsgi.logfile, rot_name) == 0) {
// reopen logfile dup'it and eventually gracefully reload workers;
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
else {
if (dup2(fd, uwsgi.original_log_fd) < 0) {
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
}
}
else {
uwsgi_error("unable to rotate log: rename()");
}
if (need_free)
free(rot_name);
uwsgi_log_rotate();
}
else if (need_reopen) {
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
// reopen logfile;
close(uwsgi.original_log_fd);
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
uwsgi_log_reopen();
}
}
void uwsgi_log_rotate() {
char message[1024];
if (!uwsgi.logfile) return;
char *rot_name = uwsgi.log_backupname;
int need_free = 0;
if (rot_name == NULL) {
char *ts_str = uwsgi_num2str((int) uwsgi_now());
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
free(ts_str);
need_free = 1;
}
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
if (rename(uwsgi.logfile, rot_name) == 0) {
// reopen logfile dup'it and eventually gracefully reload workers;
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
else {
if (dup2(fd, uwsgi.original_log_fd) < 0) {
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
}
}
else {
uwsgi_error("unable to rotate log: rename()");
}
if (need_free)
free(rot_name);
}
void uwsgi_log_reopen() {
char message[1024];
if (!uwsgi.logfile) return;
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
// reopen logfile;
close(uwsgi.original_log_fd);
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
return;
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
}
void log_request(struct wsgi_request *wsgi_req) {
@@ -607,6 +575,9 @@ void log_request(struct wsgi_request *wsgi_req) {
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SENDFILE] && wsgi_req->via == UWSGI_VIA_SENDFILE) {
goto logit;
}
if (uwsgi.shared->options[UWSGI_OPTION_LOG_IOERROR] && wsgi_req->read_errors > 0 && wsgi_req->write_errors > 0) {
goto logit;
}
if (!log_it)
return;
@@ -970,6 +941,20 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 0;
}
}
// var
else if (logchunk->type == 5) {
uint16_t value_len = 0;
char *value = uwsgi_get_var(wsgi_req, logchunk->ptr, logchunk->len, &value_len);
// could be NULL
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = value;
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = (size_t) value_len;
}
// metric
else if (logchunk->type == 4) {
int64_t metric = uwsgi_metric_get(logchunk->ptr, NULL);
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = uwsgi_64bit2str(metric);
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = strlen(uwsgi.logvectors[wsgi_req->async_id][pos].iov_base);
}
if (uwsgi.logvectors[wsgi_req->async_id][pos].iov_len == 0 && logchunk->type != 0) {
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = (char *) empty_var;
@@ -995,10 +980,6 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
}
}
void uwsgi_logit_lf_strftime(struct wsgi_request *wsgi_req) {
uwsgi_log("lf strftime\n");
}
void uwsgi_build_log_format(char *format) {
int state = 0;
char *ptr = format;
@@ -1122,6 +1103,16 @@ static ssize_t uwsgi_lf_ftime(struct wsgi_request * wsgi_req, char **buf) {
return ret;
}
static ssize_t uwsgi_lf_tmsecs(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_64bit2str(wsgi_req->start_of_request / (int64_t) 1000);
return strlen(*buf);
}
static ssize_t uwsgi_lf_tmicros(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_64bit2str(wsgi_req->start_of_request);
return strlen(*buf);
}
static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
return strlen(*buf);
@@ -1197,6 +1188,54 @@ static ssize_t uwsgi_lf_headers(struct wsgi_request * wsgi_req, char **buf) {
return strlen(*buf);
}
static ssize_t uwsgi_lf_werr(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str((int) wsgi_req->write_errors);
return strlen(*buf);
}
static ssize_t uwsgi_lf_rerr(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str((int) wsgi_req->read_errors);
return strlen(*buf);
}
static ssize_t uwsgi_lf_ioerr(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str((int) (wsgi_req->write_errors + wsgi_req->read_errors));
return strlen(*buf);
}
struct uwsgi_logchunk *uwsgi_register_logchunk(char *name, ssize_t (*func)(struct wsgi_request *, char **), int need_free) {
struct uwsgi_logchunk *old_logchunk = NULL, *logchunk = uwsgi.registered_logchunks;
while(logchunk) {
if (!strcmp(logchunk->name, name)) goto found;
old_logchunk = logchunk;
logchunk = logchunk->next;
}
logchunk = uwsgi_calloc(sizeof(struct uwsgi_logchunk));
logchunk->name = name;
if (old_logchunk) {
old_logchunk->next = logchunk;
}
else {
uwsgi.registered_logchunks = logchunk;
}
found:
logchunk->func = func;
logchunk->free = need_free;
logchunk->type = 3;
return logchunk;
}
struct uwsgi_logchunk *uwsgi_get_logchunk_by_name(char *name, size_t name_len) {
struct uwsgi_logchunk *logchunk = uwsgi.registered_logchunks;
while(logchunk) {
if (!uwsgi_strncmp(name, name_len, logchunk->name, strlen(logchunk->name))) {
return logchunk;
}
logchunk = logchunk->next;
}
return NULL;
}
void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
struct uwsgi_logchunk *logchunk = uwsgi.logchunks;
@@ -1217,10 +1256,12 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
}
/*
0 -> raw test
0 -> raw text
1 -> offsetof variable
2 -> logvar
3 -> func
4 -> metric
5 -> request variable
*/
logchunk->type = variable;
@@ -1230,161 +1271,29 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->len = len;
// variable
if (variable) {
if (!uwsgi_strncmp(ptr, len, "uri", 3)) {
logchunk->pos = offsetof(struct wsgi_request, uri);
logchunk->pos_len = offsetof(struct wsgi_request, uri_len);
struct uwsgi_logchunk *rlc = uwsgi_get_logchunk_by_name(ptr, len);
if (rlc) {
if (rlc->type == 1) {
logchunk->pos = rlc->pos;
logchunk->pos_len = rlc->pos_len;
}
else if (rlc->type == 3) {
logchunk->type = 3;
logchunk->func = rlc->func;
logchunk->free = rlc->free;
}
}
else if (!uwsgi_strncmp(ptr, len, "method", 6)) {
logchunk->pos = offsetof(struct wsgi_request, method);
logchunk->pos_len = offsetof(struct wsgi_request, method_len);
// var
else if (!uwsgi_starts_with(ptr, len, "var.", 4)) {
logchunk->type = 5;
logchunk->ptr = ptr+4;
logchunk->len = len-4;
logchunk->free = 0;
}
else if (!uwsgi_strncmp(ptr, len, "user", 4)) {
logchunk->pos = offsetof(struct wsgi_request, remote_user);
logchunk->pos_len = offsetof(struct wsgi_request, remote_user_len);
}
else if (!uwsgi_strncmp(ptr, len, "addr", 4)) {
logchunk->pos = offsetof(struct wsgi_request, remote_addr);
logchunk->pos_len = offsetof(struct wsgi_request, remote_addr_len);
}
else if (!uwsgi_strncmp(ptr, len, "host", 4)) {
logchunk->pos = offsetof(struct wsgi_request, host);
logchunk->pos_len = offsetof(struct wsgi_request, host_len);
}
else if (!uwsgi_strncmp(ptr, len, "proto", 5)) {
logchunk->pos = offsetof(struct wsgi_request, protocol);
logchunk->pos_len = offsetof(struct wsgi_request, protocol_len);
}
else if (!uwsgi_strncmp(ptr, len, "uagent", 6)) {
logchunk->pos = offsetof(struct wsgi_request, user_agent);
logchunk->pos_len = offsetof(struct wsgi_request, user_agent_len);
}
else if (!uwsgi_strncmp(ptr, len, "referer", 7)) {
logchunk->pos = offsetof(struct wsgi_request, referer);
logchunk->pos_len = offsetof(struct wsgi_request, referer_len);
}
else if (!uwsgi_strncmp(ptr, len, "status", 6)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_status;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "rsize", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_rsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "hsize", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_hsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "size", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_size;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "cl", 2)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_cl;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "micros", 6)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_micros;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "msecs", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_msecs;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "time", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_time;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ltime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ltime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ftime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ftime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ctime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ctime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "epoch", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_epoch;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "pid", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_pid;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "wid", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_wid;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "switches", 8)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_switches;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "vars", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_vars;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "core", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_core;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "vsz", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_vsz;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "rss", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_rss;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "vszM", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_vszM;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "rssM", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_rssM;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "pktsize", 7)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_pktsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "modifier1", 9)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_modifier1;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "modifier2", 9)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_modifier2;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "headers", 7)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_headers;
// metric
else if (!uwsgi_starts_with(ptr, len, "metric.", 7)) {
logchunk->type = 4;
logchunk->ptr = uwsgi_concat2n(ptr+7, len - 7, "", 0);
logchunk->free = 1;
}
// logvar
@@ -1401,6 +1310,16 @@ static void uwsgi_log_func_do(struct uwsgi_string_list *encoders, struct uwsgi_l
size_t new_msg_len = len;
while(usl) {
struct uwsgi_log_encoder *ule = (struct uwsgi_log_encoder *) usl->custom_ptr;
if (ule->use_for) {
if (ul && ul->id) {
if (strcmp(ule->use_for, ul->id)) {
goto next;
}
}
else {
goto next;
}
}
size_t rlen = 0;
char *buf = ule->func(ule, new_msg, new_msg_len, &rlen);
if (new_msg != msg) {
@@ -1408,6 +1327,7 @@ static void uwsgi_log_func_do(struct uwsgi_string_list *encoders, struct uwsgi_l
}
new_msg = buf;
new_msg_len = rlen;
next:
usl = usl->next;
}
if (ul) {
@@ -1625,21 +1545,28 @@ void uwsgi_setup_log_encoders() {
uwsgi_foreach(usl, uwsgi.requested_log_encoders) {
char *space = strchr(usl->value, ' ');
if (space) *space = 0;
char *use_for = strchr(usl->value, ':');
if (use_for) *use_for = 0;
struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
if (!ule) {
uwsgi_log("log encoder \"%s\" not found\n", usl->value);
exit(1);
}
if (space) *space = ' ';
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
if (use_for) {
ule2->use_for = uwsgi_str(use_for+1);
*use_for = ':';
}
// we use a copy
if (space) {
*space = ' ';
ule2->args = uwsgi_str(space+1);
}
else {
ule2->args = uwsgi_str("");
}
usl->custom_ptr = ule2;
uwsgi_log("[log-encoder] registered %s\n", usl->value);
}
@@ -1647,21 +1574,27 @@ void uwsgi_setup_log_encoders() {
uwsgi_foreach(usl, uwsgi.requested_log_req_encoders) {
char *space = strchr(usl->value, ' ');
if (space) *space = 0;
char *use_for = strchr(usl->value, ':');
if (use_for) *use_for = 0;
struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
if (!ule) {
uwsgi_log("log encoder \"%s\" not found\n", usl->value);
exit(1);
}
if (space) *space = ' ';
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
if (use_for) {
ule2->use_for = uwsgi_str(use_for+1);
*use_for = ':';
}
// we use a copy
if (space) {
ule2->args = uwsgi_str(space+1);
}
else {
ule2->args = uwsgi_str("");
}
if (space) {
*space = ' ';
ule2->args = uwsgi_str(space+1);
}
else {
ule2->args = uwsgi_str("");
}
usl->custom_ptr = ule2;
uwsgi_log("[log-req-encoder] registered %s\n", usl->value);
}
@@ -1807,7 +1740,7 @@ void uwsgi_log_encoder_parse_vars(struct uwsgi_log_encoder *ule) {
/*
// format: foo ${var} bar
msg (the logline)
msgnl (the logine with newline)
msgnl (the logline with newline)
unix (the time_t value)
micros (current microseconds)
strftime (strftime)
@@ -1933,6 +1866,51 @@ end:
return buf;
}
#define r_logchunk(x) uwsgi_register_logchunk(#x, uwsgi_lf_ ## x, 1)
#define r_logchunk_offset(x, y) { struct uwsgi_logchunk *lc = uwsgi_register_logchunk(#x, NULL, 0); lc->pos = offsetof(struct wsgi_request, y); lc->pos_len = offsetof(struct wsgi_request, y ## _len); lc->type = 1; lc->free=0;}
void uwsgi_register_logchunks() {
// offsets
r_logchunk_offset(uri, uri);
r_logchunk_offset(method, method);
r_logchunk_offset(user, remote_user);
r_logchunk_offset(addr, remote_addr);
r_logchunk_offset(host, host);
r_logchunk_offset(proto, protocol);
r_logchunk_offset(uagent, user_agent);
r_logchunk_offset(referer, referer);
// funcs
r_logchunk(status);
r_logchunk(rsize);
r_logchunk(hsize);
r_logchunk(size);
r_logchunk(cl);
r_logchunk(micros);
r_logchunk(msecs);
r_logchunk(tmsecs);
r_logchunk(tmicros);
r_logchunk(time);
r_logchunk(ltime);
r_logchunk(ftime);
r_logchunk(ctime);
r_logchunk(epoch);
r_logchunk(pid);
r_logchunk(wid);
r_logchunk(switches);
r_logchunk(vars);
r_logchunk(core);
r_logchunk(vsz);
r_logchunk(rss);
r_logchunk(vszM);
r_logchunk(rssM);
r_logchunk(pktsize);
r_logchunk(modifier1);
r_logchunk(modifier2);
r_logchunk(headers);
r_logchunk(werr);
r_logchunk(rerr);
r_logchunk(ioerr);
}
void uwsgi_log_encoders_register_embedded() {
uwsgi_register_log_encoder("prefix", uwsgi_log_encoder_prefix);
+159 -140
View File
@@ -2,15 +2,30 @@
extern struct uwsgi_server uwsgi;
void uwsgi_restore_auto_snapshot(int signum) {
void uwsgi_update_load_counters() {
if (uwsgi.workers[1].snapshot > 0) {
uwsgi.restore_snapshot = 1;
}
else {
uwsgi_log("[WARNING] no snapshot available\n");
int i;
uint64_t busy_workers = 0;
uint64_t idle_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) == 0) {
idle_workers++;
}
else {
busy_workers++;
}
}
}
if (busy_workers >= (uint64_t) uwsgi.numproc) {
ushared->overloaded++;
}
ushared->busy_workers = busy_workers;
ushared->idle_workers = idle_workers;
}
void uwsgi_block_signal(int signum) {
@@ -32,24 +47,25 @@ void uwsgi_unblock_signal(int signum) {
}
void uwsgi_master_manage_udp(int udp_fd) {
char buf[4096];
struct sockaddr_in udp_client;
char udp_client_addr[16];
int i;
socklen_t udp_len = sizeof(udp_client);
ssize_t rlen = recvfrom(udp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
ssize_t rlen = recvfrom(udp_fd, buf, 4096, 0, (struct sockaddr *) &udp_client, &udp_len);
if (rlen < 0) {
uwsgi_error("recvfrom()");
uwsgi_error("uwsgi_master_manage_udp()/recvfrom()");
}
else if (rlen > 0) {
memset(udp_client_addr, 0, 16);
if (inet_ntop(AF_INET, &udp_client.sin_addr.s_addr, udp_client_addr, 16)) {
if (uwsgi.wsgi_req->buffer[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
if (buf[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
}
else if (uwsgi.wsgi_req->buffer[0] == 0x30 && uwsgi.snmp) {
manage_snmp(udp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
else if (buf[0] == 0x30 && uwsgi.snmp) {
manage_snmp(udp_fd, (uint8_t *) buf, rlen, &udp_client);
}
else {
@@ -57,7 +73,7 @@ void uwsgi_master_manage_udp(int udp_fd) {
int udp_managed = 0;
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->manage_udp) {
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, uwsgi.wsgi_req->buffer, rlen)) {
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, buf, rlen)) {
udp_managed = 1;
break;
}
@@ -66,74 +82,17 @@ void uwsgi_master_manage_udp(int udp_fd) {
// else a simple udp logger
if (!udp_managed) {
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, uwsgi.wsgi_req->buffer);
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, buf);
}
}
}
else {
uwsgi_error("inet_ntop()");
uwsgi_error("uwsgi_master_manage_udp()/inet_ntop()");
}
}
}
void uwsgi_master_manage_emperor() {
char byte;
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
if (rlen > 0) {
uwsgi_log_verbose("received message %d from emperor\n", byte);
// remove me
if (byte == 0) {
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
}
// reload me
else if (byte == 1) {
// un-lazy the stack to trigger a real reload
uwsgi.lazy = 0;
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
}
}
else {
uwsgi_log("lost connection with my emperor !!!\n");
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
sleep(2);
exit(1);
}
}
void uwsgi_master_restore_snapshot() {
int i, waitpid_status;
uwsgi_log("[snapshot] restoring workers...\n");
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid == 0)
continue;
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
uwsgi.workers[i].pid = 0;
uwsgi.workers[i].snapshot = 0;
}
else {
uwsgi.workers[i].pid = uwsgi.workers[i].snapshot;
uwsgi.workers[i].snapshot = 0;
kill(uwsgi.workers[i].pid, SIGURG);
uwsgi_log("Restored uWSGI worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
}
}
uwsgi.restore_snapshot = 0;
}
void suspend_resume_them_all(int signum) {
int i;
@@ -222,8 +181,8 @@ int uwsgi_get_tcp_info(int fd) {
#elif defined(__FreeBSD__)
if (!uwsgi.shared->ti.__tcpi_sacked) {
#endif
return 0;
}
return 0;
}
#if defined(__linux__)
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.tcpi_unacked;
@@ -242,12 +201,12 @@ int uwsgi_get_tcp_info(int fd) {
uwsgi_error("write()");
}
else {
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long ) uwsgi.shared->load);
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->load);
}
}
}
if (uwsgi.shared->load >= uwsgi.shared->max_load) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long ) uwsgi.shared->load, (unsigned long long ) uwsgi.shared->max_load);
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long) uwsgi.shared->load, (unsigned long long) uwsgi.shared->max_load);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
@@ -306,7 +265,6 @@ int master_loop(char **argv, char **environ) {
struct uwsgi_rb_timer *min_timeout;
struct uwsgi_rbtree *rb_timers = uwsgi_init_rb_timer();
if (uwsgi.procname_master) {
uwsgi_set_processname(uwsgi.procname_master);
}
@@ -332,9 +290,6 @@ int master_loop(char **argv, char **environ) {
}
uwsgi_unix_signal(SIGINT, kill_them_all);
uwsgi_unix_signal(SIGUSR1, stats);
if (uwsgi.auto_snapshot) {
uwsgi_unix_signal(SIGURG, uwsgi_restore_auto_snapshot);
}
atexit(uwsgi_master_cleanup_hooks);
@@ -346,6 +301,11 @@ int master_loop(char **argv, char **environ) {
#endif
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]);
if (uwsgi.master_fifo) {
uwsgi.master_fifo_fd = uwsgi_master_fifo();
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
}
if (uwsgi.spoolers) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
}
@@ -374,6 +334,7 @@ int master_loop(char **argv, char **environ) {
#ifdef UWSGI_SSL
uwsgi_start_legions();
#endif
uwsgi_metrics_start_collector();
uwsgi_add_reload_fds();
@@ -383,7 +344,18 @@ int master_loop(char **argv, char **environ) {
uwsgi.wsgi_req->buffer = uwsgi.workers[0].cores[0].buffer;
if (uwsgi.has_emperor) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
if (uwsgi.emperor_proxy) {
uwsgi.emperor_fd_proxy = bind_to_unix(uwsgi.emperor_proxy, uwsgi.listen_queue, 0, 0);
if (uwsgi.emperor_fd_proxy < 0) exit(1);
if (chmod(uwsgi.emperor_proxy, S_IRUSR|S_IWUSR)) {
uwsgi_error("[emperor-proxy] chmod()");
exit(1);
}
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd_proxy);
}
else {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
}
}
if (uwsgi.zerg_server) {
@@ -477,7 +449,7 @@ int master_loop(char **argv, char **environ) {
uwsgi_check_touches(uwsgi.touch_gracefully_stop);
// update exec touches
struct uwsgi_string_list *usl = uwsgi.touch_exec;
while(usl) {
while (usl) {
char *space = strchr(usl->value, ' ');
if (space) {
*space = 0;
@@ -489,20 +461,42 @@ int master_loop(char **argv, char **environ) {
uwsgi_check_touches(uwsgi.touch_exec);
// update signal touches
usl = uwsgi.touch_signal;
while(usl) {
char *space = strchr(usl->value, ' ');
if (space) {
*space = 0;
usl->len = strlen(usl->value);
usl->custom_ptr = space + 1;
}
usl = usl->next;
}
uwsgi_check_touches(uwsgi.touch_signal);
while (usl) {
char *space = strchr(usl->value, ' ');
if (space) {
*space = 0;
usl->len = strlen(usl->value);
usl->custom_ptr = space + 1;
}
usl = usl->next;
}
uwsgi_check_touches(uwsgi.touch_signal);
// fsmon
uwsgi_fsmon_setup();
uwsgi_foreach(usl, uwsgi.signal_timers) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid signal timer syntax, must be: <signal> <seconds>\n");
exit(1);
}
*space = 0;
uwsgi_add_timer(atoi(usl->value), atoi(space+1));
*space = ' ';
}
uwsgi_foreach(usl, uwsgi.rb_signal_timers) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid redblack signal timer syntax, must be: <signal> <seconds>\n");
exit(1);
}
*space = 0;
uwsgi_signal_add_rb_timer(atoi(usl->value), atoi(space+1), 0);
*space = ' ';
}
// setup cheaper algos (can be stacked)
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
if (uwsgi.requested_cheaper_algo) {
@@ -556,21 +550,6 @@ int master_loop(char **argv, char **environ) {
// check for daemons (smart and dumb)
uwsgi_daemons_smart_check();
if (uwsgi.respawn_snapshots) {
for (i = 1; i <= uwsgi.respawn_snapshots; i++) {
if (uwsgi_respawn_worker(i))
return 0;
}
uwsgi.respawn_snapshots = 0;
}
if (uwsgi.restore_snapshot) {
uwsgi_master_restore_snapshot();
continue;
}
// cheaper management
if (uwsgi.cheaper && !uwsgi.status.is_cheap && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
if (!uwsgi_calc_cheaper())
@@ -600,8 +579,10 @@ int master_loop(char **argv, char **environ) {
/* all processes ok, doing status scan after N seconds */
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!check_interval)
if (!check_interval) {
check_interval = 1;
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = 1;
}
// add unregistered file monitors
@@ -636,14 +617,14 @@ int master_loop(char **argv, char **environ) {
if (ushared->rb_timers_cnt > 0) {
min_timeout = uwsgi_min_rb_timer(rb_timers, NULL);
if (min_timeout == NULL) {
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
}
else {
check_interval = min_timeout->value - uwsgi_now();
if (check_interval <= 0) {
if (min_timeout) {
int delta = min_timeout->value - uwsgi_now();
if (delta <= 0) {
expire_rb_timeouts(rb_timers);
check_interval = 0;
}
// if the timer expires before the check_interval, override it
else if (delta < check_interval) {
check_interval = delta;
}
}
}
@@ -657,6 +638,9 @@ int master_loop(char **argv, char **environ) {
}
}
// update load counter
uwsgi_update_load_counters();
// check uwsgi-cron table
if (ushared->cron_cnt) {
@@ -697,8 +681,10 @@ int master_loop(char **argv, char **environ) {
uwsgi_master_check_idle();
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!check_interval)
if (!check_interval) {
check_interval = 1;
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = 1;
}
// get listen_queue status
@@ -731,6 +717,7 @@ int master_loop(char **argv, char **environ) {
uwsgi_master_check_mules_deadline();
uwsgi_master_check_spoolers_deadline();
uwsgi_master_check_crons_deadline();
uwsgi_master_check_mountpoints();
#ifdef __linux__
#ifdef MADV_MERGEABLE
@@ -741,7 +728,7 @@ int master_loop(char **argv, char **environ) {
#endif
// resubscribe every 10 cycles by default
if (( (uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
if (((uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
uwsgi_subscribe_all(0, 0);
}
@@ -765,40 +752,34 @@ int master_loop(char **argv, char **environ) {
}
touched = uwsgi_check_touches(uwsgi.touch_workers_reload);
if (touched) {
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
uwsgi_block_signal(SIGHUP);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_curse(i, SIGHUP);
}
}
uwsgi_unblock_signal(SIGHUP);
continue;
}
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
uwsgi_reload_workers();
continue;
}
touched = uwsgi_check_touches(uwsgi.touch_chain_reload);
if (touched) {
if (uwsgi.status.chain_reloading == 0) {
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
uwsgi.status.chain_reloading = 1;
}
else {
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
}
}
// be sure to run it as the last touch check
touched = uwsgi_check_touches(uwsgi.touch_exec);
if (touched) {
if (uwsgi_run_command( touched , NULL, -1) >= 0) {
if (uwsgi_run_command(touched, NULL, -1) >= 0) {
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
}
}
touched = uwsgi_check_touches(uwsgi.touch_signal);
if (touched) {
if (touched) {
uint8_t signum = atoi(touched);
uwsgi_route_signal(signum);
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
}
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
}
}
continue;
@@ -815,12 +796,18 @@ int master_loop(char **argv, char **environ) {
// reload gateways and daemons only on normal workflow (+outworld status)
if (!uwsgi_instance_is_reloading && !uwsgi_instance_is_dying) {
if (uwsgi_master_check_emperor_death(diedpid)) continue;
if (uwsgi_master_check_spoolers_death(diedpid)) continue;
if (uwsgi_master_check_mules_death(diedpid)) continue;
if (uwsgi_master_check_gateways_death(diedpid)) continue;
if (uwsgi_master_check_daemons_death(diedpid)) continue;
if (uwsgi_master_check_cron_death(diedpid)) continue;
if (uwsgi_master_check_emperor_death(diedpid))
continue;
if (uwsgi_master_check_spoolers_death(diedpid))
continue;
if (uwsgi_master_check_mules_death(diedpid))
continue;
if (uwsgi_master_check_gateways_death(diedpid))
continue;
if (uwsgi_master_check_daemons_death(diedpid))
continue;
if (uwsgi_master_check_cron_death(diedpid))
continue;
}
@@ -885,8 +872,9 @@ next:
// 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
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
if (!uwsgi.workers[thewid].cursed_at) uwsgi.workers[thewid].cursed_at = uwsgi_now();
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
if (!uwsgi.workers[thewid].cursed_at)
uwsgi.workers[thewid].cursed_at = uwsgi_now();
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now() - uwsgi.workers[thewid].cursed_at));
uwsgi.workers[thewid].cursed_at = 0;
continue;
}
@@ -964,3 +952,34 @@ next:
// never here
}
void uwsgi_reload_workers() {
int i;
uwsgi_block_signal(SIGHUP);
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_curse(i, SIGHUP);
}
}
uwsgi_unblock_signal(SIGHUP);
}
void uwsgi_chain_reload() {
if (!uwsgi.status.chain_reloading) {
uwsgi_log_verbose("chain reload starting...\n");
uwsgi.status.chain_reloading = 1;
}
else {
uwsgi_log_verbose("chain reload already running...\n");
}
}
void uwsgi_brutally_reload_workers() {
int i;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_log_verbose("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
uwsgi_curse(i, SIGINT);
}
}
}
+24 -2
View File
@@ -35,13 +35,21 @@ int uwsgi_master_check_reload(char **argv) {
// check for chain reload
void uwsgi_master_check_chain() {
if (!uwsgi.status.chain_reloading) return;
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
int i;
int needed_procs = 0;
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0) {
needed_procs++;
}
}
if (uwsgi.status.chain_reloading > needed_procs) {
uwsgi.status.chain_reloading = 0;
uwsgi_log_verbose("chain reloading complete\n");
}
int i;
uwsgi_block_signal(SIGHUP);
for(i=1;i<=uwsgi.numproc;i++) {
// do not curse a worker until the old one is ready
if (uwsgi.workers[i].accepting == 0) break;
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
uwsgi_curse(i, SIGHUP);
break;
@@ -112,6 +120,9 @@ void uwsgi_master_check_idle() {
if (errno != ECHILD)
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
}
else {
uwsgi.workers[i].pid = 0;
}
}
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
@@ -316,3 +327,14 @@ void uwsgi_master_check_crons_deadline() {
}
}
void uwsgi_master_check_mountpoints() {
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.mountpoints_check) {
if (uwsgi_check_mountpoint(usl->value)) {
uwsgi_log_verbose("mountpoint %s failed, triggering detonation...\n", usl->value);
uwsgi_nuclear_blast();
//never here
exit(1);
}
}
}
+10
View File
@@ -18,6 +18,10 @@ int uwsgi_master_manage_events(int interesting_fd) {
}
}
if (uwsgi.master_fifo_fd > -1 && interesting_fd == uwsgi.master_fifo_fd) {
return uwsgi_master_fifo_manage(uwsgi.master_fifo_fd);
}
// stats server ?
if (uwsgi.stats && uwsgi.stats_fd > -1) {
if (interesting_fd == uwsgi.stats_fd) {
@@ -36,6 +40,11 @@ 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();
return 0;
}
if (interesting_fd == uwsgi.emperor_fd) {
uwsgi_master_manage_emperor();
return 0;
@@ -109,6 +118,7 @@ int uwsgi_master_manage_events(int interesting_fd) {
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
if (usl->custom2 > 8) free(tmp);
return 0;
}
usl = usl->next;
+170 -21
View File
@@ -142,7 +142,22 @@ int uwsgi_calc_cheaper(void) {
}
}
if (!ignore_algo) needed_workers = uwsgi.cheaper_algo();
// then check for fifo
if (uwsgi.cheaper_fifo_delta != 0) {
if (!ignore_algo) {
needed_workers = uwsgi.cheaper_fifo_delta;
ignore_algo = 1;
}
uwsgi.cheaper_fifo_delta = 0;
}
// if cheaper limits wants to change worker count, then skip cheaper algo
if (!needed_workers) needed_workers = uwsgi.cheaper_algo(!ignore_algo);
// safe check to verify if cheaper algo obeyed ignore_algo value
if (ignore_algo && needed_workers > 0) {
uwsgi_log("BUG! cheaper algo returned %d but it cannot spawn any worker at this time!\n", needed_workers);
needed_workers = 0;
}
if (needed_workers > 0) {
for (i = 1; i <= uwsgi.numproc; i++) {
@@ -179,6 +194,11 @@ int uwsgi_calc_cheaper(void) {
return 1;
}
// fake algo to allow control with the fifo
int uwsgi_cheaper_algo_manual(int can_spawn) {
return 0;
}
/*
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
@@ -214,7 +234,7 @@ int uwsgi_calc_cheaper(void) {
*/
int uwsgi_cheaper_algo_spare(void) {
int uwsgi_cheaper_algo_spare(int can_spawn) {
int i;
static uint64_t overload_count = 0;
@@ -238,7 +258,7 @@ int uwsgi_cheaper_algo_spare(void) {
healthy:
// are we overloaded ?
if (overload_count > uwsgi.cheaper_overload) {
if (can_spawn && overload_count > uwsgi.cheaper_overload) {
#ifdef UWSGI_DEBUG
uwsgi_log("overloaded !!!\n");
@@ -306,7 +326,7 @@ healthy:
*/
int uwsgi_cheaper_algo_backlog(void) {
int uwsgi_cheaper_algo_backlog(int can_spawn) {
int i;
#ifdef __linux__
@@ -315,7 +335,7 @@ int uwsgi_cheaper_algo_backlog(void) {
int backlog = 0;
#endif
if (backlog > (int) uwsgi.cheaper_overload) {
if (can_spawn && backlog > (int) uwsgi.cheaper_overload) {
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
@@ -353,23 +373,30 @@ void uwsgi_reload(char **argv) {
int i;
int waitpid_status;
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
if (!uwsgi.master_is_reforked) {
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
// call master cleanup hooks
uwsgi_master_cleanup_hooks();
// call atexit user exec
uwsgi_exec_atexit();
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
}
uwsgi_log("binary reloading uWSGI...\n");
}
else {
uwsgi_log("fork()'ing uWSGI...\n");
}
// call master cleanup hooks
uwsgi_master_cleanup_hooks();
// call atexit user exec
uwsgi_exec_atexit();
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
}
uwsgi_log("binary reloading uWSGI...\n");
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
if (chdir(uwsgi.cwd)) {
uwsgi_error("chdir()");
@@ -556,6 +583,7 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
}
}
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
}
@@ -564,6 +592,8 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
int uwsgi_respawn_worker(int wid) {
int respawns = uwsgi.workers[wid].respawn_count;
// the workers is not accepting (obviously)
uwsgi.workers[wid].accepting = 0;
// we count the respawns before errors...
uwsgi.workers[wid].respawn_count++;
// ... same for update time
@@ -843,6 +873,70 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
}
if (uwsgi.has_metrics) {
if (uwsgi_stats_key(us, "metrics"))
goto end;
if (uwsgi_stats_object_open(us))
goto end;
uwsgi_rlock(uwsgi.metrics_lock);
struct uwsgi_metric *um = uwsgi.metrics;
while(um) {
int64_t um_val = *um->value;
if (uwsgi_stats_key(us, um->name)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_object_open(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_keylong(us, "type", (long long) um->type)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_comma(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_keyval_comma(us, "oid", um->oid ? um->oid : "")) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_keyslong(us, "value", (long long) um_val)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_object_close(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
um = um->next;
if (um) {
if (uwsgi_stats_comma(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
}
}
uwsgi_rwunlock(uwsgi.metrics_lock);
if (uwsgi_stats_object_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
}
if (uwsgi_stats_key(us, "sockets"))
goto end;
@@ -898,6 +992,8 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
goto end;
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) uwsgi.workers[i + 1].accepting))
goto end;
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
@@ -1037,6 +1133,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keylong_comma(us, "write_errors", (unsigned long long) uc->write_errors))
goto end;
if (uwsgi_stats_keylong_comma(us, "read_errors", (unsigned long long) uc->read_errors))
goto end;
if (uwsgi_stats_keylong_comma(us, "in_request", (unsigned long long) uc->in_request))
goto end;
@@ -1323,7 +1422,7 @@ end:
return NULL;
}
void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
void uwsgi_register_cheaper_algo(char *name, int (*func) (int)) {
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
@@ -1512,3 +1611,53 @@ void uwsgi_add_reload_fds() {
add_reload_fds(uwsgi.reload_on_fd, "graceful");
add_reload_fds(uwsgi.brutal_reload_on_fd, "brutal");
}
void uwsgi_refork_master() {
pid_t pid = fork();
if (pid < 0) {
uwsgi_error("uwsgi_refork_master()/fork()");
return;
}
if (pid > 0) {
uwsgi_log_verbose("new master copy spawned with pid %d\n", (int) pid);
return;
}
// detach from the old master
setsid();
uwsgi.master_is_reforked = 1;
uwsgi_reload(uwsgi.argv);
// never here
exit(1);
}
void uwsgi_cheaper_increase() {
uwsgi.cheaper_fifo_delta++;
}
void uwsgi_cheaper_decrease() {
uwsgi.cheaper_fifo_delta--;
}
void uwsgi_go_cheap() {
int i;
int waitpid_status;
if (uwsgi.status.is_cheap) return;
uwsgi_log_verbose("going cheap...\n");
uwsgi.status.is_cheap = 1;
for (i = 1; i <= uwsgi.numproc; i++) {
uwsgi.workers[i].cheaped = 1;
if (uwsgi.workers[i].pid == 0)
continue;
uwsgi_log("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
if (errno != ECHILD)
uwsgi_error("uwsgi_go_cheap()/waitpid()");
}
}
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
}
+973 -63
View File
File diff suppressed because it is too large Load Diff
+23 -9
View File
@@ -16,6 +16,7 @@
#ifndef MS_REC
#define MS_REC 16384
#endif
#include <sys/statfs.h>
#endif
struct uwsgi_mount_flag {
@@ -102,27 +103,26 @@ uint64_t uwsgi_mount_flag(char *mflag) {
}
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
#ifdef __FreeBSD__
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
struct iovec iov[6];
#endif
unsigned long mountflags = 0;
if (!flags) goto parsed;
char *mflags = uwsgi_str(flags);
char *p = strtok(mflags, ",");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(mflags, ",", p, ctx) {
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
if (!flag) {
uwsgi_log("unknown mount flag \"%s\"\n", p);
exit(1);
}
mountflags |= flag;
p = strtok(NULL, ",");
}
free(mflags);
parsed:
#ifdef __linux__
return mount(what, where, fs, mountflags, NULL);
#elif defined(__FreeBSD__)
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
iov[0].iov_base = "fstype";
iov[0].iov_len = 7;
iov[1].iov_base = fs;
@@ -147,15 +147,14 @@ int uwsgi_umount(char *where, char *flags) {
unsigned long mountflags = 0;
if (!flags) goto parsed;
char *mflags = uwsgi_str(flags);
char *p = strtok(mflags, ",");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(mflags, ",", p, ctx) {
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
if (!flag) {
uwsgi_log("unknown umount flag \"%s\"\n", p);
exit(1);
}
mountflags |= flag;
p = strtok(NULL, ",");
}
free(mflags);
parsed:
@@ -191,7 +190,7 @@ unmountable:
free(slashed);
}
return umount2(where, mountflags);
#elif defined(__FreeBSD__)
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
return unmount(where, mountflags);
#endif
return -1;
@@ -238,3 +237,18 @@ int uwsgi_umount_hook(char *arg) {
free(tmp_arg);
return 0;
}
int uwsgi_check_mountpoint(char *mountpoint) {
#ifdef __linux__
struct statfs sfs;
int ret = statfs(mountpoint, &sfs);
if (ret) {
uwsgi_error("uwsgi_check_mountpoint()/statfs()");
return -1;
}
return 0;
#else
uwsgi_log("this platform does not support mountpoints check !!!\n");
return -1;
#endif
}
+3 -4
View File
@@ -77,6 +77,7 @@ void uwsgi_mule(int id) {
}
}
uwsgi_hooks_run(uwsgi.hook_as_mule, "as-mule", 1);
uwsgi_mule_run();
}
@@ -453,8 +454,8 @@ void uwsgi_setup_mules_and_farms() {
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
char *p = strtok(mules_list, ",");
while (p != NULL) {
char *p, *ctx = NULL;
uwsgi_foreach_token(mules_list, ",", p, ctx) {
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
if (!um) {
uwsgi_log("invalid mule id: %s\n", p);
@@ -462,8 +463,6 @@ void uwsgi_setup_mules_and_farms() {
}
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
p = strtok(NULL, ",");
}
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
+1 -1
View File
@@ -1,4 +1,4 @@
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
+1 -1
View File
@@ -323,7 +323,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
if (event_queue_add_fd_write(ut->queue, uor->fd2)) return -1;
return 0;
}
#if defined(__linux__) || defined(__sun__)
#if defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
if (len > 0) {
uor->written += len;
+3 -1
View File
@@ -14,7 +14,9 @@ static void uwsgi_plugin_parse_section(char *filename) {
if (equal) {
*equal = 0;
if (!strcmp(p, "requires")) {
uwsgi_load_plugin(-1, equal + 1, NULL);
if (!plugin_already_loaded(equal+1)) {
uwsgi_load_plugin(-1, equal + 1, NULL);
}
}
}
p = strtok_r(NULL, "\n", &ctx);
+112
View File
@@ -0,0 +1,112 @@
#include <uwsgi.h>
#define UWSGI_BUILD_DIR ".uwsgi_plugins_builder"
/*
steps:
mkdir(.uwsgi_plugin_builder)
generate .uwsgi_plugin_builder/uwsgi.h
generate .uwsgi_plugin_builder/uwsgiconfig.py
setenv(UWSGI_PLUGINS_BUILDER_CFLAGS=uwsgi_cflags)
exec PYTHON .uwsgi_plugin_builder/uwsgiconfig.py --extra-plugin <directory> [name]
*/
void uwsgi_build_plugin(char *directory) {
if (!uwsgi_file_exists(UWSGI_BUILD_DIR)) {
if (mkdir(UWSGI_BUILD_DIR, S_IRWXU) < 0) {
uwsgi_error("uwsgi_build_plugin()/mkdir() " UWSGI_BUILD_DIR "/");
_exit(1);
}
}
char *dot_h = uwsgi_get_dot_h();
if (!dot_h) {
uwsgi_log("unable to generate uwsgi.h");
_exit(1);
}
if (strlen(dot_h) == 0) {
free(dot_h);
uwsgi_log("invalid uwsgi.h");
_exit(1);
}
int dot_h_fd = open(UWSGI_BUILD_DIR "/uwsgi.h", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if (dot_h_fd < 0) {
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgi.h");
free(dot_h);
_exit(1);
}
ssize_t dot_h_len = (ssize_t) strlen(dot_h);
if (write(dot_h_fd, dot_h, dot_h_len) != dot_h_len) {
uwsgi_error("uwsgi_build_plugin()/write()");
_exit(1);
}
char *config_py = uwsgi_get_config_py();
if (!config_py) {
uwsgi_log("unable to generate uwsgiconfig.py");
_exit(1);
}
if (strlen(config_py) == 0) {
uwsgi_log("invalid uwsgiconfig.py");
_exit(1);
}
int config_py_fd = open(UWSGI_BUILD_DIR "/uwsgiconfig.py", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if (config_py_fd < 0) {
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgiconfig.py");
_exit(1);
}
ssize_t config_py_len = (ssize_t) strlen(config_py);
if (write(config_py_fd, config_py, config_py_len) != config_py_len) {
uwsgi_error("uwsgi_build_plugin()/write()");
_exit(1);
}
char *cflags = uwsgi_get_cflags();
if (!cflags) {
uwsgi_log("unable to find cflags\n");
_exit(1);
}
if (strlen(cflags) == 0) {
uwsgi_log("invalid cflags\n");
_exit(1);
}
if (setenv("UWSGI_PLUGINS_BUILDER_CFLAGS", cflags, 1)) {
uwsgi_error("uwsgi_build_plugin()/setenv()");
_exit(1);
}
// now run the python script
char *argv[6];
argv[0] = getenv("PYTHON");
if (!argv[0]) argv[0] = "python";
argv[1] = UWSGI_BUILD_DIR "/uwsgiconfig.py";
argv[2] = "--extra-plugin";
char *space = strchr(directory, ' ');
if (space) {
*space = 0;
argv[3] = directory;
argv[4] = space+1;
argv[5] = NULL;
}
else {
argv[3] = directory;
argv[4] = NULL;
}
execvp(argv[0], argv);
// never here...
_exit(1);
}
+1 -1
View File
@@ -57,7 +57,7 @@ void uwsgi_init_queue() {
uwsgi.queue_header->pos = 0;
uwsgi.queue_header->pull_pos = 0;
}
if (!uwsgi.queue) {
if (uwsgi.queue == MAP_FAILED) {
uwsgi_error("mmap()");
exit(1);
}
+68 -11
View File
@@ -24,6 +24,39 @@ int uwsgi_simple_wait_read_hook(int fd, int timeout) {
return ret;
}
int uwsgi_simple_wait_read2_hook(int fd0, int fd1, int timeout, int *fd) {
struct pollfd upoll[2];
timeout = timeout * 1000;
upoll[0].fd = fd0;
upoll[0].events = POLLIN;
upoll[0].revents = 0;
upoll[1].fd = fd1;
upoll[1].events = POLLIN;
upoll[1].revents = 0;
int ret = poll(upoll, 2, timeout);
if (ret > 0) {
if (upoll[0].revents & POLLIN) {
*fd = fd0;
return 1;
}
if (upoll[1].revents & POLLIN) {
*fd = fd1;
return 1;
}
return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_simple_wait_read_hook2()/poll()");
}
return ret;
}
/*
seek()/rewind() language-independent implementations.
*/
@@ -32,14 +65,16 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
if (wsgi_req->post_file) {
if (pos < 0) {
if (fseek(wsgi_req->post_file, pos, SEEK_CUR)) {
uwsgi_error("uwsgi_request_body_seek()/fseek()");
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
wsgi_req->read_errors++;
}
wsgi_req->post_pos = ftell(wsgi_req->post_file);
return;
}
if (fseek(wsgi_req->post_file, pos, SEEK_SET)) {
uwsgi_error("uwsgi_request_body_seek()/fseek()");
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
wsgi_req->read_errors++;
}
wsgi_req->post_pos = ftell(wsgi_req->post_file);
return;
@@ -95,7 +130,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark < remains) {
char *tmp_buf = realloc(wsgi_req->post_readline_buf, wsgi_req->post_readline_size + remains);
if (!tmp_buf) {
uwsgi_error("consume_body_for_readline()/realloc()");
uwsgi_req_error("consume_body_for_readline()/realloc()");
return -1;
}
wsgi_req->post_readline_buf = tmp_buf;
@@ -114,7 +149,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
if (wsgi_req->post_file) {
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
if (ret == 0) {
uwsgi_error("consume_body_for_readline()/fread()");
uwsgi_req_error("consume_body_for_readline()/fread()");
return -1;
}
wsgi_req->post_pos += remains;
@@ -140,6 +175,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
}
if (len == 0) {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
if (len < 0) {
@@ -147,6 +183,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
goto wait;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
wait:
@@ -159,6 +196,7 @@ wait:
return 0;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
// 0 means timeout
@@ -167,6 +205,7 @@ wait:
return -1;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
@@ -204,7 +243,8 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
size_t amount = UMIN(uwsgi.buffer_size, wsgi_req->post_cl);
wsgi_req->post_readline_buf = malloc(amount);
if (!wsgi_req->post_readline_buf) {
uwsgi_error("uwsgi_request_body_readline()/malloc()");
uwsgi_req_error("uwsgi_request_body_readline()/malloc()");
wsgi_req->read_errors++;
*rlen = -1;
return NULL;
}
@@ -217,6 +257,7 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
if (wsgi_req->post_pos >= wsgi_req->post_cl) break;
if (consume_body_for_readline(wsgi_req)) {
wsgi_req->read_errors++;
*rlen = -1;
return NULL;
}
@@ -272,8 +313,9 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (avail > wsgi_req->post_read_buf_size) {
char *tmp_buf = realloc(wsgi_req->post_read_buf, avail);
if (!tmp_buf) {
uwsgi_error("uwsgi_request_body_read()/realloc()");
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
*rlen = -1;
wsgi_req->read_errors++;
return NULL;
}
wsgi_req->post_read_buf = tmp_buf;
@@ -320,7 +362,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (!wsgi_req->post_read_buf) {
wsgi_req->post_read_buf = malloc(remains);
if (!wsgi_req->post_read_buf) {
uwsgi_error("uwsgi_request_body_read()/malloc()");
uwsgi_req_error("uwsgi_request_body_read()/malloc()");
wsgi_req->read_errors++;
*rlen = -1;
return NULL;
}
@@ -331,7 +374,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if ((remains+*rlen) > wsgi_req->post_read_buf_size) {
char *tmp_buf = realloc(wsgi_req->post_read_buf, (remains+*rlen));
if (!tmp_buf) {
uwsgi_error("uwsgi_request_body_read()/realloc()");
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
wsgi_req->read_errors++;
*rlen = -1;
return NULL;
}
@@ -348,7 +392,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (wsgi_req->post_file) {
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
*rlen = -1;
uwsgi_error("uwsgi_request_body_read()/fread()");
uwsgi_req_error("uwsgi_request_body_read()/fread()");
wsgi_req->read_errors++;
return NULL;
}
*rlen += remains;
@@ -378,6 +423,7 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
}
*rlen = -1;
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return NULL;
}
wait:
@@ -389,6 +435,8 @@ wait:
remains -= len;
*rlen += len;
continue;
}else if (len < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) {
goto wait;
}
*rlen = -1;
if (len == 0) {
@@ -396,6 +444,7 @@ wait:
}
else {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
}
return NULL;
}
@@ -407,6 +456,7 @@ wait:
}
*rlen = -1;
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return NULL;
}
@@ -445,6 +495,7 @@ int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
goto wait;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
@@ -460,6 +511,7 @@ wait:
}
if (ret < 0) {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
uwsgi_read_timeout(remains);
@@ -480,7 +532,8 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
wsgi_req->post_file = uwsgi_tmpfile();
if (!wsgi_req->post_file) {
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
uwsgi_req_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
wsgi_req->read_errors++;
return -1;
}
@@ -516,6 +569,7 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
goto wait;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
goto end;
}
@@ -529,11 +583,13 @@ wait:
}
else {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
}
goto end;
}
if (ret < 0) {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
goto end;
}
uwsgi_read_timeout(remains);
@@ -541,7 +597,8 @@ wait:
write:
if (fwrite(wsgi_req->post_buffering_buf, rlen, 1, wsgi_req->post_file) != 1) {
uwsgi_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
uwsgi_req_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
wsgi_req->read_errors++;
goto end;
}
+101 -50
View File
@@ -582,6 +582,88 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
return 0;
}
// simple math router
static int uwsgi_router_simple_math_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uint16_t var_vallen = 0;
char *var_value = uwsgi_get_var(wsgi_req, ur->data, ur->data_len, &var_vallen);
if (!var_value) return UWSGI_ROUTE_BREAK;
int64_t base_value = uwsgi_str_num(var_value, var_vallen);
int64_t value = 1;
if (ur->data2_len) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
if (!ub) return UWSGI_ROUTE_BREAK;
value = uwsgi_str_num(ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
}
char out[sizeof(UMAX64_STR)+1];
int64_t total = 0;
switch(ur->custom) {
// -
case 1:
total = base_value - value;
break;
// *
case 2:
total = base_value * value;
break;
// /
case 3:
if (value == 0) total = 0;
else {
total = base_value/value;
}
break;
default:
total = base_value + value;
break;
}
int ret = uwsgi_long2str2n(total, out, sizeof(UMAX64_STR)+1);
if (ret <= 0) return UWSGI_ROUTE_BREAK;
if (!uwsgi_req_append(wsgi_req, ur->data, ur->data_len, out, ret)) {
return UWSGI_ROUTE_BREAK;
}
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_simple_math_plus(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_simple_math_func;
char *comma = strchr(arg, ',');
if (comma) {
ur->data = arg;
ur->data_len = comma - arg;
ur->data2 = comma+1;
ur->data2_len = strlen(ur->data);
}
else {
ur->data = arg;
ur->data_len = strlen(arg);
}
return 0;
}
static int uwsgi_router_simple_math_minus(struct uwsgi_route *ur, char *arg) {
ur->custom = 1;
return uwsgi_router_simple_math_plus(ur, arg);
}
static int uwsgi_router_simple_math_multiply(struct uwsgi_route *ur, char *arg) {
ur->custom = 2;
return uwsgi_router_simple_math_plus(ur, arg);
}
static int uwsgi_router_simple_math_divide(struct uwsgi_route *ur, char *arg) {
ur->custom = 2;
return uwsgi_router_simple_math_plus(ur, arg);
}
// harakiri router
static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
@@ -640,7 +722,6 @@ static int uwsgi_router_fixcl(struct uwsgi_route *ur, char *arg) {
return 0;
}
// log route
static int uwsgi_router_log_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -881,7 +962,7 @@ static int uwsgi_router_chdir_func(struct wsgi_request *wsgi_req, struct uwsgi_r
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
if (chdir(ub->buf)) {
uwsgi_error("uwsgi_router_chdir_func()/chdir()");
uwsgi_req_error("uwsgi_router_chdir_func()/chdir()");
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
@@ -1199,10 +1280,21 @@ static int uwsgi_router_alarm(struct uwsgi_route *ur, char *arg) {
// send route
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
uwsgi_response_write_body_do(wsgi_req, route->data, route->data_len);
char **subject = (char **) (((char *)(wsgi_req))+route->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+route->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, route, *subject, *subject_len, route->data, route->data_len);
if (!ub) {
return UWSGI_ROUTE_BREAK;
}
if (route->custom) {
uwsgi_response_write_body_do(wsgi_req, "\r\n", 2);
if (uwsgi_buffer_append(ub, "\r\n", 2)) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
}
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_send(struct uwsgi_route *ur, char *arg) {
@@ -1629,48 +1721,6 @@ static char *uwsgi_route_var_hex(struct wsgi_request *wsgi_req, char *key, uint1
return ret;
}
#ifdef UWSGI_MATHEVAL
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
// avoid crash
if (!wsgi_req->var_cnt) return NULL;
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
int i,j = 0;
char *ptr = vars_buf;
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
names[j] = ptr;
ptr += wsgi_req->hvec[i-1].iov_len;
*ptr++=0;
char *num = ptr;
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
ptr += wsgi_req->hvec[i].iov_len;
*ptr++=0;
values[j] = strtod(num, NULL);
j++;
}
char *expr = ptr;
memcpy(ptr, key, keylen); ptr += keylen;
*ptr++=0;
void *e = evaluator_create(expr);
if (!e) goto end;
double n = evaluator_evaluate(e, j, names, values);
evaluator_destroy(e);
ret = uwsgi_num2str((int)n);
*vallen = strlen(ret);
end:
free(vars_buf);
free(names);
free(values);
return ret;
}
#endif
// register embedded routers
void uwsgi_register_embedded_routers() {
uwsgi_register_router("continue", uwsgi_router_continue);
@@ -1703,6 +1753,11 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
uwsgi_register_router("alarm", uwsgi_router_alarm);
uwsgi_register_router("+", uwsgi_router_simple_math_plus);
uwsgi_register_router("-", uwsgi_router_simple_math_minus);
uwsgi_register_router("*", uwsgi_router_simple_math_multiply);
uwsgi_register_router("/", uwsgi_router_simple_math_divide);
uwsgi_register_router("flush", uwsgi_router_flush);
uwsgi_register_router("fixcl", uwsgi_router_fixcl);
@@ -1746,10 +1801,6 @@ void uwsgi_register_embedded_routers() {
urv->need_free = 1;
urv = uwsgi_register_route_var("httptime", uwsgi_route_var_httptime);
urv->need_free = 1;
#ifdef UWSGI_MATHEVAL
urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
urv->need_free = 1;
#endif
urv = uwsgi_register_route_var("base64", uwsgi_route_var_base64);
urv->need_free = 1;
+36 -8
View File
@@ -59,11 +59,11 @@ already:
return ret;
}
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
uint64_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char **output) {
struct uwsgi_rpc *urpc = NULL;
uint64_t i;
uint16_t ret = 0;
uint64_t ret = 0;
int pos = (uwsgi.mywid * uwsgi.rpc_max);
@@ -85,8 +85,15 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
return ret;
}
static void rpc_context_hook(char *key, uint16_t kl, char *value, uint16_t vl, void *data) {
size_t *r = (size_t *) data;
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
if (!uwsgi_strncmp(key, kl, "CONTENT_LENGTH", 14)) {
*r = uwsgi_str_num(value, vl);
}
}
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint64_t * len) {
uint8_t i;
uint16_t ulen;
@@ -97,9 +104,10 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
if (node == NULL || !strcmp(node, "")) {
// allocate the whole buffer
buffer = uwsgi_malloc(UMAX16);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
return buffer;
*len = uwsgi_rpc(func, argc, argv, argvs, &buffer);
if (*buffer)
return buffer;
return NULL;
}
@@ -147,17 +155,37 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
bufptr += ulen;
}
// ok the reuqest is ready, let's send it in non blocking way
// ok the request is ready, let's send it in non blocking way
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
goto error;
}
// ok time to wait for the response in non blocking way
size_t rlen = buffer_size+4;
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uint8_t modifier2 = 0;
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL, &modifier2)) {
goto error;
}
// 64bit response ?
if (modifier2 == 5) {
size_t content_len = 0;
if (uwsgi_hooked_parse(buffer, rlen, rpc_context_hook, &content_len )) goto error;
if (content_len > rlen) {
char *tmp_buf = realloc(buffer, content_len);
if (!tmp_buf) goto error;
buffer = tmp_buf;
}
rlen = content_len;
// read the raw value from the socket
if (uwsgi_read_whole_true_nb(fd, buffer, rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
goto error;
}
}
close(fd);
*len = rlen;
if (*len == 0) {
+1 -1
View File
@@ -20,7 +20,7 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
return -1;
#elif defined(__linux__) || defined(__sun__)
#elif defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
off_t off = pos;
return sendfile(sockfd, filefd, &off, len);
#endif
+366
View File
@@ -0,0 +1,366 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
This is an high-performance memory area shared by all workers/cores/threads
Contrary to the caching subsystem it is 1-copy (caching for non-c apps is 2-copy)
Languages not allowing that kind of access should emulate it calling uwsgi_malloc and then copying it back to
the language object.
The memory areas could be monitored for changes (read: cores can be suspended while waiting for values)
You can configure multiple areas specifying multiple --sharedarea options
This is a very low-level api, try to use it to build higher-level primitives or rely on the caching subsystem
*/
struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int id, uint64_t pos) {
if (id > uwsgi.sharedareas_cnt-1) return NULL;
struct uwsgi_sharedarea *sa = uwsgi.sharedareas[id];
if (pos > sa->max_pos) return NULL;
return sa;
}
int uwsgi_sharedarea_update(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
sa->updates++;
return 0;
}
int uwsgi_sharedarea_rlock(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
uwsgi_rlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_wlock(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
uwsgi_wlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_unlock(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
uwsgi_rwunlock(sa->lock);
return 0;
}
int64_t uwsgi_sharedarea_read(int id, uint64_t pos, char *blob, uint64_t len) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + len > sa->max_pos + 1) return -1;
if (len == 0) len = (sa->max_pos + 1) - pos;
if (sa->honour_used && sa->used-pos < len) len = sa->used-pos ;
uwsgi_rlock(sa->lock);
memcpy(blob, sa->area + pos, len);
sa->hits++;
uwsgi_rwunlock(sa->lock);
return len;
}
int uwsgi_sharedarea_write(int id, uint64_t pos, char *blob, uint64_t len) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + len > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
memcpy(sa->area + pos, blob, len);
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_read64(int id, uint64_t pos, int64_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 8);
return rlen == 8 ? 0 : -1;
}
int uwsgi_sharedarea_write64(int id, uint64_t pos, int64_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 8);
}
int uwsgi_sharedarea_read8(int id, uint64_t pos, int8_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 1);
return rlen == 1 ? 0 : -1;
}
int uwsgi_sharedarea_write8(int id, uint64_t pos, int8_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 1);
}
int uwsgi_sharedarea_read16(int id, uint64_t pos, int16_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 2);
return rlen == 2 ? 0 : -1;
}
int uwsgi_sharedarea_write16(int id, uint64_t pos, int16_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 2);
}
int uwsgi_sharedarea_read32(int id, uint64_t pos, int32_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 4);
return rlen == 4 ? 0 : -1;
}
int uwsgi_sharedarea_write32(int id, uint64_t pos, int32_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 4);
}
int uwsgi_sharedarea_inc8(int id, uint64_t pos, int8_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 1 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int8_t *n_ptr = (int8_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_inc16(int id, uint64_t pos, int16_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 2 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int16_t *n_ptr = (int16_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_inc32(int id, uint64_t pos, int32_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int32_t *n_ptr = (int32_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_inc64(int id, uint64_t pos, int64_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int64_t *n_ptr = (int64_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec8(int id, uint64_t pos, int8_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 1 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int8_t *n_ptr = (int8_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec16(int id, uint64_t pos, int16_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 2 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int16_t *n_ptr = (int16_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec32(int id, uint64_t pos, int32_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int32_t *n_ptr = (int32_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec64(int id, uint64_t pos, int64_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int64_t *n_ptr = (int64_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
/*
returns:
0 -> on updates
-1 -> on error
-2 -> on timeout
*/
int uwsgi_sharedarea_wait(int id, int freq, int timeout) {
int waiting = 0;
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
if (!freq) freq = 100;
uwsgi_rlock(sa->lock);
uint64_t updates = sa->updates;
uwsgi_rwunlock(sa->lock);
while(timeout == 0 || (timeout > 0 && (waiting/1000) >= timeout)) {
uwsgi.wait_milliseconds_hook(freq);
waiting += freq;
// lock sa
uwsgi_rlock(sa->lock);
if (sa->updates != updates) {
uwsgi_rwunlock(sa->lock);
return 0;
}
// unlock sa
uwsgi_rwunlock(sa->lock);
}
return -2;
}
int uwsgi_sharedarea_new_id() {
int id = uwsgi.sharedareas_cnt;
uwsgi.sharedareas_cnt++;
if (!uwsgi.sharedareas) {
uwsgi.sharedareas = uwsgi_malloc(sizeof(struct uwsgi_sharedarea *));
}
else {
struct uwsgi_sharedarea **usa = realloc(uwsgi.sharedareas, ((sizeof(struct uwsgi_sharedarea *)) * uwsgi.sharedareas_cnt));
if (!usa) {
uwsgi_error("uwsgi_sharedarea_init()/realloc()");
exit(1);
}
uwsgi.sharedareas = usa;
}
return id;
}
static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) {
uwsgi_log("sharedarea %d created at %p (%d pages, area at %p)\n", sa->id, sa, sa->pages, sa->area);
return sa;
}
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]->id = id;
uwsgi.sharedareas[id]->fd = -1;
uwsgi.sharedareas[id]->pages = pages;
uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
free(id_str);
return announce_sa(uwsgi.sharedareas[id]);
}
struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) {
int id = uwsgi_sharedarea_new_id();
uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea));
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]->max_pos = len-1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
free(id_str);
return announce_sa(uwsgi.sharedareas[id]);
}
struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
char *s_pages = NULL;
char *s_file = NULL;
char *s_fd = NULL;
char *s_ptr = NULL;
char *s_size = NULL;
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"pages", &s_pages,
"file", &s_file,
"fd", &s_fd,
"ptr", &s_ptr,
"size", &s_size,
NULL)) {
uwsgi_log("invalid sharedarea keyval syntax\n");
exit(1);
}
uint64_t len = 0;
int pages = 0;
if (s_size) {
len = uwsgi_n64(s_size);
pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) pages++;
}
if (s_pages) {
pages = atoi(s_pages);
}
char *area = NULL;
struct uwsgi_sharedarea *sa = NULL;
if (s_file) {
}
else if (s_fd) {
}
else if (s_ptr) {
}
if (pages) {
if (!area) {
sa = uwsgi_sharedarea_init(pages);
}
else {
uwsgi_sharedarea_init_ptr(area, len);
}
}
if (s_pages) free(s_pages);
if (s_file) free(s_file);
if (s_fd) free(s_fd);
if (s_ptr) free(s_ptr);
if (s_size) free(s_size);
return sa;
}
void uwsgi_sharedareas_init() {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.sharedareas_list) {
char *is_keyval = strchr(usl->value, '=');
if (!is_keyval) {
uwsgi_sharedarea_init(atoi(usl->value));
}
else {
uwsgi_sharedarea_init_keyval(usl->value);
}
}
}
+2
View File
@@ -301,8 +301,10 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
else {
uwsgi_error("uwsgi_signal_send()");
}
uwsgi.shared->unrouted_signals++;
return -1;
}
uwsgi.shared->routed_signals++;
return 0;
}
+55 -14
View File
@@ -23,6 +23,7 @@ static uint64_t get_uwsgi_custom_snmp_value(uint64_t, uint8_t *);
static uint8_t snmp_int_to_snmp(uint64_t, uint8_t, uint8_t *);
static ssize_t build_snmp_response(uint8_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
static ssize_t build_snmp_metric_response(int64_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_addr) {
@@ -71,7 +72,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
uwsgi_debug("SNMP version: %d\n", version);
#endif
// check for community string (this must be set from the python vm using uwsgi.snmp_community or with --snmp-community arg)
// check for community string (this must be set from the api using uwsgi.snmp_community or with --snmp-community arg)
if (*ptr != SNMP_STRING)
return;
ptr++;
@@ -196,7 +197,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
ptr++;
oidlen = *ptr;
if (oidlen != 11)
if (oidlen < 11)
return;
ptr++;
@@ -208,21 +209,33 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
oid_part[0] = *ptr;
if (oid_part[0] != 1 && oid_part[0] != 2)
return;
ptr++;
// old-style SNMP metrics
if (oid_part[0] == 1 || oid_part[0] == 2) {
ptr++;
oid_part[1] = *ptr;
if (oid_part[1] < 1 || oid_part[1] > 100)
return;
ptr++;
oid_part[1] = *ptr;
if (oid_part[1] < 1 || oid_part[1] > 100)
return;
ptr++;
// check for null
if (memcmp((char *) ptr, "\x05\x00", 2))
return;
ptr += 2;
// check for null
if (memcmp((char *) ptr, "\x05\x00", 2))
return;
ptr += 2;
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
}
// metrics subsystem
else {
size_t metric_asn_len = oidlen - 9;
char *metric_asn = (char *) ptr;
struct uwsgi_metric *um = uwsgi_metric_find_by_asn(metric_asn, metric_asn_len);
if (!um) return;
uwsgi_rlock(uwsgi.metrics_lock);
int64_t value = *um->value;
uwsgi_rwunlock(uwsgi.metrics_lock);
size = build_snmp_metric_response(value, um->type, buffer, size, seq1, seq2, seq3);
}
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
if (size > 0) {
if (sendto(fd, buffer, size, 0, (struct sockaddr *) client_addr, sizeof(struct sockaddr_in)) < 0) {
@@ -292,6 +305,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
uint8_t tlen;
int i, j;
uint8_t *ptr = (uint8_t *) & snmp_val;
int32_t val32 = (int32_t) snmp_val;
// check for counter, counter64 or gauge
@@ -303,6 +317,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
}
else {
tlen = 4;
ptr = (uint8_t *) &val32;
}
buffer[0] = tlen;
@@ -352,6 +367,32 @@ static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer,
}
static ssize_t build_snmp_metric_response(int64_t value, uint8_t type, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
uint8_t oid_sz;
if (type == UWSGI_METRIC_GAUGE) {
buffer[size - 2] = SNMP_GAUGE;
oid_sz = snmp_int_to_snmp(value, SNMP_GAUGE, buffer + (size - 1));
}
else {
buffer[size - 2] = SNMP_COUNTER64;
oid_sz = snmp_int_to_snmp(value, SNMP_COUNTER64, buffer + (size - 1));
}
if (oid_sz < 1)
return -1;
oid_sz--;
buffer[1] += oid_sz;
*seq1 += oid_sz;
*seq2 += oid_sz;
*seq3 += oid_sz;
return size + oid_sz;
}
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
uwsgi.snmp = 1;
if (value) {
+76 -106
View File
@@ -6,6 +6,22 @@ static int connect_to_unix(char *, int, int);
static int connect_to_tcp(char *, int, int, int);
static int connect_to_udp(char *, int);
void uwsgi_socket_setup_protocol(struct uwsgi_socket *uwsgi_sock, char *protocol) {
if (!protocol) protocol = "uwsgi";
struct uwsgi_protocol *up = uwsgi.protocols;
while(up) {
if (!strcmp(protocol, up->name)) {
up->func(uwsgi_sock);
return;
}
up = up->next;
}
uwsgi_log("unable to find protocol %s\n", protocol);
exit(1);
}
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
size_t sock1_len = strlen(sock1);
size_t sock2_len = strlen(sock2);
@@ -187,6 +203,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
return -1;
}
#ifdef __linux__
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
uwsgi_nuclear_blast();
return -1;
}
#endif
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
@@ -1358,7 +1382,7 @@ void uwsgi_add_sockets_to_queue(int queue, int async_id) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->fd_threads && async_id > -1) {
if (uwsgi_sock->fd_threads && async_id > -1 && uwsgi_sock->fd_threads[async_id] > -1) {
event_queue_add_fd_read(queue, uwsgi_sock->fd_threads[async_id]);
}
else if (uwsgi_sock->fd > -1) {
@@ -1645,8 +1669,8 @@ void uwsgi_map_sockets() {
}
if ((int) uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
enabled = 0;
char *p = strtok(colon + 1, ",");
while (p != NULL) {
char *p, *ctx = NULL;
uwsgi_foreach_token(colon + 1, ",", p, ctx) {
int w = atoi(p);
if (w < 1 || w > uwsgi.numproc) {
uwsgi_log("invalid worker num: %d\n", w);
@@ -1657,7 +1681,6 @@ void uwsgi_map_sockets() {
uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
break;
}
p = strtok(NULL, ",");
}
}
@@ -1666,18 +1689,7 @@ void uwsgi_map_sockets() {
if (!enabled) {
close(uwsgi_sock->fd);
int fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != uwsgi_sock->fd) {
if (dup2(fd, uwsgi_sock->fd) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
uwsgi_remap_fd(uwsgi_sock->fd, "/dev/null");
uwsgi_sock->disabled = 1;
}
@@ -1707,6 +1719,10 @@ void uwsgi_bind_sockets() {
while (uwsgi_sock) {
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
char *tcp_port = strrchr(uwsgi_sock->name, ':');
int current_defer_accept = uwsgi.no_defer_accept;
if (uwsgi_sock->no_defer) {
uwsgi.no_defer_accept = 1;
}
if (tcp_port == NULL) {
uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
uwsgi_sock->family = AF_UNIX;
@@ -1740,6 +1756,7 @@ void uwsgi_bind_sockets() {
uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
exit(1);
}
uwsgi.no_defer_accept = current_defer_accept;
}
uwsgi_sock->bound = 1;
uwsgi_sock = uwsgi_sock->next;
@@ -1852,96 +1869,8 @@ void uwsgi_set_sockets_protocols() {
setup_proto:
if (!requested_protocol) {
requested_protocol = uwsgi.protocol;
}
if (requested_protocol && !strcmp("http", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_http_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && (!strcmp("fastcgi-nph", requested_protocol) || !strcmp("fcgi-nph", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && (!strcmp("scgi", requested_protocol) || !strcmp("scgi", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
else if (requested_protocol && (!strcmp("scgi-nph", requested_protocol) || !strcmp("scgi-nph", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
#ifdef UWSGI_ZEROMQ
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
uwsgi.zeromq = 1;
}
#endif
else {
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
if (!requested_protocol) requested_protocol = uwsgi.protocol;
uwsgi_socket_setup_protocol(uwsgi_sock, requested_protocol);
nextsock:
uwsgi_sock = uwsgi_sock->next;
}
@@ -1976,3 +1905,44 @@ int uwsgi_accept(int server_fd) {
}
struct uwsgi_protocol *uwsgi_register_protocol(char *name, void (*func)(struct uwsgi_socket *)) {
struct uwsgi_protocol *old_up = NULL, *up = uwsgi.protocols;
while(up) {
if (!strcmp(name, up->name)) {
goto found;
}
old_up = up;
up = up->next;
}
up = uwsgi_calloc(sizeof(struct uwsgi_protocol));
up->name = name;
if (old_up) {
old_up->next = up;
}
else {
uwsgi.protocols = up;
}
found:
up->func = func;
return up;
}
void uwsgi_protocols_register() {
uwsgi_register_protocol("uwsgi", uwsgi_proto_uwsgi_setup);
uwsgi_register_protocol("puwsgi", uwsgi_proto_puwsgi_setup);
uwsgi_register_protocol("http", uwsgi_proto_http_setup);
#ifdef UWSGI_SSL
uwsgi_register_protocol("suwsgi", uwsgi_proto_suwsgi_setup);
uwsgi_register_protocol("https", uwsgi_proto_https_setup);
#endif
uwsgi_register_protocol("fastcgi", uwsgi_proto_fastcgi_setup);
uwsgi_register_protocol("fastcgi-nph", uwsgi_proto_fastcgi_nph_setup);
uwsgi_register_protocol("scgi", uwsgi_proto_scgi_setup);
uwsgi_register_protocol("scgi-nph", uwsgi_proto_scgi_nph_setup);
uwsgi_register_protocol("raw", uwsgi_proto_raw_setup);
}
+18 -45
View File
@@ -440,6 +440,11 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
void *events = event_queue_alloc(1);
for (;;) {
int nevents = event_queue_wait_multi(ut->queue, 1, events, 1);
if (nevents < 0) {
if (errno == EINTR) continue;
uwsgi_log_verbose("ending the stats pusher thread...\n");
return;
}
if (nevents > 0) {
int interesting_fd = event_queue_interesting_fd(events, 0);
char buf[4096];
@@ -457,7 +462,8 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
struct uwsgi_stats *us = NULL;
while (uspi) {
int delta = uspi->freq ? uspi->freq : uwsgi.stats_pusher_default_freq;
if ((uspi->last_run + delta) <= now) {
if (((uspi->last_run + delta) <= now) || (uspi->needs_retry && (uspi->next_retry <= now))) {
if (uspi->needs_retry) uspi->retries++;
if (uspi->raw) {
uspi->pusher->func(uspi, now, NULL, 0);
}
@@ -470,6 +476,17 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
uspi->pusher->func(uspi, now, us->base, us->pos);
}
uspi->last_run = now;
if (uspi->needs_retry && uspi->max_retries > 0 && uspi->retries < uspi->max_retries) {
uwsgi_log("[uwsgi-stats-pusher] %s failed (%d), retry in %ds\n", uspi->pusher->name, uspi->retries, uspi->retry_delay);
uspi->next_retry = now + uspi->retry_delay;
} else if (uspi->needs_retry && uspi->retries >= uspi->max_retries) {
uwsgi_log("[uwsgi-stats-pusher] %s failed and maximum number of retries was reached (%d)\n", uspi->pusher->name, uspi->retries);
uspi->needs_retry = 0;
uspi->retries = 0;
} else if (uspi->retries) {
uwsgi_log("[uwsgi-stats-pusher] retry succeeded for %s\n", uspi->pusher->name);
uspi->retries = 0;
}
}
next:
uspi = uspi->next;
@@ -531,50 +548,6 @@ struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func)
return pusher;
}
struct uwsgi_stats_pusher_file_conf {
char *path;
char *freq;
char *separator;
};
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
struct uwsgi_stats_pusher_file_conf *uspic = (struct uwsgi_stats_pusher_file_conf *) uspi->data;
if (!uspi->configured) {
uspic = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_file_conf));
if (uspi->arg) {
if (uwsgi_kvlist_parse(uspi->arg, strlen(uspi->arg), ',', '=', "path", &uspic->path, "separator", &uspic->separator, "freq", &uspic->freq, NULL)) {
free(uspi);
return;
}
}
if (!uspic->path)
uspic->path = "uwsgi.stats";
if (!uspic->separator)
uspic->separator = "\n\n";
if (uspic->freq)
uspi->freq = atoi(uspic->freq);
uspi->configured = 1;
uspi->data = uspic;
}
int fd = open(uspic->path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uspic->path);
return;
}
ssize_t rlen = write(fd, json, json_len);
if (rlen != (ssize_t) json_len) {
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
}
rlen = write(fd, uspic->separator, strlen(uspic->separator));
if (rlen != (ssize_t) strlen(uspic->separator)) {
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
}
close(fd);
}
static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
struct uwsgi_stats *us = (struct uwsgi_stats *) data;
if (us->dirty) return;
+104
View File
@@ -379,3 +379,107 @@ char *uwsgi_cheap_string(char *buf, int len) {
return buf - 1;
}
/*
status 0: append mode
status 1: single quote found
status 2: double quote found
status 3: backslash found (on 0)
status 4: backslash found (on 1)
status 5: backslash found (on 2)
*/
char ** uwsgi_split_quoted(char *what, size_t what_len, char *sep, size_t *rlen) {
size_t i;
int status = 0;
char *base = uwsgi_concat2n(what, what_len, "", 0);
char *item = NULL;
char *ptr = NULL;
*rlen = 0;
char **ret = (char **) uwsgi_malloc(sizeof(char *) * (what_len+1));
for(i=0;i<what_len;i++) {
if (!item) {
item = uwsgi_malloc((what_len - i)+1);
ptr = item;
}
if (status == 0) {
if (base[i] == '\\') {
status = 3;
}
else if (base[i] == '"') {
status = 2;
}
else if (base[i] == '\'') {
status = 1;
}
else if (strchr(sep, base[i])) {
*ptr++= 0;
ret[(*rlen)] = item; (*rlen)++;
item = NULL;
}
else {
*ptr++= base[i];
}
continue;
}
// backslash
if (status == 3) {
*ptr++= base[i];
status = 0;
continue;
}
// single quote
if (status == 1) {
if (base[i] == '\\') {
status = 4;
}
else if (base[i] == '\'') {
status = 0;
}
else {
*ptr++= base[i];
}
continue;
}
// double quote
if (status == 2) {
if (base[i] == '\\') {
status = 5;
}
else if (base[i] == '"') {
status = 0;
}
else {
*ptr++= base[i];
}
continue;
}
// backslash single quote
if (status == 4) {
*ptr++= base[i];
status = 1;
continue;
}
// backslash double quote
if (status == 5) {
*ptr++= base[i];
status = 2;
continue;
}
}
if (item) {
*ptr++= 0;
ret[(*rlen)] = item; (*rlen)++;
}
free(base);
return ret;
}
+2
View File
@@ -812,6 +812,8 @@ end:
}
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
if (!uwsgi.subscriptions_blocked) return;
// -- subscribe
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while (subscriptions) {
+1119 -938
View File
File diff suppressed because it is too large Load Diff
+497 -323
View File
File diff suppressed because it is too large Load Diff
+64 -12
View File
@@ -10,9 +10,17 @@
extern struct uwsgi_server uwsgi;
static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(10 + len);
if (uwsgi_buffer_u8(ub, 0x81)) goto error;
static struct uwsgi_buffer *uwsgi_websocket_message(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) {
struct uwsgi_buffer *ub = wsgi_req->websocket_send_buf;
if (!ub) {
wsgi_req->websocket_send_buf = uwsgi_buffer_new(10 + len);
ub = wsgi_req->websocket_send_buf;
}
else {
// reset the buffer
ub->pos = 0;
}
if (uwsgi_buffer_u8(ub, opcode)) goto error;
if (len < 126) {
if (uwsgi_buffer_u8(ub, len)) goto error;
}
@@ -29,7 +37,6 @@ static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len) {
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
@@ -59,34 +66,79 @@ static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) {
}
return 0;
}
// pong received, send anther ping
// pong received, send another ping
if (now - wsgi_req->websocket_last_ping >= uwsgi.websockets_ping_freq) {
return uwsgi_websockets_ping(wsgi_req);
}
return 0;
}
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len) {
struct uwsgi_buffer *ub = uwsgi_websocket_message(msg, len);
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) {
struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, msg, len, opcode);
if (!ub) return -1;
ssize_t ret = uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
return ret;
return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
}
static int uwsgi_websocket_send_from_sharedarea_do(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len, uint8_t opcode) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (!len) {
len = sa->honour_used ? sa->used-pos : ((sa->max_pos+1)-pos);
}
uwsgi_rlock(sa->lock);
sa->hits++;
struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, sa->area, len, opcode);
uwsgi_rwunlock(sa->lock);
if (!ub) return -1;
return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
}
int uwsgi_websocket_send(struct wsgi_request *wsgi_req, char *msg, size_t len) {
if (wsgi_req->websocket_closed) {
return -1;
}
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len);
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len, 0x81);
if (ret < 0) {
wsgi_req->websocket_closed = 1;
}
return ret;
}
int uwsgi_websocket_send_from_sharedarea(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len) {
if (wsgi_req->websocket_closed) {
return -1;
}
ssize_t ret = uwsgi_websocket_send_from_sharedarea_do(wsgi_req, id, pos, len, 0x81);
if (ret < 0) {
wsgi_req->websocket_closed = 1;
}
return ret;
}
int uwsgi_websocket_send_binary(struct wsgi_request *wsgi_req, char *msg, size_t len) {
if (wsgi_req->websocket_closed) {
return -1;
}
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len, 0x82);
if (ret < 0) {
wsgi_req->websocket_closed = 1;
}
return ret;
}
int uwsgi_websocket_send_binary_from_sharedarea(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len) {
if (wsgi_req->websocket_closed) {
return -1;
}
ssize_t ret = uwsgi_websocket_send_from_sharedarea_do(wsgi_req, id, pos, len, 0x82);
if (ret < 0) {
wsgi_req->websocket_closed = 1;
}
return ret;
}
static void uwsgi_websocket_parse_header(struct wsgi_request *wsgi_req) {
uint8_t byte1 = wsgi_req->websocket_buf->buf[0];
uint8_t byte2 = wsgi_req->websocket_buf->buf[1];
+244 -7
View File
@@ -179,7 +179,7 @@ int uwsgi_response_add_header_force(struct wsgi_request *wsgi_req, char *key, ui
return uwsgi_response_add_header_do(wsgi_req, key, key_len, value, value_len);
}
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
static int uwsgi_response_write_headers_do0(struct wsgi_request *wsgi_req) {
if (wsgi_req->headers_sent || !wsgi_req->headers || wsgi_req->response_size || wsgi_req->write_errors) {
return UWSGI_OK;
}
@@ -209,11 +209,20 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
if (wsgi_req->socket->proto_fix_headers(wsgi_req)) { wsgi_req->write_errors++ ; return -1;}
return UWSGI_AGAIN;
}
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
int ret = uwsgi_response_write_headers_do0(wsgi_req);
if (ret != UWSGI_AGAIN) return ret;
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_write_headers(wsgi_req, wsgi_req->headers->buf, wsgi_req->headers->pos);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_response_write_headers_do()");
uwsgi_req_error("uwsgi_response_write_headers_do()");
}
wsgi_req->write_errors++;
return -1;
@@ -221,6 +230,7 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
@@ -238,6 +248,100 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
/*
private function for highly optimized writes (1 single syscall for headers and body)
*/
static int uwsgi_response_writev_headers_and_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
struct iovec iov[2];
int ret = uwsgi_response_write_headers_do0(wsgi_req);
if (ret != UWSGI_AGAIN) return ret;
iov[0].iov_base = wsgi_req->headers->buf;
iov[0].iov_len = wsgi_req->headers->pos;
iov[1].iov_base = buf;
iov[1].iov_len = len;
size_t iov_len = 2;
for(;;) {
errno = 0;
// no need to use writev if a single iovec remains
if (iov_len == 1) {
buf = iov[0].iov_base;
len = iov[0].iov_len;
// update counters
wsgi_req->headers_size += wsgi_req->headers->pos;
wsgi_req->headers_sent = 1;
wsgi_req->response_size += wsgi_req->write_pos - wsgi_req->headers_size;
wsgi_req->write_pos = 0;
goto fallback;
}
int ret = wsgi_req->socket->proto_writev(wsgi_req, iov, &iov_len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_req_error("uwsgi_response_writev_headers_and_body_do()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
uwsgi_log("uwsgi_response_writev_headers_and_body_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
wsgi_req->headers_size += wsgi_req->headers->pos;
wsgi_req->response_size += len;
wsgi_req->headers_sent = 1;
// reset for the next write
wsgi_req->write_pos = 0;
return UWSGI_OK;
fallback:
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
// here we use the parent name
uwsgi_req_error("uwsgi_response_write_body_do()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
// here we use the parent name
uwsgi_log("uwsgi_response_write_body_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
wsgi_req->response_size += wsgi_req->write_pos;
// reset for the next write
wsgi_req->write_pos = 0;
return UWSGI_OK;
}
// this is the function called by all request plugins to send chunks to the client
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
@@ -278,6 +382,9 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
write:
// send headers if not already sent
if (!wsgi_req->headers_sent) {
if (wsgi_req->socket->proto_writev && len > 0 && wsgi_req->headers) {
return uwsgi_response_writev_headers_and_body_do(wsgi_req, buf, len);
}
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendbody;
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
@@ -290,10 +397,11 @@ sendbody:
if (len == 0) return UWSGI_OK;
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_response_write_body_do()");
uwsgi_req_error("uwsgi_response_write_body_do()");
}
wsgi_req->write_errors++;
return -1;
@@ -301,6 +409,7 @@ sendbody:
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
@@ -317,6 +426,130 @@ sendbody:
return UWSGI_OK;
}
int uwsgi_response_writev_body_do(struct wsgi_request *wsgi_req, struct iovec *iov, size_t len) {
if (wsgi_req->write_errors) return -1;
if (wsgi_req->ignore_body) return UWSGI_OK;
#ifdef UWSGI_ROUTING
// special case here, we could need to set transformations before
if (!wsgi_req->headers_sent) {
// apply response routes
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
// from now on ignore write body requests...
wsgi_req->ignore_body = 1;
return -1;
}
wsgi_req->is_response_routing = 0;
}
#endif
size_t i;
int buffering = 0;
// transformations apply to every vector
for(i=0;i<len;i++) {
// if the transformation chain returns 1, we are in buffering mode
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
int t_ret = uwsgi_apply_transformations(wsgi_req, iov[i].iov_base, iov[i].iov_len);
if (t_ret == 0) {
iov[i].iov_base = wsgi_req->transformed_chunk;
iov[i].iov_len = wsgi_req->transformed_chunk_len;
// reset transformation
wsgi_req->transformed_chunk = NULL;
wsgi_req->transformed_chunk_len = 0;
goto write;
}
if (t_ret == 1) {
buffering = 1;
continue;
}
wsgi_req->write_errors++;
return -1;
}
}
if (buffering) return UWSGI_OK;
write:
// send headers if not already sent
if (!wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendbody;
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
wsgi_req->write_errors++;
return -1;
}
sendbody:
if (len == 0) return UWSGI_OK;
// unfortunately vector based I/O cannot be accomplished on all protocols
if (!wsgi_req->socket->proto_writev) goto fallback;
// we use a copy to avoid mess
size_t iov_len = len;
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_writev(wsgi_req, iov, &iov_len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_req_error("uwsgi_response_writev_body_do()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
uwsgi_log("uwsgi_response_writev_body_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
goto done;
fallback:
for(i=0;i<len;i++) {
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_write(wsgi_req, iov[i].iov_base, iov[i].iov_len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_req_error("uwsgi_response_writev_body_do()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
uwsgi_log("uwsgi_response_writev_body_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
}
done:
wsgi_req->response_size += wsgi_req->write_pos;
// reset for the next write
wsgi_req->write_pos = 0;
return UWSGI_OK;
}
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
return uwsgi_response_sendfile_do_can_close(wsgi_req, fd, pos, len, 1);
}
@@ -349,7 +582,7 @@ sendfile:
if (len == 0) {
struct stat st;
if (fstat(fd, &st)) {
uwsgi_error("uwsgi_response_sendfile_do()/fstat()");
uwsgi_req_error("uwsgi_response_sendfile_do()/fstat()");
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
@@ -367,7 +600,7 @@ sendfile:
if (!can_close) {
int tmp_fd = dup(fd);
if (tmp_fd < 0) {
uwsgi_error("uwsgi_response_sendfile_do()/dup()");
uwsgi_req_error("uwsgi_response_sendfile_do()/dup()");
wsgi_req->write_errors++;
return -1;
}
@@ -388,10 +621,11 @@ sendfile:
wsgi_req->via = UWSGI_VIA_SENDFILE;
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_response_sendfile_do()");
uwsgi_req_error("uwsgi_response_sendfile_do()");
}
wsgi_req->write_errors++;
if (can_close) close(fd);
@@ -400,6 +634,7 @@ sendfile:
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) {
wsgi_req->write_errors++;
@@ -454,10 +689,11 @@ int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
wsgi_req->write_pos = 0;
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_simple_write()");
uwsgi_req_error("uwsgi_simple_write()");
}
wsgi_req->write_errors++;
return -1;
@@ -465,6 +701,7 @@ int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
+3
View File
@@ -151,6 +151,8 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
}
/* We can safely free resources */
if (colon) colon[0] = ':';
xmlFreeDoc(doc);
xmlCleanupParser();
@@ -267,6 +269,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
} while (!done);
if (colon) colon[0] = ':';
// we can safely free, as we have a copy of datas
XML_ParserFree(parser);
+1
View File
@@ -280,6 +280,7 @@ next:
}
#endif
if (colon) colon[0] = ':';
}
+3 -2
View File
@@ -123,12 +123,13 @@ int uwsgi_gzip_fix(z_stream *z, uint32_t crc32, struct uwsgi_buffer *ub, size_t
if (!gzipped0) goto end;
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
free(gzipped0);
if (uwsgi_buffer_u32le(ub, crc32)) goto end;
if (uwsgi_buffer_u32le(ub, len)) goto end;
if (uwsgi_buffer_u32le(ub, crc32)) goto end2;
if (uwsgi_buffer_u32le(ub, len)) goto end2;
deflateEnd(z);
return 0;
end:
if (gzipped0) free(gzipped0);
end2:
deflateEnd(z);
return -1;
}
+5 -6
View File
@@ -1,5 +1,4 @@
import uwsgi
import os
def application(env, start_response):
@@ -15,12 +14,12 @@ def application(env, start_response):
]
)
yield "--%s\n" % boundary
yield "--%s\r\n" % boundary
while 1:
yield "Content-Type: image/jpeg\r\n\r\n"
uwsgi.sendfile('screenshot.jpg')
yield "--%s\n" % boundary
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')
#os.system('screencapture -m -T 1 screenshot.jpg')
View File
+11 -1
View File
@@ -52,6 +52,11 @@ int uwsgi_is_a_keep_mount(char *mp) {
}
static int uwsgi_ns_start(void *v_argv) {
uwsgi_start(v_argv);
return uwsgi_run();
}
void linux_namespace_start(void *argv) {
for (;;) {
char stack[PTHREAD_STACK_MIN];
@@ -61,7 +66,7 @@ void linux_namespace_start(void *argv) {
if (uwsgi.ns_net) {
clone_flags |= CLONE_NEWNET;
}
pid_t pid = clone(uwsgi_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
pid_t pid = clone(uwsgi_ns_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
if (pid == -1) {
uwsgi_error("clone()");
exit(1);
@@ -106,6 +111,11 @@ void linux_namespace_start(void *argv) {
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == 1) {
exit(1);
}
else if (uwsgi.exit_on_reload && WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == 0) {
uwsgi_log("jailed master process exited and exit-on-reload is enabled, shutting down\n");
exit(0);
}
uwsgi_log("pid %d ended. Respawning...\n", (int) pid);
}
+29 -36
View File
@@ -26,9 +26,6 @@ struct uwsgi_carbon {
unsigned long long *last_busyness_values;
unsigned long long *current_busyness_values;
int *was_busy;
int need_retry;
time_t last_update;
time_t next_retry;
int max_retries;
int retry_delay;
char *root_node;
@@ -40,6 +37,7 @@ struct uwsgi_carbon {
int zero_avg;
uint64_t last_requests;
struct uwsgi_stats_pusher *pusher;
int use_metrics;
} u_carbon;
static struct uwsgi_option carbon_options[] = {
@@ -55,6 +53,7 @@ static struct uwsgi_option carbon_options[] = {
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-idle-avg", required_argument, 0, "average values source during idle period (no requests), can be \"last\", \"zero\", \"none\" (default is last)", uwsgi_opt_set_str, &u_carbon.idle_avg, 0},
{"carbon-use-metrics", no_argument, 0, "don't compute all statistics, use metrics subsystem data instead (warning! key names will be different)", uwsgi_opt_true, &u_carbon.use_metrics, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -71,8 +70,8 @@ static void carbon_post_init() {
u_server->healthy = 1;
u_server->errors = 0;
char *p = strtok(usl->value, ":");
while (p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(usl->value, ":", p, ctx) {
if (!u_server->hostname) {
u_server->hostname = uwsgi_str(p);
}
@@ -81,7 +80,6 @@ static void carbon_post_init() {
}
else
break;
p = strtok(NULL, ":");
}
if (!u_server->hostname || !u_server->port) {
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
@@ -109,7 +107,7 @@ static void carbon_post_init() {
if (u_carbon.freq < 1) u_carbon.freq = 60;
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
if (u_carbon.max_retries < 0) u_carbon.max_retries = 0;
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
if (!u_carbon.id) {
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
@@ -154,14 +152,13 @@ static void carbon_post_init() {
u_carbon.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
}
// set next update to now()+retry_delay, this way we will have first flush just after start
u_carbon.last_update = uwsgi_now() - u_carbon.freq + u_carbon.retry_delay;
uwsgi_log("[carbon] carbon plugin started, %is frequency, %is timeout, max retries %i, retry delay %is\n",
u_carbon.freq, u_carbon.timeout, u_carbon.max_retries, u_carbon.retry_delay);
struct uwsgi_stats_pusher_instance *uspi = uwsgi_stats_pusher_add(u_carbon.pusher, NULL);
uspi->freq = u_carbon.freq;
uspi->retry_delay = u_carbon.retry_delay;
uspi->max_retries = u_carbon.max_retries;
// no need to generate the json
uspi->raw=1;
}
@@ -186,14 +183,15 @@ static int carbon_write(int fd, char *fmt,...) {
return 1;
}
static void carbon_push_stats(int retry_cycle, time_t now) {
static int carbon_push_stats(int retry_cycle, time_t now) {
struct carbon_server_list *usl = u_carbon.servers_data;
if (!u_carbon.servers_data) return;
if (!u_carbon.servers_data) return 0;
int i;
int fd;
int wok;
char *ip;
char *carbon_address = NULL;
int needs_retry;
for (i = 0; i < uwsgi.numproc; i++) {
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
@@ -201,7 +199,7 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
u_carbon.was_busy[i-1] += uwsgi_worker_is_busy(i+1);
}
u_carbon.need_retry = 0;
needs_retry = 0;
while(usl) {
if (retry_cycle && usl->healthy)
// skip healthy servers during retry cycle
@@ -229,15 +227,7 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
fd = uwsgi_connect(carbon_address, u_carbon.timeout, 0);
if (fd < 0) {
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", carbon_address);
if (usl->errors < u_carbon.max_retries) {
u_carbon.need_retry = 1;
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
} else {
uwsgi_log("[carbon] Maximum number of retries for %s (%d)\n",
carbon_address, u_carbon.max_retries);
usl->healthy = 0;
usl->errors = 0;
}
needs_retry = 1;
usl->healthy = 0;
usl->errors++;
free(carbon_address);
@@ -247,6 +237,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
if (u_carbon.use_metrics) goto metrics_loop;
unsigned long long total_rss = 0;
unsigned long long total_vsz = 0;
unsigned long long total_tx = 0;
@@ -381,6 +373,18 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
wok = carbon_write(fd, "%s%s.%s.harakiri %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_harakiri, (unsigned long long) now);
if (!wok) goto clear;
metrics_loop:
if (u_carbon.use_metrics) {
struct uwsgi_metric *um = uwsgi.metrics;
while(um) {
uwsgi_rlock(uwsgi.metrics_lock);
wok = carbon_write(fd, "%s%s.%s.%.*s %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, um->name_len, um->name, (unsigned long long) *um->value, (unsigned long long) now);
uwsgi_rwunlock(uwsgi.metrics_lock);
if (!wok) goto clear;
um = um->next;
}
}
usl->healthy = 1;
usl->errors = 0;
@@ -391,23 +395,12 @@ clear:
nxt:
usl = usl->next;
}
if (!retry_cycle) u_carbon.last_update = uwsgi_now();
if (u_carbon.need_retry)
// timeouts and retries might cause additional lags in carbon cycles, we will adjust timer to fix that
u_carbon.last_update -= u_carbon.timeout;
return needs_retry;
}
static void carbon_push(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
if (u_carbon.need_retry && now >= u_carbon.next_retry) {
carbon_push_stats(1, now);
}
else {
// update
u_carbon.need_retry = 0;
carbon_push_stats(0, now);
}
uspi->needs_retry = carbon_push_stats(uspi->retries, now);
}
static void carbon_cleanup() {
+2 -3
View File
@@ -828,8 +828,8 @@ clear2:
// set the start position of args in argv
i = 1;
if (helper) i = 2;
char *p = strtok(qs, "+");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(qs, "+", p, ctx) {
// create a copy for the url_decoded string
char *arg_copy = uwsgi_str(p);
uint16_t arg_copy_len = strlen(p);
@@ -838,7 +838,6 @@ clear2:
argv[i] = uwsgi_malloc( (arg_copy_len * 2) +1);
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
i++;
p = strtok(NULL, "+");
}
free(qs);
}
+4 -2
View File
@@ -13,7 +13,7 @@
extern struct uwsgi_server uwsgi;
int cheaper_backlog2_algo(void) {
int cheaper_backlog2_algo(int can_spawn) {
int i;
#ifdef __linux__
@@ -22,7 +22,9 @@ int cheaper_backlog2_algo(void) {
int backlog = 0;
#endif
if (backlog > (int)uwsgi.cheaper_overload) {
// if can_spawn == 0 we cannot spawn any new worker
// this is set to 1 if --cheaper-rss-limit-* options are used and running workers are exceeding resources limit
if (can_spawn && backlog > (int)uwsgi.cheaper_overload) {
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
+12 -12
View File
@@ -142,7 +142,7 @@ int spawn_emergency_worker(int backlog) {
#endif
int cheaper_busyness_algo(void) {
int cheaper_busyness_algo(int can_spawn) {
int i;
// we use microseconds
@@ -243,11 +243,12 @@ int cheaper_busyness_algo(void) {
uwsgi_cheaper_busyness_global.tolerance_counter = 0;
int decheaped = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step) break;
if (can_spawn) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step) break;
}
}
}
@@ -271,15 +272,15 @@ int cheaper_busyness_algo(void) {
uwsgi_log("[busyness] %llus average busyness is at %llu%%, will spawn %d new worker(s)\n",
uwsgi.cheaper_overload, avg_busyness, decheaped);
} else {
uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers (%d)\n",
uwsgi.cheaper_overload, avg_busyness, uwsgi.numproc);
uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers available with current limits (%d)\n",
uwsgi.cheaper_overload, avg_busyness, active_workers);
}
// return the maximum number of workers to spawn
return decheaped;
#ifdef __linux__
} else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
} else if (can_spawn && backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
return spawn_emergency_worker(backlog);
#endif
@@ -347,14 +348,14 @@ int cheaper_busyness_algo(void) {
}
#ifdef __linux__
else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
else if (can_spawn && backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
// we check for backlog overload every cycle
return spawn_emergency_worker(backlog);
}
else if (backlog > 0) {
if (uwsgi_cheaper_busyness_global.backlog_is_nonzero) {
// backlog was > 0 last time, check timestamp and spawn workers if needed
if ((now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) {
if (can_spawn && (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) {
uwsgi_log("[busyness] backlog was non-zero for %llu second(s), spawning new worker(s)\n", (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000);
uwsgi_cheaper_busyness_global.backlog_nonzero_since = now;
return spawn_emergency_worker(backlog);
@@ -391,4 +392,3 @@ struct uwsgi_plugin cheaper_busyness_plugin = {
.options = uwsgi_cheaper_busyness_options,
};
+6 -5
View File
@@ -187,11 +187,12 @@ void uwsgi_opt_corerouter_zerg(char *opt, char *value, void *cr) {
close(zerg_fd);
for(j=0;j<count;j++) {
if (zerg[j] == -1) break;
ugs = uwsgi_new_gateway_socket_from_fd(zerg[j], ucr->name);
ugs->zerg = optarg;
}
for(j=0;j<count;j++) {
if (zerg[j] == -1) break;
ugs = uwsgi_new_gateway_socket_from_fd(zerg[j], ucr->name);
ugs->zerg = optarg;
}
free(zerg);
}
+36 -7
View File
@@ -51,7 +51,7 @@ SV * coroae_coro_new(CV *block) {
XPUSHs(sv_2mortal(newSVpv( "Coro", 4)));
XPUSHs(newRV_inc((SV *)block));
PUTBACK;
call_method("new", G_SCALAR);
call_method("new", G_SCALAR|G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
@@ -65,6 +65,33 @@ SV * coroae_coro_new(CV *block) {
return newobj;
}
static int coroae_wait_milliseconds(int timeout) {
int ret = -1;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(newSVnv(((double)timeout)/1000.0));
PUTBACK;
call_pv("Coro::AnyEvent::sleep", G_SCALAR|G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
}
else {
SV *p_ret = POPs;
if (SvTRUE(p_ret)) {
ret = 0;
}
}
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
static int coroae_wait_fd_read(int fd, int timeout) {
int ret = 0;
dSP;
@@ -74,7 +101,7 @@ static int coroae_wait_fd_read(int fd, int timeout) {
XPUSHs(newSViv(fd));
XPUSHs(newSViv(timeout));
PUTBACK;
call_pv("Coro::AnyEvent::readable", G_SCALAR);
call_pv("Coro::AnyEvent::readable", G_SCALAR|G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
@@ -101,13 +128,14 @@ static int coroae_wait_fd_write(int fd, int timeout) {
XPUSHs(sv_2mortal(newSViv(fd)));
XPUSHs(sv_2mortal(newSViv(timeout)));
PUTBACK;
call_pv("Coro::AnyEvent::writable", G_SCALAR);
call_pv("Coro::AnyEvent::writable", G_SCALAR|G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
}
else {
if (SvTRUE(POPs)) {
SV *p_ret = POPs;
if (SvTRUE(p_ret)) {
ret = 1;
}
}
@@ -275,7 +303,7 @@ static SV *coroae_add_watcher(int fd, SV *cb) {
XPUSHs(newRV_inc(cb));
PUTBACK;
call_method( "io", G_SCALAR);
call_method( "io", G_SCALAR|G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
@@ -306,7 +334,7 @@ static SV *coroae_condvar_new() {
XPUSHs(sv_2mortal(newSVpv( "AnyEvent", 8)));
PUTBACK;
call_method( "condvar", G_SCALAR);
call_method( "condvar", G_SCALAR|G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
@@ -332,7 +360,7 @@ static void coroae_wait_condvar(SV *cv) {
XPUSHs(cv);
PUTBACK;
call_method( "recv", G_DISCARD);
call_method( "recv", G_DISCARD|G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
@@ -377,6 +405,7 @@ static void coroae_loop() {
uwsgi.current_wsgi_req = coroae_current_wsgi_req;
uwsgi.wait_write_hook = coroae_wait_fd_write;
uwsgi.wait_read_hook = coroae_wait_fd_read;
uwsgi.wait_milliseconds_hook = coroae_wait_milliseconds;
I_CORO_API("uwsgi::coroae");
+1 -1
View File
@@ -14,7 +14,7 @@ if not coroapi:
NAME='coroae'
CFLAGS = os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip().split()
CFLAGS += ['-Wno-int-to-pointer-cast', '-Wno-error=int-to-pointer-cast', '-I%s/Coro' % coroapi]
CFLAGS += ['-Wno-int-to-pointer-cast', '-Wno-error=format', '-Wno-error=int-to-pointer-cast', '-I%s/Coro' % coroapi]
LDFLAGS = []
LIBS = []
+7 -9
View File
@@ -52,9 +52,7 @@ s.send_multipart(['touch','foo.ini',"[uwsgi]\nsocket=:4142"])
*/
#ifdef UWSGI_ZEROMQ
#include "../../uwsgi.h"
#include <uwsgi.h>
#include <zmq.h>
extern struct uwsgi_server uwsgi;
@@ -166,7 +164,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
}
}
// destroy an instance
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 6)) {
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 7)) {
struct uwsgi_instance *ui = emperor_get(name);
if (!ui) {
uwsgi_log("[emperor-zeromq] unknown instance \"%s\"\n", name);
@@ -215,7 +213,11 @@ static void uwsgi_imperial_monitor_zeromq_event(struct uwsgi_emperor_scanner *ue
// initialize the zmq PULL socket
static void uwsgi_imperial_monitor_zeromq_init(struct uwsgi_emperor_scanner *ues) {
void *context = uwsgi_zeromq_init();
void *context = zmq_init(1);
if (!context) {
uwsgi_error("uwsgi_imperial_monitor_zeromq_init()/zmq_init()");
exit(1);
}
ues->data = zmq_socket(context, ZMQ_PULL);
if (!ues->data) {
@@ -256,7 +258,3 @@ struct uwsgi_plugin emperor_zeromq_plugin = {
.name = "emperor_zeromq",
.on_load = emperor_zeromq_init,
};
#else
#error the uWSGI ZeroMQ imperial monitor requires uWSGI zeromq support
#endif
+6 -4
View File
@@ -190,21 +190,23 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
// called after receaving the uwsgi header (read vars)
static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
struct uwsgi_header *uh = (struct uwsgi_header *) main_peer->in->buf;
// better to store it as the original buf address could change
uint16_t pktsize = uh->pktsize;
// increase buffer if needed
if (uwsgi_buffer_fix(main_peer->in, uh->pktsize+4))
if (uwsgi_buffer_fix(main_peer->in, pktsize+4))
return -1;
ssize_t len = cr_read_exact(main_peer, uh->pktsize+4, "fr_recv_uwsgi_vars()");
ssize_t len = cr_read_exact(main_peer, pktsize+4, "fr_recv_uwsgi_vars()");
if (!len) return 0;
// headers received, ready to choose the instance
if (main_peer->in->pos == (size_t)(uh->pktsize+4)) {
if (main_peer->in->pos == (size_t)(pktsize+4)) {
struct uwsgi_corerouter *ucr = main_peer->session->corerouter;
struct corerouter_peer *new_peer = uwsgi_cr_peer_add(main_peer->session);
new_peer->last_hook_read = fr_instance_read;
// find the hostname
if (uwsgi_hooked_parse(main_peer->in->buf+4, uh->pktsize, fr_get_hostname, (void *) new_peer)) {
if (uwsgi_hooked_parse(main_peer->in->buf+4, pktsize, fr_get_hostname, (void *) new_peer)) {
return -1;
}
+296
View File
@@ -0,0 +1,296 @@
/*
uWSGI forkpty-router
can use the uwsgi protocol, modifier2 means:
0 -> stdin
1-99 -> UNIX signal
100 -> window rows (pktsize is the window size)
101 -> window cols (pktsize is the window size)
*/
#include <uwsgi.h>
#include "../corerouter/cr.h"
extern struct uwsgi_server uwsgi;
#if defined(__linux__) || defined(__GNU_kFreeBSD__)
#include <pty.h>
#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include <util.h>
#elif defined(__FreeBSD__)
#include <libutil.h>
#endif
#ifndef __FreeBSD__
#include <utmp.h>
#endif
static struct uwsgi_forkptyrouter {
struct uwsgi_corerouter cr;
char *cmd;
uint16_t win_rows;
uint16_t win_cols;
} ufpty;
extern struct uwsgi_server uwsgi;
struct forkptyrouter_session {
struct corerouter_session session;
// use the uwsgi protocol ?
int uwsgi;
size_t restore_size;
struct winsize w;
pid_t pid;
};
static void uwsgi_opt_forkpty_urouter(char *opt, char *value, void *cr) {
struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr;
struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(value, ucr->name);
ugs->no_defer = 1;
ugs->mode = 1;
ucr->has_sockets++;
}
static struct uwsgi_option forkptyrouter_options[] = {
{"forkptyrouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
{"forkpty-router", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
{"forkptyurouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_forkpty_urouter, &ufpty, 0},
{"forkpty-urouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_forkpty_urouter, &ufpty, 0},
{"forkptyrouter-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
{"forkpty-router-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
{"forkptyrouter-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
{"forkpty-router-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
{"forkptyrouter-rows", required_argument, 0, "set forkptyrouter default pty window rows", uwsgi_opt_set_16bit, &ufpty.win_rows, 0},
{"forkptyrouter-cols", required_argument, 0, "set forkptyrouter default pty window cols", uwsgi_opt_set_16bit, &ufpty.win_cols, 0},
{"forkptyrouter-processes", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
{"forkptyrouter-workers", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
{"forkptyrouter-zerg", required_argument, 0, "attach the forkptyrouter to a zerg server", uwsgi_opt_corerouter_zerg, &ufpty, 0},
{"forkptyrouter-fallback", required_argument, 0, "fallback to the specified node in case of error", uwsgi_opt_add_string_list, &ufpty.cr.fallback, 0},
{"forkptyrouter-events", required_argument, 0, "set the maximum number of concufptyent events", uwsgi_opt_set_int, &ufpty.cr.nevents, 0},
{"forkptyrouter-cheap", no_argument, 0, "run the forkptyrouter in cheap mode", uwsgi_opt_true, &ufpty.cr.cheap, 0},
{"forkptyrouter-timeout", required_argument, 0, "set forkptyrouter timeout", uwsgi_opt_set_int, &ufpty.cr.socket_timeout, 0},
{"forkptyrouter-stats", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
{"forkptyrouter-stats-server", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
{"forkptyrouter-ss", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
{"forkptyrouter-harakiri", required_argument, 0, "enable forkptyrouter harakiri", uwsgi_opt_set_int, &ufpty.cr.harakiri, 0},
{0, 0, 0, 0, 0, 0, 0},
};
// write to backend
static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) peer->session;
ssize_t len = cr_write(peer, "fpty_instance_write()");
// end on empty write
if (!len) return 0;
// the chunk has been sent, start (again) reading from client and instances
if (cr_write_complete(peer)) {
// reset the buffer
if (fpty_session->uwsgi) {
if (uwsgi_buffer_decapitate(peer->out, peer->out->pos)) return -1;
peer->out->pos = fpty_session->restore_size;
}
else {
peer->out->pos = 0;
}
cr_reset_hooks(peer);
}
return len;
}
// write to client
static ssize_t fpty_write(struct corerouter_peer *main_peer) {
ssize_t len = cr_write(main_peer, "fpty_write()");
// end on empty write
if (!len) return 0;
// ok this response chunk is sent, let's start reading again
if (cr_write_complete(main_peer)) {
// reset the buffer
main_peer->out->pos = 0;
cr_reset_hooks(main_peer);
}
return len;
}
static ssize_t fpty_parse_uwsgi(struct corerouter_peer *peer) {
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) peer->session;
for(;;) {
if (peer->in->pos < 4) return 0;
struct uwsgi_header *uh = (struct uwsgi_header *) peer->in->buf;
uint16_t pktsize = uh->pktsize;
switch(uh->modifier2) {
case 0:
// stdin
if ((size_t) (pktsize+4) > peer->in->pos) return 0;
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
return pktsize;
case 100:
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
fpty_session->w.ws_row = pktsize;
ioctl(peer->session->peers->fd, TIOCSWINSZ, &fpty_session->w);
// rows
break;
case 101:
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
fpty_session->w.ws_col = pktsize;
ioctl(peer->session->peers->fd, TIOCSWINSZ, &fpty_session->w);
// cols
break;
default:
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
// send signal
kill(fpty_session->pid, uh->modifier2);
break;
}
}
return 0;
}
// read from backend
static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
ssize_t len = cr_read(peer, "fpty_instance_read()");
if (!len) return 0;
// set the input buffer as the main output one
peer->session->main_peer->out = peer->in;
peer->session->main_peer->out_pos = 0;
cr_write_to_main(peer, fpty_write);
return len;
}
// read from client
static ssize_t fpty_read(struct corerouter_peer *main_peer) {
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) main_peer->session;
ssize_t len = cr_read(main_peer, "fpty_read()");
if (!len) return 0;
if (fpty_session->uwsgi) {
ssize_t rlen = fpty_parse_uwsgi(main_peer);
if (rlen < 0) return -1;
if (rlen == 0) return 1;
fpty_session->restore_size = main_peer->in->pos - rlen;
main_peer->session->peers->out = main_peer->in;
main_peer->session->peers->out->pos = rlen;
}
else {
main_peer->session->peers->out = main_peer->in;
}
main_peer->session->peers->out_pos = 0;
cr_write_to_backend(main_peer->session->peers, fpty_instance_write);
return len;
}
static void fpty_session_close(struct corerouter_session *cs) {
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
if (fpty_session->pid > 0) {
int waitpid_status = 0;
if (waitpid(fpty_session->pid, &waitpid_status, WNOHANG) < 0) {
uwsgi_error("fpty_session_close()/waitpid()");
}
}
}
// allocate a new session
static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
// set default read hook
cs->main_peer->last_hook_read = fpty_read;
// wait4() on close
cs->close = fpty_session_close;
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
if (ugs->mode == 1) {
fpty_session->uwsgi = 1;
}
// default terminal size
fpty_session->w.ws_row = ufpty.win_rows ? ufpty.win_rows : 24;
fpty_session->w.ws_col = ufpty.win_cols ? ufpty.win_cols : 80;
// add a new peer
struct corerouter_peer *peer = uwsgi_cr_peer_add(cs);
// on new connection generate a new pty
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, &fpty_session->w);
if (fpty_session->pid < 0) {
uwsgi_error("forkpty()");
return -1;
}
else if (fpty_session->pid == 0) {
if (ufpty.cmd) {
char *space = strchr(ufpty.cmd, ' ');
if (space) {
char *argv[4];
argv[0] = uwsgi_binsh();
argv[1] = "-c";
argv[2] = ufpty.cmd;
argv[3] = NULL;
execv(argv[0], argv);
}
else {
char *argv[2];
argv[0] = ufpty.cmd;
argv[1] = NULL;
execv(argv[0], argv);
}
}
else {
char *argv[2];
argv[0] = "/bin/sh";
argv[1] = NULL;
execv(argv[0], argv);
}
// never here;
uwsgi_error("forkptyrouter_alloc_session()/execv()");
exit(1);
}
ucr->cr_table[peer->fd] = peer;
cr_reset_hooks_and_read(peer, fpty_instance_read);
return 0;
}
static int forkptyrouter_init() {
ufpty.cr.session_size = sizeof(struct forkptyrouter_session);
ufpty.cr.alloc_session = forkptyrouter_alloc_session;
uwsgi_corerouter_init((struct uwsgi_corerouter *) &ufpty);
return 0;
}
static void forkptyrouter_setup() {
ufpty.cr.name = uwsgi_str("uWSGI forkptyrouter");
ufpty.cr.short_name = uwsgi_str("forkptyrouter");
}
struct uwsgi_plugin forkptyrouter_plugin = {
.name = "forkptyrouter",
.options = forkptyrouter_options,
.init = forkptyrouter_init,
.on_load = forkptyrouter_setup
};
+8
View File
@@ -0,0 +1,8 @@
NAME='forkptyrouter'
CFLAGS = []
LDFLAGS = []
LIBS = []
REQUIRES = ['corerouter']
GCC_LIST = ['forkptyrouter']
+275 -19
View File
@@ -2,7 +2,7 @@
/*
Soon before official Go 1.1, we understand supporting Go in a fork() heavy
Soon before official Go 1.1, we understood supporting Go in a fork() heavy
environment was not blessed by the Go community.
Instead of completely dropping support for Go, we studied how the gccgo project works and we
@@ -16,8 +16,31 @@
the uwsgi.Run() go function directly calls the uwsgi_takeover() function (it automatically
manages mules, spoolers and workers)
As well as before each core maps to a goroutine mapped to a real pthread. (goroutines called
from your apps are native goroutines)
The plugin implements goroutines too.
On startup a goroutine is created for each socket and signals file descriptors.
For every request a new goroutine is created too.
The wsgi_request * structure is attached to the "closure" field of the goroutine (PAY ATTENTION)
even if the loop engine makes use of the async mode, pthreads could be spawned all over the place.
For such a reason a mutex is created avoiding the global wsgi_req structures to be clobbered
Contrary to the standard way Go apps are deployed, the plugin supports loading shared libraries.
While this is a common approach in other environments, the Go community prefers monolithic binaries.
As always, choose the model that best suite for you. Eventually building a single uWSGI binary with your Go
app embedded is pretty easy:
CFLAGS=-DUWSGI_GCCGO_MONOLITHIC UWSGI_ADDITIONAL_SOURCES=t/go/uploadtest.go UWSGI_PROFILE=gccgo make
or you can add the following two directives in a build profile:
cflags = -DUWSGI_GCCGO_MONOLITHIC
additional_sources = t/go/uploadtest.go
*/
@@ -25,25 +48,29 @@ extern struct uwsgi_server uwsgi;
struct uwsgi_plugin gccgo_plugin;
struct uwsgi_gccgo{
// 1 if a main is loaded
int initialized;
struct uwsgi_string_list *libs;
char *args;
pthread_mutex_t wsgi_req_lock;
} ugccgo;
/*
shortcut for enabling the "goroutines" loop engine
*/
static void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
// set async mode
uwsgi_opt_set_int(opt, value, &uwsgi.async);
// set loop engine
uwsgi.loop = "goroutines";
}
*/
struct uwsgi_option uwsgi_gccgo_options[] = {
{"go-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
{"gccgo-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
{"go-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
{"gccgo-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
// {"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
{"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of max goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -51,27 +78,46 @@ struct uwsgi_option uwsgi_gccgo_options[] = {
// no_split_stack is the key to avoid crashing !!!
void* runtime_m(void) __attribute__ ((noinline, no_split_stack));
// initialize runtime
void runtime_check(void);
void runtime_args(int, char **);
void runtime_osinit(void);
void runtime_schedinit(void);
void *__go_go(void *, void *);
void runtime_main(void);
void runtime_mstart(void *);
// spawn a goroutine
void *__go_go(void *, void *);
// api functions exposed
extern void uwsgigo_request(void *, void *) __asm__ ("go.uwsgi.RequestHandler");
extern void* uwsgigo_env(void *) __asm__ ("go.uwsgi.Env");
extern void* uwsgigo_env_add(void *, void *, uint16_t, void *, uint16_t) __asm__ ("go.uwsgi.EnvAdd");
extern void uwsgigo_run_core(int) __asm__ ("go.uwsgi.RunCore");
extern void uwsgigo_signal_handler(void *, uint8_t) __asm__ ("go.uwsgi.SignalHandler");
//extern void uwsgigo_loop(void) __asm__ ("go.uwsgi.Loop");
// for goroutines
void runtime_netpollinit(void);
void runtime_starttheworld(void);
void *runtime_pollOpen(int) __asm__ ("net.runtime_pollOpen");
void runtime_pollClose(void *) __asm__ ("net.runtime_pollClose");
void runtime_pollUnblock(void *) __asm__ ("net.runtime_pollUnblock");
int runtime_pollWait(void *, int) __asm__ ("net.runtime_pollWait");
void runtime_pollSetDeadline(void *, int64_t, int) __asm__ ("net.runtime_pollSetDeadline");
void runtime_gosched(void);
// the current goroutine
void *runtime_g(void);
// we use the closure field to store the wsgi_req structure
void __go_set_closure(void *);
void *__go_get_closure(void);
static void mainstart(void *arg __attribute__((unused))) {
runtime_main();
}
#ifndef UWSGI_GCCGO_MONOLITHIC
void uwsgigo_main_main(void) __asm__ ("main.main");
void uwsgigo_main_init(void) __asm__ ("__go_init_main");
#endif
void (*uwsgigo_hook_init)(void);
void (*uwsgigo_hook_main)(void);
@@ -102,6 +148,14 @@ int uwsgi_gccgo_helper_register_signal(uint8_t signum, char *receiver, void *han
}
static void uwsgi_gccgo_initialize() {
if (uwsgi.threads > 1) {
uwsgi_log("!!! the Go runtime cannot work in multithreaded modes !!!\n");
exit(1);
}
#ifdef UWSGI_GCCGO_MONOLITHIC
uwsgigo_hook_init = dlsym(RTLD_DEFAULT, "__go_init_main");
uwsgigo_hook_main = dlsym(RTLD_DEFAULT, "main.main");
#endif
struct uwsgi_string_list *usl = ugccgo.libs;
while(usl) {
void *handle = dlopen(usl->value, RTLD_NOW | RTLD_GLOBAL);
@@ -109,9 +163,16 @@ static void uwsgi_gccgo_initialize() {
uwsgi_log("unable to open go shared library: %s\n", dlerror());
exit(1);
}
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
uwsgigo_hook_init = dlsym(handle, "__go_init_main");
uwsgigo_hook_main = dlsym(handle, "main.main");
void *g_init = dlsym(handle, "__go_init_main");
void *g_main = dlsym(handle, "main.main");
if (g_init && g_main) {
uwsgigo_hook_init = g_init;
uwsgigo_hook_main = g_main;
uwsgi_log("[uwsgi-gccgo] loaded %s as main\n", usl->value);
}
else {
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
}
usl = usl->next;
}
@@ -119,27 +180,27 @@ static void uwsgi_gccgo_initialize() {
return;
}
ugccgo.initialized = 1;
// Go runtime initialization
int argc = 0;
if (ugccgo.args) {
char *argv_list = uwsgi_str(ugccgo.args);
char *p = strtok(argv_list, " ");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(argv_list, " ", p, ctx) {
argc++;
p = strtok(NULL, " ");
}
free(argv_list);
}
runtime_check();
if (argc > 0) {
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 2));
char *argv_list = uwsgi_str(ugccgo.args);
char *p = strtok(argv_list, " ");
char *p, *ctx = NULL;
int n = 0;
while(p) {
uwsgi_foreach_token(argv_list, " ", p, ctx) {
argv[n] = p;
n++;
p = strtok(NULL, " ");
}
runtime_args(argc, argv);
}
@@ -147,6 +208,7 @@ static void uwsgi_gccgo_initialize() {
char *argv[2] = {0,0};
runtime_args(0, argv);
}
runtime_osinit();
runtime_schedinit();
__go_go(mainstart, NULL);
@@ -155,6 +217,10 @@ static void uwsgi_gccgo_initialize() {
}
static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
if (!ugccgo.initialized) {
uwsgi_log("!!! Go runtime not initialized !!!\n");
goto end;
}
/* Standard GO request */
if (!wsgi_req->uh->pktsize) {
uwsgi_log("Empty GO request. skip.\n");
@@ -172,6 +238,7 @@ static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
i++;
}
uwsgigo_request(wsgi_req->async_environ, wsgi_req);
end:
return UWSGI_OK;
}
@@ -180,15 +247,204 @@ static void uwsgi_gccgo_after_request(struct wsgi_request *wsgi_req) {
}
static int uwsgi_gccgo_signal_handler(uint8_t signum, void *handler) {
if (!ugccgo.initialized) return -1;
uwsgigo_signal_handler(handler, signum);
return 0;
}
#define free_req_queue pthread_mutex_lock(&ugccgo.wsgi_req_lock);uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req; pthread_mutex_unlock(&ugccgo.wsgi_req_lock)
static void uwsgi_gccgo_request_goroutine(void *arg) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) arg;
// map wsgi_req to the goroutine
__go_set_closure(wsgi_req);
int ret,status;
for(;;) {
ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
wsgi_req->switches++;
if (ret <= 0) {
goto end;
}
retry:
status = wsgi_req->socket->proto(wsgi_req);
if (status < 0) {
goto end;
}
else if (status == 0) {
break;
}
if (uwsgi_is_again()) continue;
goto retry;
}
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
goto end;
}
#endif
for(;;) {
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
goto end;
}
wsgi_req->switches++;
// yield
runtime_gosched();
}
end:
uwsgi_close_request(wsgi_req);
free_req_queue;
}
static struct wsgi_request *uwsgi_gccgo_current_wsgi_req(void) {
return (struct wsgi_request *) __go_get_closure();
}
static int uwsgi_gccgo_wait_read_hook(int fd, int timeout) {
void *pdesc = runtime_pollOpen(fd);
int64_t t = (uwsgi_micros() * 1000LL) + (((int64_t)timeout) * 1000LL * 1000LL * 1000LL);
runtime_pollSetDeadline(pdesc, t, 'r');
int ret = runtime_pollWait(pdesc, 'r');
runtime_pollUnblock(pdesc);
runtime_pollClose(pdesc);
if (ret == 0) return 1;
// timeout
if (ret == 2) return 0;
return -1;
}
static int uwsgi_gccgo_wait_write_hook(int fd, int timeout) {
void *pdesc = runtime_pollOpen(fd);
int64_t t = (uwsgi_micros() * 1000LL) + (((int64_t)timeout) * 1000LL * 1000LL * 1000LL);
runtime_pollSetDeadline(pdesc, t, 'w');
int ret = runtime_pollWait(pdesc, 'w');
runtime_pollUnblock(pdesc);
runtime_pollClose(pdesc);
if (ret == 0) return 1;
// timeout
if (ret == 2) return 0;
return -1;
}
/*
this goroutine manages signals
*/
static void uwsgi_gccgo_signal_goroutine(void *arg) {
int *fd = (int *) arg;
void *pdesc = runtime_pollOpen(*fd);
for(;;) {
runtime_pollWait(pdesc, 'r');
retry:
uwsgi_receive_signal(*fd, "worker", uwsgi.mywid);
if (uwsgi_is_again()) continue;
goto retry;
}
}
static void uwsgi_gccgo_socket_goroutine(void *arg) {
struct uwsgi_socket *uwsgi_sock = (struct uwsgi_socket *) arg;
struct wsgi_request *wsgi_req = NULL;
void *pdesc = runtime_pollOpen(uwsgi_sock->fd);
// wait for connection
for(;;) {
runtime_pollWait(pdesc, 'r');
retry:
pthread_mutex_lock(&ugccgo.wsgi_req_lock);
wsgi_req = find_first_available_wsgi_req();
pthread_mutex_unlock(&ugccgo.wsgi_req_lock);
if (wsgi_req == NULL) {
uwsgi_async_queue_is_full(uwsgi_now());
// try rescheduling...
// we do not use runtime_gosched() as we want to call the netpoll loop too
runtime_pollUnblock(pdesc);
runtime_pollClose(pdesc);
pdesc = runtime_pollOpen(uwsgi_sock->fd);
continue;
}
// fill wsgi_request structure
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi_sock );
// mark core as used
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
// accept the connection (since uWSGI 1.5 all of the sockets are non-blocking)
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
free_req_queue;
if (uwsgi_is_again()) continue;
goto retry;
}
wsgi_req->start_of_request = uwsgi_micros();
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// spawn the new goroutine
__go_go(uwsgi_gccgo_request_goroutine, wsgi_req);
goto retry;
}
}
static void uwsgi_gccgo_loop() {
if (!ugccgo.initialized) {
uwsgi_log("no go.main code loaded !!!\n");
exit(1);
}
// initialize the log protecting the wsgi_req structures
pthread_mutex_init(&ugccgo.wsgi_req_lock, NULL);
// hooks
uwsgi.current_wsgi_req = uwsgi_gccgo_current_wsgi_req;
uwsgi.wait_write_hook = uwsgi_gccgo_wait_write_hook;
uwsgi.wait_read_hook = uwsgi_gccgo_wait_read_hook;
// ininitialize Go I/O loop
runtime_netpollinit();
if (uwsgi.signal_socket > -1) {
__go_go(uwsgi_gccgo_signal_goroutine, &uwsgi.signal_socket);
__go_go(uwsgi_gccgo_signal_goroutine, &uwsgi.my_signal_socket);
}
// start a goroutine for each socket
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (!uwsgi_sock->next) {
uwsgi_gccgo_socket_goroutine(uwsgi_sock);
}
else {
__go_go(uwsgi_gccgo_socket_goroutine, uwsgi_sock);
}
uwsgi_sock = uwsgi_sock->next;
}
// never here
}
static void uwsgi_gccgo_on_load() {
uwsgi_register_loop( (char *) "go", uwsgi_gccgo_loop);
uwsgi_register_loop( (char *) "goroutine", uwsgi_gccgo_loop);
uwsgi_register_loop( (char *) "goroutines", uwsgi_gccgo_loop);
}
struct uwsgi_plugin gccgo_plugin = {
.name = "gccgo",
.modifier1 = 11,
.options = uwsgi_gccgo_options,
//.on_load = uwsgi_gccgo_on_load,
.on_load = uwsgi_gccgo_on_load,
.request = uwsgi_gccgo_request,
.after_request = uwsgi_gccgo_after_request,
.post_fork = uwsgi_gccgo_initialize,

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