Compare commits

...
199 Commits
Author SHA1 Message Date
Unbit 7108ee1ba0 improved xclient 2013-06-22 11:50:45 +02:00
Unbit cf8e68f7a0 another attempt to fix xclient 2013-06-22 11:18:25 +02:00
Unbit a9510c2209 fixed xclient 2013-06-22 10:51:17 +02:00
Unbit b2be5943a8 added router_xmldir plugin 2013-06-21 06:54:05 +02:00
Unbit 8f19fe292e added --add-cache-item 2013-06-20 15:12:48 +02:00
Unbit d3e7668d0a better clang detection 2013-06-20 11:00:05 +02:00
Unbit 88e67a74e5 fixed #321 2013-06-20 08:59:18 +02:00
Roberta Giordano 7fecda1a23 fixed #324 2013-06-20 06:15:35 +02:00
unbit 56b6fa88f9 Merge pull request #323 from jbert/master
Fix infinite loop in psgi/coroae
2013-06-19 07:47:52 -07:00
John Berthels e847cfe4bc fix infinite loop in coroae/psgi
Perl PSGI app infinite loops since f20213ff10

Looking at that change, other loop termination conditions are '<= UWSGI_OK'.
Using gdb to inspect the app while looping shows thats ->request is returning
UWSGI_OK in this case. However, the numeric value of this is zero, so we
never exit the for(;;) loop.

Cargo culting loop escape conditions from core/async.c (or gevent/gevent.c)
fixes the inf loop for psgi/coroae.
2013-06-19 15:27:31 +01:00
Roberta Giordano 1a854ae3ba varios osx build workaround 2013-06-19 07:14:54 +02:00
unbit c75180bf95 Create logo_uWSGI.svg 2013-06-17 10:26:59 +02:00
Unbit d496450b84 added seturi and setpathinfo routing actions 2013-06-16 07:52:59 +02:00
Unbit d2636ed133 better compiler detection 2013-06-16 07:13:19 +02:00
unbit 59de0c2085 Merge pull request #317 from anaconda/fix-gcc-darwin-llvm
Fix GCC on Darwin for Python 3.
2013-06-15 22:11:11 -07:00
anaconda 4b7df29bd1 Fix GCC on Darwin for Python 3.
distutils.sysconfig.get_config_var('CC') returns the compiler used to
build Python, which may be not installed on the system where uWSGI is
being built.

In my case, I grabbed Python 3.3.2 from python.org: it was apparently
compiled with 'gcc-4.2', but my system only has 'gcc' (symlink) and
'llvm-gcc-4.2'.  This change tries to detect this situation (only on
Darwin) and sets GCC to 'llvm-' + compiler returned by sysconfig.
2013-06-16 01:59:48 +02:00
unbit b099ba6a29 Merge pull request #316 from anaconda/spool-decorator-call
Implement __call__ for @spool* decorators.
2013-06-15 07:09:51 -07:00
anaconda 164069e194 Implement __call__ for @spool* decorators.
Also removed duplicate code.
2013-06-15 15:05:39 +02:00
Unbit b3e4ff8613 cosmetic fix for fastcgi 2013-06-15 14:37:50 +02:00
Unbit 3eb5ec3543 better fastcgi handling 2013-06-15 14:36:18 +02:00
unbit c3c698a615 Update uwsgi.conf 2013-06-15 15:09:22 +03:00
Unbit ac6d2f3e83 rack api functions are now static 2013-06-15 11:55:48 +02:00
Unbit d1f1b8a43a another tests cleanup 2013-06-15 08:03:34 +02:00
Unbit 85586a621c the official API list is now in uwsgi-docs 2013-06-15 08:01:53 +02:00
Unbit 1a384a334f remove mercurial files 2013-06-15 08:00:16 +02:00
Unbit 8901afded5 moved lanunchd examples to contrib 2013-06-15 07:59:27 +02:00
Roberta Giordano ab12703a11 added new set_user_harakiri to python,pypy,perl and ruby 2013-06-15 07:04:53 +02:00
Roberta Giordano 9992b4c964 improved set_user_harakiri to support mules and spoolers 2013-06-15 06:50:10 +02:00
unbit 9a2dbd08cd Merge pull request #315 from prymitive/curl_bug
fix curl crashing master on slow dns responses
2013-06-14 06:48:03 -07:00
Łukasz Mierzwa 5f92a00b71 fix curl crashing master on slow dns responses 2013-06-14 09:24:00 +02:00
Unbit 7bd9d51217 added mule support to pypy 2013-06-12 16:39:10 +02:00
unbit 80c649aa40 Create emperor.conf 2013-06-11 13:47:34 +03:00
Unbit 6c8fe2cc53 improved ready_fd call 2013-06-10 23:01:19 +02:00
Unbit dcc7167d75 added uwsgi[lq] routing var 2013-06-10 02:48:52 +02:00
Unbit e3a52e4039 added --use-abort 2013-06-09 23:14:52 +02:00
Unbit 498f6162f7 fixed debug 2013-06-09 23:00:22 +02:00
Unbit 33d85d3670 added coroae build profile 2013-06-09 22:58:18 +02:00
Unbit afbf5b9633 fixed typo doc 2013-06-09 22:54:42 +02:00
Unbit a8505be6c0 standardized uwsgi.disconnect() 2013-06-09 22:47:44 +02:00
Unbit 4a07632569 uwsgi.add_cron does not return a value 2013-06-09 22:35:52 +02:00
Unbit d4f0589c39 fixed uwsgi.fd_ready() 2013-06-09 22:22:59 +02:00
Roberta Giordano a9989d46fc set default lock to 0 in pypy uwsgi.lock/uwsgi.unlock 2013-06-10 06:08:15 +02:00
Unbit 99cf598c0c added chunked input support to pypy 2013-06-09 08:47:50 +02:00
Unbit a6af22b8f0 ported websockets api to pypy 2013-06-09 08:35:12 +02:00
Unbit 0961d61a88 added chunked async support 2013-06-09 08:06:45 +02:00
Unbit 7b76a2d749 first test for chunked input 2013-06-09 03:25:46 +02:00
Unbit b516f1d3ec added --chunked-input-limit and --chunked-input-timeout 2013-06-09 03:06:12 +02:00
Unbit 8fdef7a1f9 added chunked input api 2013-06-09 03:02:16 +02:00
Unbit 10258db4ae removed python 3 need for 'imp' module 2013-06-08 23:36:49 +02:00
unbit 621c9523cf fixed python3 compilation and added UWSGI_INCLUDES 2013-06-09 07:01:34 +02:00
Unbit c415adab28 added setmethod routing action 2013-06-08 01:05:44 +02:00
Unbit 7fef1048b3 added pypy greenlet contrib module 2013-06-07 10:15:25 +02:00
Unbit 1e7aaeeeed fix harakiri routing 2013-06-07 09:11:54 +02:00
Unbit c5b4564001 added 2 example of continulets 2013-06-06 18:16:01 +02:00
Unbit a9127c8d79 added support for pypy uwsgi.async_sleep 2013-06-06 17:25:03 +02:00
Unbit a0f7a5c70f added support for pypy continulets 2013-06-06 17:17:51 +02:00
Unbit ecf3cae35b use ffi.string instead of ffi.buffer in pypy 2013-06-06 16:05:20 +02:00
Unbit d553bc8014 let's start with 1.9.13 2013-06-06 15:49:51 +02:00
Unbit a1553d3632 removed debug print from pypy_setup.py 2013-06-06 14:54:39 +02:00
Unbit bb42ae1b4a fixed cron and alarm in pypy_setup.py 2013-06-06 14:16:38 +02:00
Unbit 61ac2efe0e added user_lock/unlock to new pypy setup 2013-06-06 14:15:02 +02:00
Unbit 1c0a3ec413 refactored the pypy plugin to make best use of cffi and to avoid the need of helpers 2013-06-06 14:10:34 +02:00
Unbit 8b7e93385b missing newline in --cflags 2013-06-06 11:27:14 +02:00
Unbit c742624054 added uwsgi_get_cflags() 2013-06-06 11:25:17 +02:00
Unbit 8011f0615d added --dot-h infrastructure 2013-06-06 11:18:25 +02:00
Unbit 8096b2198f fixed --print-sym and embed uwsgi.h in the server binary 2013-06-06 10:06:40 +02:00
Unbit 3556bd5283 removed PTRACE check, was an old stupid attempt 2013-06-06 09:42:08 +02:00
Unbit 26710694af fixed #306 2013-06-05 15:19:21 +02:00
Unbit 0f397eeb55 fixed #305 2013-06-05 11:14:47 +02:00
Unbit bf929398a9 updated gemspec for 1.9.12 2013-06-05 09:19:57 +02:00
Unbit 4f8a0f753e added router_hash and extended support for memcached and redis 2013-06-05 06:26:39 +02:00
Unbit 7db5da9566 fixed support for newer cygwin 2013-06-04 17:13:18 +02:00
Unbit 4d1389805c added redis router code 2013-06-04 13:20:47 +02:00
Unbit ee87e2b946 memcached and redis routers are now builtin by default 2013-06-04 13:07:51 +02:00
Unbit 6356d78768 completed memcachedstore 2013-06-04 12:04:42 +02:00
Unbit afdf7e740e prepare for memcachedstore 2013-06-04 11:40:19 +02:00
Unbit 51ce3ddf78 added offloading to memcached internal router 2013-06-04 11:18:02 +02:00
Unbit 192186056e added pipe offload engine 2013-06-04 10:34:19 +02:00
Unbit 336a7febd7 prepate for 1.9.12 2013-06-03 15:35:17 +02:00
Unbit 63e73d1b73 added --touch-signal 2013-06-03 11:15:39 +02:00
Unbit a02ab9a723 automatically search for 'application' method in jwsgi 2013-06-03 06:33:48 +02:00
Unbit 95f15ab9dd added a note for python logger 2013-06-02 19:20:35 +02:00
Unbit 5d0ea0066a fixed fastcgi body read 2013-06-02 12:52:13 +02:00
Unbit 9ff6b2da9b improved tmp file generation and first implementation of offload transformation 2013-06-02 11:12:28 +02:00
Roberta Giordano 6ac7e27847 added seek() support to jvm input 2013-06-01 19:53:29 +02:00
Roberta Giordano 4ed1c5e747 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-06-01 19:42:29 +02:00
Roberta Giordano bae3bc096f added readLine featute to jvm input 2013-06-01 19:42:11 +02:00
unbit 9d73683de2 Merge pull request #298 from prymitive/csfix
try to escape json
2013-06-01 08:15:19 -07:00
Roberta Giordano f5fec0ab71 added support for jvm list and uwsgi.opt 2013-06-01 16:32:39 +02:00
Łukasz Mierzwa 9909ab10c4 try to escape json 2013-06-01 15:53:35 +02:00
Roberta Giordano 65cff01fee implemented non-static JWSGI apps 2013-06-01 12:20:19 +02:00
unbit 10190a3012 Merge pull request #301 from jimfunk/master
Fix signed/unsigned comparison in emperor_amqp plugin
2013-05-31 21:56:23 -07:00
James Oakley 79ab696f4e Fix signed/unsigned comparison 2013-05-31 13:24:49 -07:00
Unbit cb603682e4 updated gemspec for the new release 2013-05-26 08:08:32 +02:00
Unbit c986a06bf7 more api functions in the uwsgi pypy module, it is enough for 1.9.11 2013-05-26 07:24:57 +02:00
Unbit e2843a6cee fixed static cache paths 2013-05-25 21:03:59 +02:00
Unbit ea1f239807 added memory offload 2013-05-25 20:01:26 +02:00
Unbit 8d7618146a fixed X-Sendfile + gzip 2013-05-25 18:07:41 +02:00
Unbit eb9e419bb0 fixed GC problem with pypy callback 2013-05-25 08:26:52 +02:00
Unbit f98f71ac26 added rbtimer and rpc/call to pypy 2013-05-25 08:09:09 +02:00
Unbit 03baaaebcb only import gevent.select in chat example 2013-05-24 20:41:51 +02:00
Unbit cbca954508 added tests/websockets_chat.py 2013-05-24 20:37:53 +02:00
Unbit 22ba6cc406 added uwsgi.lock/unlock to pypy and fixed --pypy-wsgi-file 2013-05-24 18:10:29 +02:00
Unbit 6bd172acb4 added preinit_apps hook in pypy 2013-05-24 06:59:13 +02:00
unbit 818ba4416f Merge pull request #295 from prymitive/cron_harakiri_fix
send sigkill to whole process group on cron harakiri
2013-05-23 06:50:45 -07:00
Łukasz Mierzwa adff12841c fixed harakiri for cron2 2013-05-23 15:40:02 +02:00
Łukasz Mierzwa 480c306591 send sigkill to whole process group on cron harakiri 2013-05-23 14:52:38 +02:00
unbit cbd1481cb7 Merge pull request #294 from prymitive/cron2
--cron2 option
2013-05-23 04:51:36 -07:00
Łukasz Mierzwa d1c1871222 --cron2 option 2013-05-23 13:44:13 +02:00
Unbit 15a94b8fb0 fixed a typo 2013-05-23 12:10:28 +02:00
unbit 66be54e6a7 Merge pull request #293 from prymitive/cron_stats
cron harakiri and stats
2013-05-23 03:46:24 -07:00
Łukasz Mierzwa 62c85cc2eb cron harakiri and stats 2013-05-23 12:25:02 +02:00
Unbit 1ae05a9ebc avoid loading pypy when python is already loaded 2013-05-23 12:02:35 +02:00
unbit 3457c70f30 Merge pull request #292 from prymitive/unique_crons
unique crons, fixes #227
2013-05-23 02:28:48 -07:00
Łukasz Mierzwa c1ec9126da unique crons, fixes #227 2013-05-23 11:09:56 +02:00
Unbit 398da2fac7 added 'harakiri' routing action 2013-05-23 08:52:19 +02:00
Unbit 47f33d6346 added --print-sym 2013-05-23 08:46:01 +02:00
Unbit 2cad82d537 removed support for SLOW pypy cpyext 2013-05-23 07:48:19 +02:00
Unbit 8d06d78537 preliminary support for GNU HURD 2013-05-23 07:43:01 +00:00
Unbit b61be000de added support for non-file object in pypy wsgi.file_wrapper 2013-05-23 07:03:41 +02:00
Unbit 9ca6de6e7a fixed #291 2013-05-23 06:51:59 +02:00
unbit 5c03c25e96 Merge pull request #237 from prymitive/cgroup_perms
allow setting cgroup dir mode
2013-05-22 05:23:42 -07:00
Roberta Giordano 23843163ad right fix for pipeline requests 2013-05-22 07:41:18 +02:00
Roberta Giordano 8b07fbbedc honour read() method if original file_wrapper object is not a file 2013-05-22 07:16:34 +02:00
Unbit 5bf55220d4 fixed python3 stdout/stderr line buffering 2013-05-21 14:19:33 +02:00
Unbit 0e1de3d6e8 added __name__ and sys.argv[0] in pypy setup script 2013-05-21 00:37:02 +02:00
Unbit 3a7ba3675b better sanity check for http requests 2013-05-20 23:44:05 +02:00
Unbit 5c0deb5bdb correctly handle pep333 exc_info in pypy 2013-05-20 23:31:14 +02:00
Unbit 50dcbc2b01 improved sendfile() on pypy 2013-05-20 23:21:08 +02:00
Unbit 90d72f7843 completed pep3333 vars for pypy 2013-05-20 21:35:02 +02:00
Unbit 90ee59c70d try to automatically set pypy home during compilation 2013-05-20 21:05:41 +02:00
Unbit 59eda11c1b Merge branch 'master' of https://github.com/unbit/uwsgi 2013-05-20 18:58:21 +02:00
Unbit 78684a424f support for http keepalive for request with body 2013-05-20 14:27:50 +02:00
unbit 4a936dda6e Merge pull request #289 from edevil/DropInvalid
Drop obvious invalid requests.
2013-05-20 03:04:14 -07:00
Andre Cruz 094d4b99a4 Drop obvious invalid requests. 2013-05-20 10:44:35 +01:00
Unbit 382268308e improved PYTHONPATH management 2013-05-19 23:40:49 +02:00
Unbit 97315d27b9 added osx support to pypy plugin 2013-05-19 23:33:49 +02:00
Unbit 26ae573b72 added cache_get,cache_update and cache_del to pypy 2013-05-19 22:40:47 +02:00
Unbit 803c44d783 added pypy management of .wsgi files and pythonpath manipulation 2013-05-19 22:33:42 +02:00
Unbit 90f3f1037a fixed a leak in uwsgi_get_app_id 2013-05-19 12:01:04 +02:00
Unbit ce39a751d9 improved uwsgi_get_app_id 2013-05-19 12:00:12 +02:00
unbit ceebf7d32d Merge pull request #288 from alex/pypy-cleanups
Some cleanups for the PyPy plugin:
2013-05-18 22:54:53 -07:00
Unbit 8da59bf0ac better __main__ setup in pypy 2013-05-19 07:52:31 +02:00
Unbit d25979502a better auto-detection of pypy paths 2013-05-19 07:45:21 +02:00
Unbit 549bc3bf9f added --pypy-eval --pypy-eval-post-fork --pypy-eval-exec --pypy-eval-exec-post-fork 2013-05-19 07:17:22 +02:00
Alex Gaynor 22b2f325e0 removed a method with a nonsense implementation 2013-05-18 22:09:24 -07:00
Alex Gaynor 6615d1b90c Catch a more precise error 2013-05-18 22:06:36 -07:00
Alex Gaynor 8f045c4254 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-05-18 22:06:04 -07:00
Alex Gaynor a4434349e5 whoops, a few small fixse 2013-05-18 22:03:55 -07:00
Unbit 01272be25f automatically detect pypy in setup.py 2013-05-19 07:02:05 +02:00
Alex Gaynor be0beed403 Some cleanups for the PyPy plugin:
a) pep8 and such
b) Made classes be newstyle
c) Made the classes be created once, not once per request
2013-05-18 21:59:37 -07:00
Unbit 453d2abed5 another micro optimization for pypy 2013-05-19 06:52:01 +02:00
Unbit 57e9ccbef0 added uwsgi.opt to pypy 2013-05-19 06:33:57 +02:00
Unbit 989124772b added wsgi.file_wrapper and improved import in pypy 2013-05-19 06:20:02 +02:00
Unbit 72400e4b91 completed wsgi.input for pypy 2013-05-19 05:33:53 +02:00
Unbit 900cba29a7 fixed python3 pyargv 2013-05-19 04:55:52 +02:00
Unbit f177a65c1e added uwsgi.add_file_monitor to pypy 2013-05-18 20:08:50 +02:00
Unbit b6baf9016d Merge branch 'master' of github.com:unbit/uwsgi 2013-05-18 20:02:37 +02:00
Unbit 86ac6e8044 implemented uwsgi.add_timer for pypy 2013-05-18 20:01:18 +02:00
unbit 66d8fb95db Merge pull request #286 from alex/patch-1
Fixed a clear typo.
2013-05-18 10:55:50 -07:00
Unbit 22da8d9ba2 optimized pypy environ helper 2013-05-18 19:45:18 +02:00
Alex Gaynor 819e9c1b16 Fixed a clear typo.
Only call writer once when the result of a WSGI application is a string.
2013-05-18 11:23:01 -06:00
Unbit dd4b2e8bc2 fixed a typo 2013-05-18 18:29:16 +02:00
Unbit e2f7ac2017 added --mule-msg-size 2013-05-18 18:28:50 +02:00
Unbit 31b5cf6926 fixed mule_msg 2013-05-18 17:52:23 +02:00
Unbit 25fe3035c2 fixed SCRIPT_NAME handling in python 2013-05-18 17:27:51 +02:00
Unbit 0cf56823cd added uwsgi.cache_get to pypy 2013-05-18 15:45:53 +02:00
Unbit c2f36968c3 trying to understand why multirheading is flaky on pypy 2013-05-18 12:17:43 +02:00
Unbit a508c7f53e added signal handling to pypy 2013-05-18 09:59:06 +02:00
Unbit 48de68031d more pypy implementations 2013-05-18 09:20:55 +02:00
Unbit 81ef85af82 added xmlrpc wrapper 2013-05-17 16:42:45 +02:00
Unbit 16b65d7dbe uwsgi RPC http wrapper 2013-05-17 15:45:43 +02:00
Unbit 5a98e6511b prepare for pypy multithreading 2013-05-17 14:28:42 +02:00
unbit 2418f08e22 Update README 2013-05-16 23:31:23 +03:00
Unbit 80a821bc20 updated pypy README 2013-05-16 18:09:36 +02:00
Unbit 378f78bd87 removed uwsgi.py 2013-05-16 18:03:35 +02:00
Unbit f010591e19 more WSGI vars 2013-05-16 17:58:15 +02:00
Unbit 5274abdcca fixed pypy environ 2013-05-16 17:30:29 +02:00
Unbit 48f9e8c5c8 improved PyPy plugin 2013-05-16 16:29:13 +02:00
unbit 5c02117fde Merge pull request #285 from fijal/master
A sketch for a PyPy plugin
2013-05-15 05:21:57 -07:00
Maciej Fijalkowski bc56a188f8 Add a copyright info 2013-05-15 14:18:47 +02:00
Maciej Fijalkowski b6df1b22ab flush the pypy debug file 2013-05-14 23:55:27 +02:00
Maciej Fijalkowski 0fbf2dd5bb Progress - now example wsgi runs 2013-05-14 23:32:05 +02:00
Unbit 38c126d11a fixed file action status 2013-05-14 16:49:22 +02:00
Unbit 7dff602e5e try to fix retry engine 2013-05-14 16:43:44 +02:00
Maciej Fijalkowski e401f32815 This was indeed temporary 2013-05-14 15:19:04 +02:00
Maciej Fijalkowski 12e94b70a7 Merge github.com:fijal/uwsgi 2013-05-14 15:06:48 +02:00
Maciej Fijalkowski 884de3959c initial checkin of pypy plugin 2013-05-14 15:04:17 +02:00
Unbit fe12325e50 fixed goto and pc in error and final routing 2013-05-14 12:19:17 +02:00
Unbit bea86f3f79 fixed a typo 2013-05-13 18:55:48 +02:00
unbit 7a5f3667da Merge pull request #280 from xrmx/warn-ini
core: print a warning if the configuration section can't be read
2013-05-13 07:35:20 -07:00
Riccardo Magliocchetti 0813788c98 core: print a warning if the configuration section can't be read
Fixes #278
2013-05-13 16:21:30 +02:00
Unbit b1ca73e7f0 added file-next action 2013-05-13 07:33:05 +02:00
Unbit ebf9e9b1a3 added ignore_body flag 2013-05-13 07:19:12 +02:00
Unbit b0abab7a1d fixed #277 2013-05-12 22:57:07 +02:00
Unbit 995bb493df preliminary implementation of error routing 2013-05-12 22:48:10 +02:00
Unbit 1b2375fc84 added error routes 2013-05-12 18:02:33 +02:00
Unbit b7315bcb5a added "file" routing action 2013-05-12 17:36:40 +02:00
Łukasz Mierzwa 7c4caef5e7 allow setting cgroup dir mode 2013-04-18 13:13:15 +02:00
102 changed files with 4947 additions and 493 deletions
+2
View File
@@ -2,6 +2,8 @@
*.py[co]
*.class
*.jar
*~
*.so
/uwsgi
/uwsgibuild.*
-4
View File
@@ -1,4 +0,0 @@
syntax: glob
*.o
*.pyc
-58
View File
@@ -1,58 +0,0 @@
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
3c70927335856883283fe4db448e092cecc0ccdb 1.0
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
620e0cb6ccdb0ce27561b4240cb3a0ef4c3527fd 1.3
+1 -1
View File
@@ -16,7 +16,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
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
as_shared_library = false
locking = auto
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = psgi,coroae
inherit = base
+1
View File
@@ -1,3 +1,4 @@
[uwsgi]
main_plugin = python,gevent
inherit = base
debug = false
+61
View File
@@ -0,0 +1,61 @@
"""
Greenlets support
simply --pypy-exec this file to enable PyPy's greenlet mode
Example:
uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi werkzeug.testapp:test_app --pypy-exec contrib/pypy/uwsgi_pypy_greenlets.py --async 8
"""
import greenlet
uwsgi_pypy_greenlets = {}
def uwsgi_pypy_greenlet_wrapper():
lib.async_schedule_to_req_green()
@ffi.callback("void()")
def uwsgi_pypy_greenlet_schedule():
id = lib.uwsgi.wsgi_req.async_id
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
# generate a new greenlet
if not lib.uwsgi.wsgi_req.suspended:
uwsgi_pypy_greenlets[id] = greenlet.greenlet(uwsgi_pypy_greenlet_wrapper)
lib.uwsgi.wsgi_req.suspended = 1
# this is called in the main stack
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
# let's switch
uwsgi_pypy_greenlets[id].switch()
# back to the main stack
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(ffi.NULL)
@ffi.callback("void(struct wsgi_request *)")
def uwsgi_pypy_greenlet_switch(wsgi_req):
id = wsgi_req.async_id
modifier1 = wsgi_req.uh.modifier1;
# this is called in the current greenlet
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(wsgi_req)
uwsgi_pypy_main_greenlet.switch()
# back to the greenlet
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(wsgi_req)
# update current running greenlet
lib.uwsgi.wsgi_req = wsgi_req
if lib.uwsgi.async <= 1:
raise Exception("pypy greenlets require async mode !!!")
lib.uwsgi.schedule_to_main = uwsgi_pypy_greenlet_switch
lib.uwsgi.schedule_to_req = uwsgi_pypy_greenlet_schedule
uwsgi_pypy_main_greenlet = greenlet.getcurrent()
+15
View File
@@ -0,0 +1,15 @@
# uWSGI - Emperor
#
description "uWSGI Emperor"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
env VASSALS=/etc/uwsgi
exec $BINPATH --emperor $VASSALS --logto $LOGTO
+2 -3
View File
@@ -11,7 +11,6 @@ respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --no-orphans avoid workers without master
# --die-on-term could be a good idea
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
# --die-on-term is upstart friendly
exec $BINPATH --die-on-term --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
+9
View File
@@ -206,7 +206,11 @@ int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
}
static int async_wait_fd_read(int fd, int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_read(wsgi_req, fd, timeout)) {
return -1;
}
@@ -222,6 +226,8 @@ static int async_wait_fd_read(int fd, int timeout) {
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
wsgi_req->async_ready_fd = 0;
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now() + timeout, wsgi_req);
}
@@ -265,6 +271,9 @@ int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
static int async_wait_fd_write(int fd, int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_write(wsgi_req, fd, timeout)) {
return -1;
}
+46 -1
View File
@@ -171,6 +171,41 @@ static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *da
}
}
static void uwsgi_cache_add_items(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uwsgi.add_cache_item;
while(usl) {
char *space = strchr(usl->value, ' ');
char *key = usl->value;
uint16_t key_len = usl->len;
if (space) {
// need to skip ?
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
goto next;
}
key = space+1;
key_len = usl->len - ((space-usl->value)+1);
}
char *value = strchr(key, '=');
if (!value) {
uwsgi_log("[cache] unable to store item %s\n", usl->value);
goto next;
}
key_len = value - key;
value++;
uint64_t len = (usl->value + usl->len) - value;
uwsgi_wlock(uc->lock);
if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) {
uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
else {
uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
uwsgi_rwunlock(uc->lock);
next:
usl = usl->next;
}
}
static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uwsgi.load_file_in_cache;
@@ -194,9 +229,15 @@ static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) {
uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
else {
uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
uwsgi_rwunlock(uc->lock);
free(value);
}
else {
uwsgi_log("[cache-error] unable to read file \"%.*s\"\n", key_len, key);
}
next:
usl = usl->next;
}
@@ -335,6 +376,8 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
uwsgi_cache_load_files(uc);
uwsgi_cache_add_items(uc);
}
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
@@ -1089,7 +1132,6 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
// defaults
uc->blocks = uc->max_items;
uc->blocksize = UMAX16;
uc->max_item_size = uc->blocksize;
uc->keysize = 2048;
uc->hashsize = UMAX16;
uc->hash = uwsgi_hash_algo_get("djb33x");
@@ -1097,6 +1139,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
// customize
if (c_blocksize) uc->blocksize = uwsgi_n64(c_blocksize);
if (!uc->blocksize) { uwsgi_log("invalid cache blocksize for \"%s\"\n", uc->name); exit(1); }
// set the true max size of an item
uc->max_item_size = uc->blocksize;
if (c_blocks) uc->blocks = uwsgi_n64(c_blocks);
if (!uc->blocks) { uwsgi_log("invalid cache blocks for \"%s\"\n", uc->name); exit(1); }
if (c_hash) uc->hash = uwsgi_hash_algo_get(c_hash);
+159
View File
@@ -0,0 +1,159 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
Chunked input implementation
--chunked-input-limit <bytes> (default 1MB)
--chunked-input-timeout <s> (default --socket-timeout)
chunk = uwsgi.chunked_read([timeout])
timeout = -1 (wait forever)
timeout = 0 (default)
*/
static ssize_t uwsgi_chunked_input_recv(struct wsgi_request *wsgi_req, int timeout, int nb) {
if (timeout == 0) timeout = uwsgi.chunked_input_timeout;
if (timeout == 0) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
int ret = -1;
for(;;) {
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
if (rlen > 0) return rlen;
if (rlen == 0) return -1;
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
if (nb) return -1;
goto wait;
}
uwsgi_error("uwsgi_chunked_input_recv()");
return -1;
}
wait:
ret = uwsgi.wait_read_hook(wsgi_req->fd, timeout);
if (ret > 0) {
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
if (rlen > 0) return rlen;
if (rlen <= 0) return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_chunked_input_recv()");
}
return -1;
}
return -1;
}
static ssize_t uwsgi_chunked_readline(struct wsgi_request *wsgi_req) {
size_t i;
int found = 0;
for(i=0;i<wsgi_req->chunked_input_buf->pos;i++) {
if (found) {
if (wsgi_req->chunked_input_buf->buf[i] == '\n') {
// strtoul will stop at \r
size_t num = strtoul(wsgi_req->chunked_input_buf->buf, NULL, 16);
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, i+1)) return -1;
return num;
}
return -1;
}
if ((wsgi_req->chunked_input_buf->buf[i] >= '0' && wsgi_req->chunked_input_buf->buf[i] <= '9') ||
(wsgi_req->chunked_input_buf->buf[i] >= 'a' && wsgi_req->chunked_input_buf->buf[i] <= 'z') ||
(wsgi_req->chunked_input_buf->buf[i] >= 'A' && wsgi_req->chunked_input_buf->buf[i] <= 'Z')) continue;
if (wsgi_req->chunked_input_buf->buf[i] == '\r') { found = 1; continue; }
return -1;
}
return -2;
}
/*
0 -> waiting for \r\n
1 -> waiting for whole body
*/
char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) {
char *ret;
if (!wsgi_req->chunked_input_buf) {
wsgi_req->chunked_input_buf = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->chunked_input_buf->limit = uwsgi.chunked_input_limit;
}
// the whole chunk stream has been consumed
if (wsgi_req->chunked_input_complete) {
*len = 0;
return wsgi_req->chunked_input_buf->buf;
}
for(;;) {
if (wsgi_req->chunked_input_need > 0 || wsgi_req->chunked_input_buf->pos == 0) {
if (uwsgi_buffer_fix(wsgi_req->chunked_input_buf, uwsgi.page_size)) return NULL;
ssize_t rlen = uwsgi_chunked_input_recv(wsgi_req, timeout, nb);
if (rlen <= 0) return NULL;
// update buffer position
wsgi_req->chunked_input_buf->pos += rlen;
if (wsgi_req->chunked_input_need > 0) {
if ((size_t)rlen > wsgi_req->chunked_input_need) {
wsgi_req->chunked_input_need = 0;
}
else {
wsgi_req->chunked_input_need -= rlen;
}
}
}
if (wsgi_req->chunked_input_need > 0) continue;
// ok we have a frame, let's parse it
if (wsgi_req->chunked_input_buf->pos > 0) {
switch(wsgi_req->chunked_input_parser_status) {
case 0:
wsgi_req->chunked_input_chunk_len = uwsgi_chunked_readline(wsgi_req);
if (wsgi_req->chunked_input_chunk_len == -2) {
break;
}
else if (wsgi_req->chunked_input_chunk_len < 0) {
return NULL;
}
else if (wsgi_req->chunked_input_chunk_len == 0) {
*len = 0;
wsgi_req->chunked_input_complete = 1;
return wsgi_req->chunked_input_buf->buf;
}
// if here the buffer has been already decapitated
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
wsgi_req->chunked_input_parser_status = 1;
break;
}
*len = wsgi_req->chunked_input_chunk_len;
ret = wsgi_req->chunked_input_buf->buf;
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
return ret;
case 1:
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
break;
}
*len = wsgi_req->chunked_input_chunk_len;
ret = wsgi_req->chunked_input_buf->buf;
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
wsgi_req->chunked_input_parser_status = 0;
return ret;
}
}
}
}
+1
View File
@@ -0,0 +1 @@
int main() {}
+160 -12
View File
@@ -27,13 +27,22 @@ struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
exit(1);
}
uc->command = crontab + i;
uc->pid = -1;
return uc;
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
uwsgi_cron_add(value);
}
void uwsgi_opt_add_unique_cron(char *opt, char *value, void *foobar) {
struct uwsgi_cron *uc = uwsgi_cron_add(value);
uc->unique = 1;
}
#ifdef UWSGI_SSL
void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
@@ -45,9 +54,140 @@ void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
}
void uwsgi_opt_add_unique_legion_cron(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
exit(1);
}
char *legion = uwsgi_concat2n(value, space-value, "", 0);
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
uc->unique = 1;
}
#endif
void uwsgi_opt_add_cron2(char *opt, char *value, void *foobar) {
char *c_minute = NULL;
char *c_hour = NULL;
char *c_day = NULL;
char *c_month = NULL;
char *c_week = NULL;
char *c_unique = NULL;
char *c_harakiri = NULL;
char *c_legion = NULL;
char *c_command = value;
char *space = strchr(value, ' ');
if (space) {
if (uwsgi_str_contains(value, space - value, '=')) {
// --cron2 key=val command
*space = 0;
c_command = space + 1;
}
// no point in parsing key=val list if there is none
if (uwsgi_kvlist_parse(value, strlen(value), ',', '=',
"minute", &c_minute,
"hour", &c_hour,
"day", &c_day,
"month", &c_month,
"week", &c_week,
"unique", &c_unique,
"harakiri", &c_harakiri,
"legion", &c_legion,
NULL)) {
uwsgi_log("unable to parse cron definition: %s\n", value);
exit(1);
}
}
else {
if (uwsgi_str_contains(value, strlen(value), '=')) {
// --cron2 key=val
uwsgi_log("unable to parse cron definition: %s\n", value);
exit(1);
}
}
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
uc->command = c_command;
if (!uc->command) {
uwsgi_log("[uwsgi-cron] invalid command in cron definition: %s\n", value);
exit(1);
}
// defaults
uc->minute = -1;
uc->hour = -1;
uc->day = -1;
uc->month = -1;
uc->week = -1;
uc->unique = 0;
uc->mercy = 0;
uc->harakiri = 0;
uc->pid = -1;
#ifdef UWSGI_SSL
uc->legion = c_legion;
#endif
if (c_minute)
uc->minute = atoi(c_minute);
if (c_hour)
uc->hour = atoi(c_hour);
if (c_day)
uc->day = atoi(c_day);
if (c_month)
uc->month = atoi(c_month);
if (c_week)
uc->week = atoi(c_week);
if (c_unique)
uc->unique = atoi(c_unique);
if (c_harakiri) {
if (atoi(c_harakiri)) {
// harakiri > 0
uc->mercy = atoi(c_harakiri);
}
else {
// harakiri == 0
uc->mercy = -1;
}
}
else if (uwsgi.cron_harakiri) {
uc->harakiri = uwsgi.cron_harakiri;
}
}
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process)
@@ -134,15 +274,16 @@ void uwsgi_manage_command_cron(time_t now) {
#ifdef UWSGI_SSL
// check for legion cron
if (current_cron->legion) {
if (!uwsgi_legion_i_am_the_lord(current_cron->legion)) {
current_cron = current_cron->next;
continue;
}
if (!uwsgi_legion_i_am_the_lord(current_cron->legion))
goto next;
}
#endif
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
// skip unique crons that are still running
if (current_cron->unique && current_cron->pid >= 0)
goto next;
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
if (run_task == 1) {
// date match, run command ?
@@ -153,20 +294,27 @@ void uwsgi_manage_command_cron(time_t now) {
current_cron->func(current_cron, now);
}
else {
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
uwsgi_log_verbose("[uwsgi-cron] running %s\n", current_cron->command);
}
pid_t pid = uwsgi_run_command(current_cron->command, NULL, -1);
if (pid >= 0) {
current_cron->pid = pid;
current_cron->started_at = now;
uwsgi_log_verbose("[uwsgi-cron] running \"%s\" (pid %d)\n", current_cron->command, current_cron->pid);
if (current_cron->mercy) {
//uwsgi_cron->mercy can be negative to inform master that harakiri should be disabled for this cron
if (current_cron->mercy > 0)
current_cron->harakiri = now + current_cron->mercy;
}
else if (uwsgi.cron_harakiri)
current_cron->harakiri = now + uwsgi.cron_harakiri;
}
}
}
current_cron->last_job = now;
}
}
next:
current_cron = current_cron->next;
}
}
+17
View File
@@ -376,7 +376,11 @@ void *event_queue_alloc(int nevents) {
int event_queue_interesting_fd(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
#ifdef PORT_SOURCE_FILE
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
#else
if (pe[id].portev_source == PORT_SOURCE_TIMER) {
#endif
return (long) pe[id].portev_user;
}
@@ -464,7 +468,11 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
}
#ifdef PORT_SOURCE_FILE
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
#else
if (pe.portev_source == PORT_SOURCE_TIMER) {
#endif
*interesting_fd = (long) pe.portev_user;
}
else {
@@ -972,6 +980,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
#ifdef PORT_SOURCE_FILE
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct file_obj fo;
@@ -1032,6 +1041,14 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
}
#else
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
return -1;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#endif
#endif
+6
View File
@@ -91,6 +91,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
char *section_asked = "uwsgi";
char *colon;
int got_section = 0;
if (uwsgi_check_scheme(file)) {
@@ -147,6 +148,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
val = ini_get_key(key);
if (!strcmp(section, section_asked)) {
got_section = 1;
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
@@ -161,6 +163,10 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
if (!got_section) {
uwsgi_log("*** WARNING: Can't find section \"%s\" in INI configuration file %s ***\n", section_asked, file);
}
if (colon) {
colon[0] = ':';
}
+8
View File
@@ -161,10 +161,17 @@ void uwsgi_init_default() {
uwsgi.empty = "";
#ifdef __linux__
uwsgi.cgroup_dir_mode = "0700";
#endif
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
uwsgi_websockets_init();
// 1 MB default limit
uwsgi.chunked_input_limit = 1024*1024;
}
void uwsgi_setup_reload() {
@@ -349,6 +356,7 @@ void uwsgi_setup_workers() {
#ifdef UWSGI_ROUTING
uwsgi_fixup_routes(uwsgi.routes);
uwsgi_fixup_routes(uwsgi.error_routes);
uwsgi_fixup_routes(uwsgi.final_routes);
#endif
+19
View File
@@ -1078,3 +1078,22 @@ void uwsgi_add_safe_fd(int fd) {
uwsgi.safe_fds[uwsgi.safe_fds_cnt] = fd;
uwsgi.safe_fds_cnt++;
}
int uwsgi_is_again() {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
return 1;
}
return 0;
}
void uwsgi_disconnect(struct wsgi_request *wsgi_req) {
if (wsgi_req->socket) {
wsgi_req->socket->proto_close(wsgi_req);
}
wsgi_req->fd_closed = 1;
}
int uwsgi_ready_fd(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_ready_fd) return wsgi_req->async_last_ready_fd;
return -1;
}
+10 -2
View File
@@ -764,10 +764,18 @@ nextlock:
}
void uwsgi_user_lock(int lock_num) {
int uwsgi_user_lock(int lock_num) {
if (lock_num < 0 || lock_num > uwsgi.locks) {
return -1;
}
uwsgi_lock(uwsgi.user_lock[lock_num]);
return 0;
}
void uwsgi_user_unlock(int lock_num) {
int uwsgi_user_unlock(int lock_num) {
if (lock_num < 0 || lock_num > uwsgi.locks) {
return -1;
}
uwsgi_unlock(uwsgi.user_lock[lock_num]);
return 0;
}
+20
View File
@@ -485,6 +485,18 @@ int master_loop(char **argv, char **environ) {
usl = usl->next;
}
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);
// setup cheaper algos (can be stacked)
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
@@ -706,6 +718,7 @@ int master_loop(char **argv, char **environ) {
uwsgi_master_check_gateways_deadline();
uwsgi_master_check_mules_deadline();
uwsgi_master_check_spoolers_deadline();
uwsgi_master_check_crons_deadline();
#ifdef __linux__
#ifdef MADV_MERGEABLE
@@ -768,6 +781,12 @@ int master_loop(char **argv, char **environ) {
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
}
}
touched = uwsgi_check_touches(uwsgi.touch_signal);
if (touched) {
uint8_t signum = atoi(touched);
uwsgi_route_signal(signum);
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
}
}
continue;
@@ -789,6 +808,7 @@ int master_loop(char **argv, char **environ) {
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;
}
+39
View File
@@ -197,6 +197,14 @@ void uwsgi_master_check_mules_deadline() {
uwsgi.mules[i].harakiri = 0;
}
}
// user harakiri
if (uwsgi.mules[i].user_harakiri > 0) {
if (uwsgi.mules[i].user_harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON MULE %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].pid);
kill(uwsgi.mules[i].pid, SIGKILL);
uwsgi.mules[i].user_harakiri = 0;
}
}
}
}
@@ -208,6 +216,11 @@ void uwsgi_master_check_spoolers_deadline() {
kill(uspool->pid, SIGKILL);
uspool->harakiri = 0;
}
if (uspool->user_harakiri > 0 && uspool->user_harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
kill(uspool->pid, SIGKILL);
uspool->user_harakiri = 0;
}
uspool = uspool->next;
}
}
@@ -277,3 +290,29 @@ int uwsgi_worker_is_busy(int wid) {
}
return 0;
}
int uwsgi_master_check_cron_death(int diedpid) {
struct uwsgi_cron *uc = uwsgi.crons;
while (uc) {
if (uc->pid == (pid_t) diedpid) {
uwsgi_log("[uwsgi-cron] command \"%s\" running with pid %d exited after %d second(s)\n", uc->command, uc->pid, uwsgi_now() - uc->started_at);
uc->pid = -1;
uc->started_at = 0;
return -1;
}
uc = uc->next;
}
return 0;
}
void uwsgi_master_check_crons_deadline() {
struct uwsgi_cron *uc = uwsgi.crons;
while (uc) {
if (uc->pid >= 0 && uc->harakiri > 0 && uc->harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON CRON \"%s\" (pid: %d) ***\n", uc->command, uc->pid);
kill(-uc->pid, SIGKILL);
}
uc = uc->next;
}
}
+72 -1
View File
@@ -696,8 +696,17 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
while (ud) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyval_comma(us, "cmd", ud->command))
// allocate 2x the size of original command
// in case we need to escape all chars
char *cmd = uwsgi_malloc(strlen(ud->command)*2);
escape_json(ud->command, strlen(ud->command), cmd);
if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
free(cmd);
goto end;
}
free(cmd);
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) (ud->pid < 0) ? 0 : ud->pid))
goto end;
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns))
@@ -1079,6 +1088,68 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
}
struct uwsgi_cron *ucron = uwsgi.crons;
if (ucron) {
if (uwsgi_stats_comma(us))
goto end;
if (uwsgi_stats_key(us, "crons"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
while (ucron) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyslong_comma(us, "minute", (long long) ucron->minute))
goto end;
if (uwsgi_stats_keyslong_comma(us, "hour", (long long) ucron->hour))
goto end;
if (uwsgi_stats_keyslong_comma(us, "day", (long long) ucron->day))
goto end;
if (uwsgi_stats_keyslong_comma(us, "month", (long long) ucron->month))
goto end;
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
goto end;
char *cmd = uwsgi_malloc(strlen(ucron->command)*2);
escape_json(ucron->command, strlen(ucron->command), cmd);
if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
free(cmd);
goto end;
}
free(cmd);
if (uwsgi_stats_keylong_comma(us, "unique", (unsigned long long) ucron->unique))
goto end;
#ifdef UWSGI_SSL
if (uwsgi_stats_keyval_comma(us, "legion", ucron->legion ? ucron->legion : ""))
goto end;
#endif
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) ucron->pid))
goto end;
if (uwsgi_stats_keylong(us, "started_at", (unsigned long long) ucron->started_at))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
ucron = ucron->next;
if (ucron) {
if (uwsgi_stats_comma(us))
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end;
}
#ifdef UWSGI_SSL
struct uwsgi_legion *legion = NULL;
if (uwsgi.legions) {
+3 -3
View File
@@ -416,12 +416,12 @@ void uwsgi_setup_mules_and_farms() {
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
create_msg_pipe(uwsgi.shared->mule_queue_pipe, uwsgi.mule_msg_size);
for (i = 0; i < uwsgi.mules_cnt; i++) {
// create the socket pipe
create_signal_pipe(uwsgi.mules[i].signal_pipe);
create_signal_pipe(uwsgi.mules[i].queue_pipe);
create_msg_pipe(uwsgi.mules[i].queue_pipe, uwsgi.mule_msg_size);
uwsgi.mules[i].id = i + 1;
@@ -451,7 +451,7 @@ void uwsgi_setup_mules_and_farms() {
// create the socket pipe
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_signal_pipe(uwsgi.farms[i].queue_pipe);
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
char *p = strtok(mules_list, ",");
while (p != NULL) {
+150 -1
View File
@@ -58,6 +58,39 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
return 0;
}
/*
pipe offload engine:
fd -> the file descriptor to read from
len -> amount of data to transfer
*/
static int u_offload_pipe_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (uor->fd < 0 || !uor->len) {
return -1;
}
return 0;
}
/*
memory offload engine:
buf -> pointer to the memory to transfer (memory is freed at the end)
len -> amount of data to transfer
*/
static int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->buf || !uor->len) {
return -1;
}
return 0;
}
/*
transfer offload engine:
@@ -66,7 +99,7 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
*/
int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
static int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->name) {
return -1;
@@ -240,6 +273,39 @@ struct uwsgi_thread *uwsgi_offload_thread_start() {
return uwsgi_thread_new(uwsgi_offload_loop);
}
/*
offload memory transfer
uor->len -> the size of the memory chunk
uor->buf -> the memory to transfer
uor->written -> written bytes
status: none
*/
static int u_offload_memory_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
if (fd == -1) {
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
return 0;
}
ssize_t rlen = write(uor->s, uor->buf + uor->written, uor->len - uor->written);
if (rlen > 0) {
uor->written += rlen;
if (uor->written >= uor->len) {
return -1;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_memory_do()");
}
return -1;
}
/*
the offload task starts after having acquired the file fd
@@ -293,6 +359,71 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
}
/*
pipe offloading
status:
0 -> waiting for data on fd
1 -> waiting for write to s
*/
static int u_offload_pipe_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
ssize_t rlen;
// setup
if (fd == -1) {
event_queue_add_fd_read(ut->queue, uor->fd);
return 0;
}
switch(uor->status) {
// read event from fd
case 0:
if (!uor->buf) {
uor->buf = uwsgi_malloc(4096);
}
rlen = read(uor->fd, uor->buf, 4096);
if (rlen > 0) {
uor->to_write = rlen;
uor->pos = 0;
if (event_queue_del_fd(ut->queue, uor->fd, event_queue_read())) return -1;
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
uor->status = 1;
return 0;
}
if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_pipe_do() -> read()");
}
return -1;
// write event on s
case 1:
rlen = write(uor->s, uor->buf + uor->pos, uor->to_write);
if (rlen > 0) {
uor->to_write -= rlen;
uor->pos += rlen;
if (uor->to_write == 0) {
if (event_queue_del_fd(ut->queue, uor->s, event_queue_write())) return -1;
if (event_queue_add_fd_read(ut->queue, uor->fd)) return -1;
uor->status = 0;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_pipe_do() -> write()");
}
return -1;
default:
break;
}
return -1;
}
/*
the offload task starts soon after the call to connect()
@@ -490,6 +621,8 @@ struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *name, int (*pre
void uwsgi_offload_engines_register_all() {
uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do);
uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do);
uwsgi.offload_engine_memory = uwsgi_offload_register_engine("memory", u_offload_memory_prepare, u_offload_memory_do);
uwsgi.offload_engine_pipe = uwsgi_offload_register_engine("pipe", u_offload_pipe_prepare, u_offload_pipe_do);
}
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
@@ -507,3 +640,19 @@ int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socketname
uor.ubuf = ubuf;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_memory, &uor, wsgi_req, 1);
uor.buf = buf;
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
int uwsgi_offload_request_pipe_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_pipe, &uor, wsgi_req, 1);
uor.fd = fd;
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
+2 -2
View File
@@ -478,9 +478,9 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
int upload_progress_fd = -1;
char *upload_progress_filename = NULL;
wsgi_req->post_file = tmpfile();
wsgi_req->post_file = uwsgi_tmpfile();
if (!wsgi_req->post_file) {
uwsgi_error("uwsgi_postbuffer_do_in_disk()/tmpfile()");
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
return -1;
}
+175 -9
View File
@@ -173,15 +173,27 @@ int uwsgi_apply_routes_do(struct uwsgi_route *routes, struct wsgi_request *wsgi_
char *orig_subject = subject;
uint16_t orig_subject_len = subject_len;
uint32_t *r_goto = &wsgi_req->route_goto;
uint32_t *r_pc = &wsgi_req->route_pc;
if (routes == uwsgi.error_routes) {
r_goto = &wsgi_req->error_route_goto;
r_pc = &wsgi_req->error_route_pc;
}
else if (routes == uwsgi.final_routes) {
r_goto = &wsgi_req->final_route_goto;
r_pc = &wsgi_req->final_route_pc;
}
while (routes) {
if (routes->label) goto next;
if (wsgi_req->route_goto > 0 && wsgi_req->route_pc < wsgi_req->route_goto) {
if (*r_goto > 0 && *r_pc < *r_goto) {
goto next;
}
wsgi_req->route_goto = 0;
*r_goto = 0;
if (!routes->if_func) {
// could be a "run"
@@ -243,7 +255,7 @@ next:
subject = orig_subject;
subject_len = orig_subject_len;
routes = routes->next;
if (routes) wsgi_req->route_pc++;
if (routes) *r_pc = *r_pc+1;
}
return UWSGI_ROUTE_CONTINUE;
@@ -282,6 +294,18 @@ void uwsgi_apply_final_routes(struct wsgi_request *wsgi_req) {
uwsgi_apply_routes_do(uwsgi.final_routes, wsgi_req, NULL, 0);
}
int uwsgi_apply_error_routes(struct wsgi_request *wsgi_req) {
if (!uwsgi.error_routes) return 0;
// do not forget to check it !!!
if (wsgi_req->is_error_routing) return 0;
wsgi_req->is_error_routing = 1;
return uwsgi_apply_routes_do(uwsgi.error_routes, wsgi_req, NULL, 0);
}
static void *uwsgi_route_get_condition_func(char *name) {
struct uwsgi_route_condition *urc = uwsgi.route_conditions;
@@ -294,6 +318,14 @@ static void *uwsgi_route_get_condition_func(char *name) {
return NULL;
}
static int uwsgi_route_condition_status(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
if (wsgi_req->status == ur->if_status) {
return 1;
}
return 0;
}
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
char *space = NULL;
@@ -302,6 +334,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
if (!uwsgi_starts_with(opt, strlen(opt), "final", 5)) {
ur = uwsgi.final_routes;
}
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
ur = uwsgi.error_routes;
}
uint64_t pos = 0;
while(ur) {
old_ur = ur;
@@ -316,6 +351,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
if (!uwsgi_starts_with(opt, strlen(opt), "final", 5)) {
uwsgi.final_routes = ur;
}
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
uwsgi.error_routes = ur;
}
else {
uwsgi.routes = ur;
}
@@ -364,6 +402,11 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
exit(1);
}
}
else if (!strcmp(foobar, "status")) {
ur->if_status = atoi(ur->orig_route);
foobar = ur->orig_route;
ur->if_func = uwsgi_route_condition_status;
}
else if (!strcmp(foobar, "http_host")) {
ur->subject = offsetof(struct wsgi_request, host);
@@ -515,6 +558,21 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
return 0;
}
// harakiri router
static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
if (route->custom > 0) {
set_user_harakiri(route->custom);
}
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_harakiri(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_harakiri_func;
ur->custom = atoi(arg);
return 0;
}
// flush response
static int transform_flush(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
// avoid loops !!!
@@ -628,28 +686,37 @@ static int uwsgi_router_goto_func(struct wsgi_request *wsgi_req, struct uwsgi_ro
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uint32_t *r_goto = &wsgi_req->route_goto;
uint32_t *r_pc = &wsgi_req->route_pc;
// find the label
struct uwsgi_route *routes = uwsgi.routes;
if (wsgi_req->is_final_routing) {
if (wsgi_req->is_error_routing) {
routes = uwsgi.error_routes;
r_goto = &wsgi_req->error_route_goto;
r_pc = &wsgi_req->error_route_pc;
}
else if (wsgi_req->is_final_routing) {
routes = uwsgi.final_routes;
r_goto = &wsgi_req->final_route_goto;
r_pc = &wsgi_req->final_route_pc;
}
while(routes) {
if (!routes->label) goto next;
if (!uwsgi_strncmp(routes->label, routes->label_len, ub->buf, ub->pos)) {
wsgi_req->route_goto = routes->pos;
*r_goto = routes->pos;
goto found;
}
next:
routes = routes->next;
}
wsgi_req->route_goto = ur->custom;
*r_goto = ur->custom;
found:
uwsgi_buffer_destroy(ub);
if (wsgi_req->route_goto <= wsgi_req->route_pc) {
wsgi_req->route_goto = 0;
if (*r_goto <= *r_pc) {
*r_goto = 0;
uwsgi_log("[uwsgi-route] ERROR \"goto\" instruction can only jump forward (check your label !!!)\n");
return UWSGI_ROUTE_BREAK;
}
@@ -822,6 +889,77 @@ static int uwsgi_router_setscriptname(struct uwsgi_route *ur, char *arg) {
return 0;
}
// setmethod route
static int uwsgi_router_setmethod_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);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "REQUEST_METHOD", 14, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->method = ptr;
wsgi_req->method_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setmethod(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setmethod_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// seturi route
static int uwsgi_router_seturi_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);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "REQUEST_URI", 11, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->uri = ptr;
wsgi_req->uri_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_seturi(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_seturi_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setpathinfo route
static int uwsgi_router_setpathinfo_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);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "PATH_INFO", 9, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->path_info = ptr;
wsgi_req->path_info_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setpathinfo(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setpathinfo_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setuser route
static int uwsgi_router_setuser_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -1322,6 +1460,11 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
*vallen = strlen(ret);
}
else if (!uwsgi_strncmp(key, keylen, "lq", 2)) {
ret = uwsgi_num2str(uwsgi.shared->load);
*vallen = strlen(ret);
}
return ret;
}
@@ -1447,12 +1590,17 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("sethome", uwsgi_router_sethome);
uwsgi_register_router("setfile", uwsgi_router_setfile);
uwsgi_register_router("setscriptname", uwsgi_router_setscriptname);
uwsgi_register_router("setmethod", uwsgi_router_setmethod);
uwsgi_register_router("seturi", uwsgi_router_seturi);
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
uwsgi_register_router("alarm", uwsgi_router_alarm);
uwsgi_register_router("flush", uwsgi_router_flush);
uwsgi_register_router("fixcl", uwsgi_router_fixcl);
uwsgi_register_router("harakiri", uwsgi_router_harakiri);
uwsgi_register_route_condition("exists", uwsgi_route_condition_exists);
uwsgi_register_route_condition("isfile", uwsgi_route_condition_isfile);
uwsgi_register_route_condition("isdir", uwsgi_route_condition_isdir);
@@ -1552,7 +1700,7 @@ struct uwsgi_route_condition *uwsgi_register_route_condition(char *name, int (*f
void uwsgi_routing_dump() {
struct uwsgi_route *routes = uwsgi.routes;
if (!routes) return;
if (!routes) goto next;
uwsgi_log("*** dumping internal routing table ***\n");
while(routes) {
if (routes->label) {
@@ -1567,6 +1715,24 @@ void uwsgi_routing_dump() {
routes = routes->next;
}
uwsgi_log("*** end of the internal routing table ***\n");
next:
routes = uwsgi.error_routes;
if (!routes) goto next2;
uwsgi_log("*** dumping internal error routing table ***\n");
while(routes) {
if (routes->label) {
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
}
else if (!routes->subject_str && !routes->if_func) {
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
}
else {
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
}
routes = routes->next;
}
uwsgi_log("*** end of the internal error routing table ***\n");
next2:
routes = uwsgi.final_routes;
if (!routes) return;
uwsgi_log("*** dumping internal final routing table ***\n");
+36
View File
@@ -37,3 +37,39 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
#endif
}
/*
simple non blocking sendfile implementation
(generally used as fallback)
*/
int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
wsgi_req->write_pos = 0;
for(;;) {
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_simple_sendfile()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) {
wsgi_req->write_errors++;
return -1;
}
if (ret == 0) {
uwsgi_log("uwsgi_simple_sendfile() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
return 0;
}
+4 -1
View File
@@ -99,7 +99,10 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
struct uwsgi_signal_entry *use = NULL;
if (!uwsgi.master_process) return -1;
if (!uwsgi.master_process) {
uwsgi_log("you cannot register signals without a master\n");
return -1;
}
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
uwsgi_log("only the master and the workers can register signal handlers\n");
+3
View File
@@ -1552,6 +1552,9 @@ void uwsgi_setup_shared_sockets() {
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
shared_sock->family = AF_UNIX;
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
if (uwsgi.chown_socket) {
uwsgi_chown(shared_sock->name, uwsgi.chown_socket);
}
}
else {
#ifdef AF_INET6
+11 -10
View File
@@ -2,9 +2,9 @@
extern struct uwsgi_server uwsgi;
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t filename_len, struct stat *st) {
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st) {
// check for filename size
if (filename_len + 4 > PATH_MAX) return 0;
if (*filename_len + 4 > PATH_MAX) return 0;
// check for supported encodings
if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0;
@@ -14,7 +14,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
// check for dirs/prefix
struct uwsgi_string_list *usl = uwsgi.static_gzip_dir;
while(usl) {
if (!uwsgi_starts_with(filename, filename_len, usl->value, usl->len)) {
if (!uwsgi_starts_with(filename, *filename_len, usl->value, usl->len)) {
goto gzip;
}
usl = usl->next;
@@ -23,7 +23,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
// check for ext/suffix
usl = uwsgi.static_gzip_ext;
while(usl) {
if (!uwsgi_strncmp(filename + (filename_len - usl->len), usl->len, usl->value, usl->len)) {
if (!uwsgi_strncmp(filename + (*filename_len - usl->len), usl->len, usl->value, usl->len)) {
goto gzip;
}
usl = usl->next;
@@ -33,7 +33,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
// check for regexp
struct uwsgi_regexp_list *url = uwsgi.static_gzip;
while(url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, filename_len) >= 0) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, *filename_len) >= 0) {
goto gzip;
}
url = url->next;
@@ -43,12 +43,12 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
gzip:
memcpy(filename + filename_len, ".gz\0", 4);
filename_len += 3;
memcpy(filename + *filename_len, ".gz\0", 4);
*filename_len += 3;
if (stat(filename, st)) {
filename_len -= 3;
filename[filename_len] = 0;
*filename_len -= 3;
filename[*filename_len] = 0;
return 0;
}
@@ -445,7 +445,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
// here we need to choose if we want the gzip variant;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) use_gzip = 1;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, &real_filename_len, st)) use_gzip = 1;
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
@@ -579,6 +579,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
if (item && item_len > 0 && item_len <= PATH_MAX) {
memcpy(real_filename, item, item_len);
real_filename_len = item_len;
real_filename[real_filename_len] = 0;
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
goto found;
}
+10 -5
View File
@@ -82,6 +82,8 @@ int uwsgi_apply_final_transformations(struct wsgi_request *wsgi_req) {
found_nostream = 1;
}
else {
// stop the chain if no chunk is available
if (!ut->chunk) return 0;
t_buf = ut->chunk->buf;
t_len = ut->chunk->pos;
goto next;
@@ -132,6 +134,12 @@ void uwsgi_free_transformations(struct wsgi_request *wsgi_req) {
if (current_ut->chunk) {
uwsgi_buffer_destroy(current_ut->chunk);
}
if (current_ut->ub) {
uwsgi_buffer_destroy(current_ut->ub);
}
if (current_ut->fd > -1) {
close(current_ut->fd);
}
ut = ut->next;
free(current_ut);
}
@@ -144,12 +152,9 @@ struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_
ut = ut->next;
}
ut = uwsgi_malloc(sizeof(struct uwsgi_transformation));
ut = uwsgi_calloc(sizeof(struct uwsgi_transformation));
ut->func = func;
ut->is_final = 0;
ut->next = NULL;
ut->chunk = NULL;
ut->can_stream = 0;
ut->fd = -1;
ut->data = data;
if (old_ut) {
+129 -30
View File
@@ -71,11 +71,30 @@ void set_user_harakiri(int sec) {
uwsgi_log("!!! unable to set user harakiri without the master process !!!\n");
return;
}
// a 0 seconds value, reset the timer
if (sec == 0) {
uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid-1].user_harakiri = 0;
}
else if (uwsgi.i_am_a_spooler) {
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
uspool->user_harakiri = 0;
}
else {
uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
}
}
else {
uwsgi.workers[uwsgi.mywid].user_harakiri = uwsgi_now() + sec;
if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid-1].user_harakiri = uwsgi_now() + sec;
}
else if (uwsgi.i_am_a_spooler) {
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
uspool->user_harakiri = uwsgi_now() + sec;
}
else {
uwsgi.workers[uwsgi.mywid].user_harakiri = uwsgi_now() + sec;
}
}
}
@@ -206,14 +225,20 @@ void uwsgi_set_cgroup() {
usl = uwsgi.cgroup;
while (usl) {
if (mkdir(usl->value, 0700)) {
uwsgi_log("using Linux cgroup %s\n", usl->value);
int mode = strtol(uwsgi.cgroup_dir_mode, 0, 8);
if (mkdir(usl->value, mode)) {
if (errno != EEXIST) {
uwsgi_error("mkdir()");
exit(1);
}
if (chmod(usl->value, mode)) {
uwsgi_error("chmod()");
exit(1);
}
uwsgi_log("using Linux cgroup %s with mode %o\n", usl->value, mode);
}
else {
uwsgi_log("created Linux cgroup %s\n", usl->value);
uwsgi_log("created Linux cgroup %s with mode %o\n", usl->value, mode);
}
cgroup_taskfile = uwsgi_concat2(usl->value, "/tasks");
@@ -702,6 +727,11 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
free(ptr);
}
// free chunked input
if (wsgi_req->chunked_input_buf) {
uwsgi_buffer_destroy(wsgi_req->chunked_input_buf);
}
// free websocket engine
if (wsgi_req->websocket_buf) {
uwsgi_buffer_destroy(wsgi_req->websocket_buf);
@@ -1141,12 +1171,11 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
int i;
struct stat st;
int found;
int free_appname = 0;
char *app_name = key;
uint16_t app_name_len = key_len;
if (!app_name && wsgi_req) {
if (app_name_len == 0 && wsgi_req) {
app_name = wsgi_req->appid;
app_name_len = wsgi_req->appid_len;
if (app_name_len == 0) {
@@ -1156,13 +1185,20 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
}
if (uwsgi.vhost) {
app_name = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
char *vhost_name = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
app_name_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
app_name = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, vhost_name, app_name_len);
free(vhost_name);
if (!app_name) {
uwsgi_log("unable to add UWSGI_APPID to the uwsgi buffer, consider increasing it\n");
return -1;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
uwsgi_debug("VirtualHost KEY=%.*s\n", app_name_len, app_name);
#endif
free_appname = 1;
}
wsgi_req->appid = app_name;
wsgi_req->appid_len = app_name_len;
}
}
@@ -1197,22 +1233,11 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
}
}
}
if (modifier1 == -1) {
if (free_appname) free(app_name);
return i;
}
if (modifier1 == uwsgi_apps[i].modifier1) {
if (free_appname) free(app_name);
return i;
}
if (modifier1 == -1) return i;
if (modifier1 == uwsgi_apps[i].modifier1) return i;
}
}
if (!uwsgi.no_default_app) {
if (free_appname) free(app_name);
return uwsgi.default_app;
}
return -1;
}
@@ -1950,7 +1975,7 @@ int uwsgi_list_has_str(char *list, char *str) {
return 0;
}
char hex2num(char *str) {
static char hex2num(char *str) {
char val = 0;
@@ -3063,6 +3088,36 @@ void escape_shell_arg(char *src, size_t len, char *dst) {
*ptr++ = 0;
}
void escape_json(char *src, size_t len, char *dst) {
size_t i;
char *ptr = dst;
for (i = 0; i < len; i++) {
if (src[i] == '\t') {
*ptr++ = '\\';
*ptr++ = 't';
}
else if (src[i] == '\n') {
*ptr++ = '\\';
*ptr++ = 'n';
}
else if (src[i] == '\r') {
*ptr++ = '\\';
*ptr++ = 'r';
}
else if (src[i] == '"') {
*ptr++ = '\\';
*ptr++ = '"';
}
else {
*ptr++ = src[i];
}
}
*ptr++ = 0;
}
void http_url_decode(char *buf, uint16_t * len, char *dst) {
uint16_t i;
@@ -3219,14 +3274,22 @@ char *uwsgi_chomp(char *str) {
return str;
}
char *uwsgi_tmpname(char *base, char *id) {
char *template = uwsgi_concat3(base, "/", id);
if (mkstemp(template) < 0) {
free(template);
return NULL;
int uwsgi_tmpfd() {
char *tmpdir = getenv("TMPDIR");
if (!tmpdir) {
tmpdir = "/tmp";
}
char *template = uwsgi_concat2(tmpdir, "/uwsgiXXXXXX");
int fd = mkstemp(template);
unlink(template);
free(template);
return fd;
}
return template;
FILE *uwsgi_tmpfile() {
int fd = uwsgi_tmpfd();
if (fd < 0) return NULL;
return fdopen(fd, "w+");
}
int uwsgi_file_to_string_list(char *filename, struct uwsgi_string_list **list) {
@@ -3956,3 +4019,39 @@ void uwsgi_takeover() {
uwsgi_worker_run();
}
}
// create a message pipe
void create_msg_pipe(int *fd, int bufsize) {
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
#endif
uwsgi_error("create_msg_pipe()/socketpair()");
exit(1);
}
uwsgi_socket_nb(fd[0]);
uwsgi_socket_nb(fd[1]);
if (bufsize) {
if (setsockopt(fd[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
if (setsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
if (setsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
if (setsockopt(fd[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
}
}
char *uwsgi_binary_path() {
return uwsgi.binary_path ? uwsgi.binary_path : "uwsgi";
}
+114 -13
View File
@@ -206,6 +206,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
{"print-sym", required_argument, 0, "print content of the specified binary symbol", uwsgi_print_sym, NULL, UWSGI_OPT_IMMEDIATE},
{"print-symbol", required_argument, 0, "print content of the specified binary symbol", uwsgi_print_sym, NULL, UWSGI_OPT_IMMEDIATE},
{"reaper", no_argument, 'r', "call waitpid(-1,...) after each request to get rid of zombies", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_REAPER, 0},
{"max-requests", required_argument, 'R', "reload workers after the specified amount of managed requests", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MAX_REQUESTS, 0},
{"min-worker-lifetime", required_argument, 0, "number of seconds worker must run before being reloaded (default is 60)", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MIN_WORKER_LIFETIME, 0},
@@ -233,6 +236,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"cache-sync", required_argument, 0, "copy the whole content of another uWSGI cache server on server startup", uwsgi_opt_set_str, &uwsgi.cache_sync, 0},
{"cache-use-last-modified", no_argument, 0, "update last_modified_at timestamp on every cache item modification (default is disabled)", uwsgi_opt_true, &uwsgi.cache_use_last_modified, 0},
{"add-cache-item", required_argument, 0, "add an item in the cache", uwsgi_opt_add_string_list, &uwsgi.add_cache_item, 0},
{"load-file-in-cache", required_argument, 0, "load a static file in the cache", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache, 0},
#ifdef UWSGI_ZLIB
{"load-file-in-cache-gzip", required_argument, 0, "load a static file in the cache with gzip compression", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache_gzip, 0},
@@ -258,6 +262,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
{"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
{"farm", required_argument, 0, "add a mule farm", uwsgi_opt_add_farm, NULL, UWSGI_OPT_MASTER},
{"mule-msg-size", optional_argument, 0, "set mule message buffer size", uwsgi_opt_set_int, &uwsgi.mule_msg_size, UWSGI_OPT_MASTER},
{"signal", required_argument, 0, "send a uwsgi signal to a server", uwsgi_opt_signal, NULL, UWSGI_OPT_IMMEDIATE},
{"signal-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
@@ -345,6 +350,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"touch-logrotate", required_argument, 0, "trigger logrotation if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logrotate, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"touch-logreopen", required_argument, 0, "trigger log reopen if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logreopen, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"touch-exec", required_argument, 0, "run command when the specified file is modified/touched (syntax: file command)", uwsgi_opt_add_string_list, &uwsgi.touch_exec, UWSGI_OPT_MASTER},
{"touch-signal", required_argument, 0, "signal when the specified file is modified/touched (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.touch_signal, UWSGI_OPT_MASTER},
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
@@ -414,7 +420,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"ssl-verbose", no_argument, 0, "be verbose about SSL errors", uwsgi_opt_true, &uwsgi.ssl_verbose, 0},
// force master, as ssl sessions caching initialize locking early
{"ssl-sessions-use-cache", optional_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_set_str, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
{"ssl-session-use-cache", no_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_true, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
{"ssl-session-use-cache", optional_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_set_str, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
{"ssl-sessions-timeout", required_argument, 0, "set SSL sessions timeout (default: 300 seconds)", uwsgi_opt_set_int, &uwsgi.ssl_sessions_timeout, 0},
{"ssl-session-timeout", required_argument, 0, "set SSL sessions timeout (default: 300 seconds)", uwsgi_opt_set_int, &uwsgi.ssl_sessions_timeout, 0},
{"sni", required_argument, 0, "add an SNI-governed SSL context", uwsgi_opt_sni, NULL, 0},
@@ -455,6 +461,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"log-route", required_argument, 0, "log to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_route, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"log-req-route", required_argument, 0, "log requests to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_req_route, UWSGI_OPT_REQ_LOG_MASTER},
#endif
{"use-abort", no_argument, 0, "call abort() on segfault/fpe, could be useful for generating a core dump", uwsgi_opt_true, &uwsgi.use_abort, 0},
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
@@ -535,6 +544,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"final-route", required_argument, 0, "add a final route", uwsgi_opt_add_route, "path_info", 0},
{"final-route-status", required_argument, 0, "add a final route for the specified status", uwsgi_opt_add_route, "status", 0},
{"final-route-host", required_argument, 0, "add a final route based on Host header", uwsgi_opt_add_route, "http_host", 0},
{"final-route-uri", required_argument, 0, "add a final route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
{"final-route-qs", required_argument, 0, "add a final route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
@@ -547,6 +557,20 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"final-route-if-not", required_argument, 0, "add a final route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
{"final-route-run", required_argument, 0, "always run the specified final route action", uwsgi_opt_add_route, "run", 0},
{"error-route", required_argument, 0, "add an error route", uwsgi_opt_add_route, "path_info", 0},
{"error-route-status", required_argument, 0, "add an error route for the specified status", uwsgi_opt_add_route, "status", 0},
{"error-route-host", required_argument, 0, "add an error route based on Host header", uwsgi_opt_add_route, "http_host", 0},
{"error-route-uri", required_argument, 0, "add an error route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
{"error-route-qs", required_argument, 0, "add an error route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
{"error-route-remote-addr", required_argument, 0, "add an error route based on REMOTE_ADDR", uwsgi_opt_add_route, "remote_addr", 0},
{"error-route-user-agent", required_argument, 0, "add an error route based on HTTP_USER_AGENT", uwsgi_opt_add_route, "user_agent", 0},
{"error-route-remote-user", required_argument, 0, "add an error route based on REMOTE_USER", uwsgi_opt_add_route, "remote_user", 0},
{"error-route-referer", required_argument, 0, "add an error route based on HTTP_REFERER", uwsgi_opt_add_route, "referer", 0},
{"error-route-label", required_argument, 0, "add an error routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
{"error-route-if", required_argument, 0, "add an error route based on condition", uwsgi_opt_add_route, "if", 0},
{"error-route-if-not", required_argument, 0, "add an error route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
{"error-route-run", required_argument, 0, "always run the specified error route action", uwsgi_opt_add_route, "run", 0},
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
#endif
@@ -560,6 +584,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"websockets-max-size", required_argument, 0, "set the max allowed size of websocket messages (in Kbytes, default 1024)", uwsgi_opt_set_64bit, &uwsgi.websockets_max_size, 0},
{"websocket-max-size", required_argument, 0, "set the max allowed size of websocket messages (in Kbytes, default 1024)", uwsgi_opt_set_64bit, &uwsgi.websockets_max_size, 0},
{"chunked-input-limit", required_argument, 0, "set the max size of a chunked input part (default 1MB, in bytes)", uwsgi_opt_set_64bit, &uwsgi.chunked_input_limit, 0},
{"chunked-input-timeout", required_argument, 0, "set default timeout for chunked input", uwsgi_opt_set_int, &uwsgi.chunked_input_timeout, 0},
{"clock", required_argument, 0, "set a clock source", uwsgi_opt_set_str, &uwsgi.requested_clock, 0},
{"clock-list", no_argument, 0, "list enabled clocks", uwsgi_opt_true, &uwsgi.clock_list, 0},
@@ -620,6 +647,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
#ifdef __linux__
{"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup, 0},
{"cgroup-opt", required_argument, 0, "set value in specified cgroup option", uwsgi_opt_add_string_list, &uwsgi.cgroup_opt, 0},
{"cgroup-dir-mode", required_argument, 0, "set permission for cgroup directory (default is 700)", uwsgi_opt_set_str, &uwsgi.cgroup_dir_mode, 0},
{"namespace", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns, 0},
{"namespace-keep-mount", required_argument, 0, "keep the specified mountpoint in your namespace", uwsgi_opt_add_string_list, &uwsgi.ns_keep_mount, 0},
{"ns", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns, 0},
@@ -636,9 +664,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"zerg-server", required_argument, 0, "enable the zerg server on the specified UNIX socket", uwsgi_opt_set_str, &uwsgi.zerg_server, UWSGI_OPT_MASTER},
{"cron", required_argument, 0, "add a cron task", uwsgi_opt_add_cron, NULL, UWSGI_OPT_MASTER},
{"cron2", required_argument, 0, "add a cron task (key=val syntax)", uwsgi_opt_add_cron2, NULL, UWSGI_OPT_MASTER},
{"unique-cron", required_argument, 0, "add a unique cron task", uwsgi_opt_add_unique_cron, NULL, UWSGI_OPT_MASTER},
{"cron-harakiri", required_argument, 0, "set the maximum time (in seconds) we wait for cron command to complete", uwsgi_opt_set_int, &uwsgi.cron_harakiri, 0},
#ifdef UWSGI_SSL
{"legion-cron", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
{"cron-legion", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
{"unique-legion-cron", required_argument, 0, "add a unique cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_unique_legion_cron, NULL, UWSGI_OPT_MASTER},
{"unique-cron-legion", required_argument, 0, "add a unique cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_unique_legion_cron, NULL, UWSGI_OPT_MASTER},
#endif
{"loop", required_argument, 0, "select the uWSGI loop engine", uwsgi_opt_set_str, &uwsgi.loop, 0},
{"loop-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
@@ -668,6 +701,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"show-config", no_argument, 0, "show the current config reformatted as ini", uwsgi_opt_true, &uwsgi.show_config, 0},
{"print", required_argument, 0, "simple print", uwsgi_opt_print, NULL, 0},
{"cflags", no_argument, 0, "report uWSGI CFLAGS (useful for building external plugins)", uwsgi_opt_cflags, NULL, UWSGI_OPT_IMMEDIATE},
{"dot-h", no_argument, 0, "dump the uwsgi.h used for building the core (useful for building external plugins)", uwsgi_opt_dot_h, NULL, UWSGI_OPT_IMMEDIATE},
{"version", no_argument, 0, "print uWSGI version", uwsgi_opt_print, UWSGI_VERSION, 0},
{0, 0, 0, 0, 0, 0, 0}
};
@@ -1502,6 +1536,8 @@ void uwsgi_segfault(int signum) {
uwsgi_log("!!! uWSGI process %d got Segmentation Fault !!!\n", (int) getpid());
uwsgi_backtrace(uwsgi.backtrace_depth);
if (uwsgi.use_abort) abort();
// restore default handler to generate core
signal(signum, SIG_DFL);
kill(getpid(), signum);
@@ -1515,6 +1551,8 @@ void uwsgi_fpe(int signum) {
uwsgi_log("!!! uWSGI process %d got Floating Point Exception !!!\n", (int) getpid());
uwsgi_backtrace(uwsgi.backtrace_depth);
if (uwsgi.use_abort) abort();
// restore default handler to generate core
signal(signum, SIG_DFL);
kill(getpid(), signum);
@@ -3361,7 +3399,9 @@ void uwsgi_opt_set_16bit(char *opt, char *value, void *key) {
uint16_t *ptr = (uint16_t *) key;
if (value) {
*ptr = (strtoul(value, NULL, 10));
unsigned long n = strtoul(value, NULL, 10);
if (n > 65535) n = 65535;
*ptr = n;
}
else {
*ptr = 1;
@@ -4032,20 +4072,61 @@ void uwsgi_opt_flock_wait(char *opt, char *filename, void *none) {
// report CFLAGS used for compiling the server
// use that values to build external plugins
void uwsgi_opt_cflags(char *opt, char *filename, void *foobar) {
size_t len = sizeof(UWSGI_CFLAGS);
char *src = UWSGI_CFLAGS;
char *ptr = uwsgi_malloc(len / 2);
char *base = ptr;
size_t i;
unsigned int u;
for (i = 0; i < len; i += 2) {
sscanf(src + i, "%2x", &u);
*ptr++ = (char) u;
}
fprintf(stdout, "%.*s\n", (int) len / 2, base);
fprintf(stdout, "%s\n", uwsgi_get_cflags());
exit(0);
}
char *uwsgi_get_cflags() {
size_t len = sizeof(UWSGI_CFLAGS);
char *src = UWSGI_CFLAGS;
char *ptr = uwsgi_malloc((len / 2) + 1);
char *base = ptr;
size_t i;
unsigned int u;
for (i = 0; i < len; i += 2) {
sscanf(src + i, "%2x", &u);
*ptr++ = (char) u;
}
*ptr ++= 0;
return base;
}
// report uwsgi.h used for compiling the server
// use that values to build external plugins
extern char *uwsgi_dot_h;
char *uwsgi_get_dot_h() {
char *src = uwsgi_dot_h;
size_t len = strlen(src);
char *ptr = uwsgi_malloc(len / 2);
char *base = ptr;
size_t i;
unsigned int u;
for (i = 0; i < len; i += 2) {
sscanf(src + i, "%2x", &u);
*ptr++ = (char) u;
}
#ifdef UWSGI_ZLIB
struct uwsgi_buffer *ub = uwsgi_zlib_decompress(base, ptr-base);
if (!ub) {
free(base);
return "";
}
// add final null byte
uwsgi_buffer_append(ub, "\0", 1);
free(base);
// base is the final blob
base = ub->buf;
ub->buf = NULL;
uwsgi_buffer_destroy(ub);
#endif
return base;
}
void uwsgi_opt_dot_h(char *opt, char *filename, void *foobar) {
fprintf(stdout, "%s\n", uwsgi_get_dot_h());
exit(0);
}
void uwsgi_opt_connect_and_read(char *opt, char *address, void *foobar) {
char buf[8192];
@@ -4080,3 +4161,23 @@ void uwsgi_opt_extract(char *opt, char *address, void *foobar) {
};
exit(0);
}
void uwsgi_print_sym(char *opt, char *symbol, void *foobar) {
char **sym = dlsym(RTLD_DEFAULT, symbol);
if (sym) {
uwsgi_log("%s", *sym);
exit(0);
}
char *symbol_start = uwsgi_concat2(symbol, "_start");
char *symbol_end = uwsgi_concat2(symbol, "_end");
char *sym_s = dlsym(RTLD_DEFAULT, symbol_start);
char *sym_e = dlsym(RTLD_DEFAULT, symbol_end);
if (sym_s && sym_e) {
uwsgi_log("%.*s", sym_e - sym_s, sym_s);
}
exit(0);
}
+54 -3
View File
@@ -76,7 +76,19 @@ int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status,
// reset the buffer (could be useful for rollbacks...)
wsgi_req->headers->pos = 0;
// reset headers count
wsgi_req->header_cnt = 0;
struct uwsgi_buffer *hh = NULL;
wsgi_req->status = uwsgi_str3_num(status);
#ifdef UWSGI_ROUTING
// apply error routes
if (uwsgi_apply_error_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
// from now on ignore write body requests...
wsgi_req->ignore_body = 1;
return -1;
}
wsgi_req->is_error_routing = 0;
#endif
if (status_len <= 4) {
char *new_sc = NULL;
size_t new_sc_len = 0;
@@ -99,7 +111,6 @@ int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status,
if (!hh) {wsgi_req->write_errors++; return -1;}
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
uwsgi_buffer_destroy(hh);
wsgi_req->status = uwsgi_str3_num(status);
return 0;
error:
uwsgi_buffer_destroy(hh);
@@ -208,6 +219,7 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
if (wsgi_req->write_errors) return -1;
if (wsgi_req->ignore_body) return UWSGI_OK;
// if the transformation chain returns 1, we are in buffering mode
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
@@ -270,8 +282,10 @@ sendbody:
}
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);
}
int can_close = 1;
int uwsgi_response_sendfile_do_can_close(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len, int can_close) {
if (fd == wsgi_req->sendfile_fd) can_close = 0;
@@ -280,6 +294,11 @@ int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos
return -1;
}
if (wsgi_req->ignore_body) {
if (can_close) close(fd);
return UWSGI_OK;
}
if (!wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendfile;
@@ -294,7 +313,7 @@ sendfile:
if (len == 0) {
struct stat st;
if (fstat(fd, &st)) {
uwsgi_error("fstat()");
uwsgi_error("uwsgi_response_sendfile_do()/fstat()");
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
@@ -389,3 +408,35 @@ int uwsgi_simple_wait_write_hook(int fd, int timeout) {
return ret;
}
/*
simplified write to client
(generally used as fallback)
*/
int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
wsgi_req->write_pos = 0;
for(;;) {
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_simple_write()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
uwsgi_log("uwsgi_simple_write() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
return 0;
}
+56
View File
@@ -2,6 +2,8 @@
char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
extern struct uwsgi_server uwsgi;
char *uwsgi_gzip_chunk(z_stream *z, uint32_t *crc32, char *buf, size_t len, size_t *dlen) {
uwsgi_crc32(crc32, buf, len);
return uwsgi_deflate(z, buf, len, dlen);
@@ -38,6 +40,45 @@ end:
return ub;
}
struct uwsgi_buffer *uwsgi_zlib_decompress(char *buf, size_t len) {
z_stream z;
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
if (inflateInit(&z) != Z_OK) {
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
unsigned char out[8192];
z.next_in = (unsigned char *)buf;
z.avail_in = len;
z.next_out = out;
do {
z.avail_out = 8192;
z.next_out = out;
int ret = inflate(&z, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
uwsgi_buffer_destroy(ub);
ub = NULL;
goto end;
}
if (uwsgi_buffer_append(ub, (char *)out, 8192 - z.avail_out)) {
uwsgi_buffer_destroy(ub);
ub = NULL;
goto end;
}
}
while (z.avail_out == 0);
end:
inflateEnd(&z);
return ub;
}
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
z->zalloc = Z_NULL;
z->zfree = Z_NULL;
@@ -54,6 +95,21 @@ int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
return 0;
}
int uwsgi_inflate_init(z_stream *z, char *dict, size_t dict_len) {
z->zalloc = Z_NULL;
z->zfree = Z_NULL;
z->opaque = Z_NULL;
if (inflateInit2(z, 16+MAX_WBITS) != Z_OK) {
return -1;
}
if (dict && dict_len) {
if (inflateSetDictionary(z, (Bytef *) dict, dict_len) != Z_OK) {
return -1;
}
}
return 0;
}
int uwsgi_gzip_prepare(z_stream *z, char *dict, size_t dict_len, uint32_t *crc32) {
uwsgi_crc32(crc32, NULL, 0);
if (uwsgi_deflate_init(z, NULL, 0)) return -1;
+52
View File
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="768px" height="272.667px" viewBox="0 0 768 272.667" enable-background="new 0 0 768 272.667" xml:space="preserve">
<g>
<path fill="#AEC84D" d="M170.667,41.334"/>
<path fill="#AEC84D" d="M46.167,106.667v92.5c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34l0.062-140h-34
l-0.062,86.5c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.167-89H46.167z"/>
<polygon fill="#141215" points="227,250.334 241,250.334 286.667,137.334 332.333,250.001 346.333,250.001 403,41.334
368.667,32.667 334.333,161.667 293.667,60.001 279.333,60.001 240,160.667 204.667,32.667 170.667,41.334 "/>
<path fill="#141215" d="M402,203c0,0,8.667,26.001,23,35.334s38.666,12.999,50.333,12.666s71.001-1.333,71.667-56.333
c5-28-19.333-48.334-26-52.334s-28.334-18-45.667-23s-34.334-16-35.667-24.666s0.001-34,37.334-34.334
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334s-13.333-19-55.333-18.666
c-42,0.332-66.666,17.666-68.333,47.666s4.666,44,35.333,62.666c19,10.334,39.001,12.667,59.667,28.334
c14.333,11.667,11.334,25.001,11,30.667s-7.334,21.666-36.334,20.333S441,209.668,439,206.334s-9-17-9-17L402,203z"/>
<rect x="710.667" y="36.334" fill="#141215" width="35.333" height="211.333"/>
<path fill="#141215" d="M636.333,135.001v27.666h27.333v56c0,0-8.334,5.001-26.667,4.334s-47.332,1.666-49.666-81.667
s37.334-80.667,42-80.667s28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667s-12.334-50.333-67-47.666
c-54.666,2.666-75.666,30.999-78.666,102c-3,71,21.999,117.334,81.666,115s64-7.334,64-7.334l-0.083-107.583L636.333,135.001z"/>
<g>
<circle fill="#AEC84D" cx="521.333" cy="71.001" r="11.667"/>
<circle fill="#252326" cx="521.333" cy="71.001" r="3.5"/>
</g>
<g>
<path fill="none" d="M81.147,185.163L81,106.667H46.167v90.88C56.139,192.016,68.027,187.752,81.147,185.163z"/>
<path fill="none" d="M171.729,106.667h-34l-0.057,78.023c12.606,2.254,24.141,6.043,34.017,11.019L171.729,106.667z"/>
<path opacity="0.1" fill="#FFFFFF" d="M46.167,199.167c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34
l0.023-50.958c-9.876-4.976-21.411-8.765-34.017-11.019l-0.006,8.477c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.02-10.504
c-13.12,2.589-25.008,6.853-34.98,12.384V199.167z"/>
</g>
<g>
<path fill="none" d="M342.89,129.517l-8.557,32.15l-13.896-34.738c-22.89-2.918-44.071-6.524-63.071-10.708L240,160.667
l-14.526-52.621c-16.399-4.896-30.286-10.312-41.175-16.132L227,250.334h14l45.667-113l45.667,112.667h14l31.898-117.459
C366.127,131.707,354.33,130.695,342.89,129.517z"/>
<path opacity="0.1" fill="#FFFFFF" d="M403,41.334l-34.333-8.667l-25.776,96.85c11.44,1.178,23.237,2.19,35.341,3.025L403,41.334z
"/>
<path opacity="0.1" fill="#FFFFFF" d="M204.667,32.667l-34,8.667l13.633,50.58c10.889,5.82,24.775,11.236,41.175,16.132
L204.667,32.667z"/>
<path opacity="0.1" fill="#FFFFFF" d="M293.667,60.001h-14.333l-21.967,56.22c19,4.185,40.182,7.79,63.071,10.708L293.667,60.001z
"/>
</g>
<path opacity="0.1" fill="#FFFFFF" d="M474.333,33.001c-42,0.332-66.666,17.666-68.333,47.666
c-1.409,25.351,2.897,39.276,22.77,54.247c10.646,0.275,21.452,0.419,32.396,0.419c15.9,0,31.514-0.299,46.756-0.872
c-9.466-5.486-21.856-12.032-32.589-15.128c-17.333-5-34.334-16-35.667-24.666s0.001-34,37.334-34.334
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334S516.333,32.667,474.333,33.001z"/>
<path opacity="0.1" fill="#FFFFFF" d="M631,33.001c-53.87,2.627-75.047,30.182-78.522,98.93c11.947-0.916,23.576-2.007,34.838-3.26
c1.845-70.377,37.603-68.004,42.019-68.004c4.666,0,28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667
S685.666,30.334,631,33.001z"/>
<path opacity="0.1" fill="#FFFFFF" d="M710.667,103.59c14.42-5.033,26.342-10.521,35.333-16.36V36.334h-35.333V103.59z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

+1
View File
@@ -229,6 +229,7 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
curl_easy_setopt(curl, CURLOPT_POST, 1L);
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;
char *opts = uwsgi_str(uacc->arg);
+1
View File
@@ -154,6 +154,7 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
curl_easy_setopt(curl, CURLOPT_POST, 1L);
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
char *opts = uwsgi_str(uacc->arg);
+3 -3
View File
@@ -214,7 +214,7 @@ static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len)
// "Status: NNN"
if (header_size >= 11) {
if (!strncasecmp("Status: ", key, 8)) {
uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8);
if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1;
status_sent = 1;
key = NULL;
value = NULL;
@@ -229,13 +229,13 @@ static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len)
// Location: X
if (header_size >= 11) {
if (!strncasecmp("Location: ", key, 10)) {
uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9);
if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1;
status_sent = 1;
}
}
if (status_sent == 0) {
uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6);
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
status_sent = 1;
}
}
-4
View File
@@ -44,10 +44,6 @@ struct corerouter_peer *uwsgi_cr_peer_add(struct corerouter_session *cs) {
peers->in = uwsgi_buffer_new(uwsgi.page_size);
// add timeout
peers->timeout = cr_add_timeout(cs->corerouter, peers);
// check retry
if (cs->retry) {
peers->can_retry = 1;
}
peers->prev = old_peers;
if (old_peers) {
+2 -2
View File
@@ -23,13 +23,13 @@
}\
peer->out_pos += len;
#define cr_write_buf(peer, buf, f) write(peer->fd, buf + buf##_pos, buf->pos - buf##_pos);\
#define cr_write_buf(peer, ubuf, f) write(peer->fd, ubuf->buf + ubuf##_pos, ubuf->pos - ubuf##_pos);\
if (len < 0) {\
cr_try_again;\
uwsgi_cr_error(peer, f);\
return -1;\
}\
buf##_pos += len;
ubuf##_pos += len;
#define cr_write_complete(peer) peer->out_pos == peer->out->pos
+1 -1
View File
@@ -161,7 +161,7 @@ request:
#endif
for(;;) {
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req)) {
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
goto end;
}
wsgi_req->switches++;
+2 -1
View File
@@ -453,7 +453,8 @@ static int amqp_wait_connection_tune(int fd) {
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
char *ptr = (char *) fh;
ssize_t len = 0, rlen;
size_t len = 0;
ssize_t rlen;
while(len < 7) {
rlen = recv(fd, ptr, 7-len, 0);
+5
View File
@@ -172,6 +172,9 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
cr_peer_connected(peer, "fr_instance_connected()");
// we are connected, we cannot retry anymore
peer->can_retry = 0;
// fix modifiers
peer->in->buf[0] = peer->session->main_peer->modifier1;
peer->in->buf[3] = peer->session->main_peer->modifier2;
@@ -217,6 +220,8 @@ static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
if (new_peer->instance_address_len == 0)
return -1;
new_peer->can_retry = 1;
cr_connect(new_peer, fr_instance_connected);
}
+34 -3
View File
@@ -121,7 +121,6 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
hr->content_length = uwsgi_str_num(val, vallen);
hr->session.can_keepalive = 0;
}
// in the future we could support chunked requests...
@@ -183,19 +182,28 @@ int http_headers_parse(struct corerouter_peer *peer) {
peer->out_pos = 0;
struct uwsgi_buffer *out = peer->out;
int found = 0;
// REQUEST_METHOD
while (ptr < watermark) {
if (*ptr == ' ') {
if (uwsgi_buffer_append_keyval(out, "REQUEST_METHOD", 14, base, ptr - base)) return -1;
ptr++;
found = 1;
break;
}
else if (*ptr == '\r' || *ptr == '\n') break;
ptr++;
}
// ensure we have a method
if (!found) {
return -1;
}
// REQUEST_URI / PATH_INFO / QUERY_STRING
base = ptr;
found = 0;
while (ptr < watermark) {
if (*ptr == '?' && !query_string) {
// PATH_INFO must be url-decoded !!!
@@ -221,13 +229,20 @@ int http_headers_parse(struct corerouter_peer *peer) {
if (uwsgi_buffer_append_keyval(out, "QUERY_STRING", 12, query_string, ptr - query_string)) return -1;
}
ptr++;
found = 1;
break;
}
ptr++;
}
// ensure we have a URI
if (!found) {
return -1;
}
// SERVER_PROTOCOL
base = ptr;
found = 0;
while (ptr < watermark) {
if (*ptr == '\r') {
if (ptr + 1 >= watermark)
@@ -239,11 +254,17 @@ int http_headers_parse(struct corerouter_peer *peer) {
hr->session.can_keepalive = 1;
}
ptr += 2;
found = 1;
break;
}
ptr++;
}
// ensure we have a protocol
if (!found) {
return -1;
}
// SCRIPT_NAME
if (uwsgi_buffer_append_keyval(out, "SCRIPT_NAME", 11, "", 0)) return -1;
@@ -459,6 +480,8 @@ ssize_t hr_instance_read(struct corerouter_peer *peer) {
struct http_session *hr = (struct http_session *) peer->session;
ssize_t len = cr_read(peer, "hr_instance_read()");
if (!len) {
// disable keepalive on unread body
if (hr->content_length) hr->session.can_keepalive = 0;
if (hr->session.can_keepalive) {
peer->session->main_peer->disabled = 0;
hr->rnrn = 0;
@@ -575,9 +598,16 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
if (main_peer->in->pos > hr->content_length) {
main_peer->in->pos = hr->content_length;
hr->content_length = 0;
// on pipeline attempt, disable keepalive
hr->session.can_keepalive = 0;
}
else {
hr->content_length -= main_peer->in->pos;
if (hr->content_length == 0) {
main_peer->disabled = 1;
// stop reading from the client
if (uwsgi_cr_set_hooks(main_peer, NULL, NULL)) return -1;
}
}
}
}
@@ -649,10 +679,11 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
new_peer->out->buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
if (hr->remains > 0) {
hr->session.can_keepalive = 0;
if (hr->content_length < hr->remains) {
hr->remains = hr->content_length;
hr->content_length = 0;
// we need to avoid problems with pipelined requests
hr->session.can_keepalive = 0;
}
else {
hr->content_length -= hr->remains;
@@ -660,7 +691,7 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
if (uwsgi_buffer_append(new_peer->out, main_peer->in->buf + hr->headers_size + 1, hr->remains)) return -1;
}
if (hr->session.can_keepalive) {
if (hr->session.can_keepalive && hr->content_length == 0) {
main_peer->disabled = 1;
// stop reading from the client
if (uwsgi_cr_set_hooks(main_peer, NULL, NULL)) return -1;
+5
View File
@@ -25,6 +25,7 @@ struct uwsgi_jvm {
jclass input_stream_class;
jclass file_class;
jclass hashmap_class;
jclass list_class;
jclass set_class;
jclass iterator_class;
@@ -63,6 +64,10 @@ jmethodID uwsgi_jvm_get_static_method_id_quiet(jclass, char *, char *);
jobject uwsgi_jvm_str(char *, size_t);
jobject uwsgi_jvm_hashmap(void);
int uwsgi_jvm_hashmap_put(jobject, jobject, jobject);
int uwsgi_jvm_hashmap_has(jobject, jobject);
jobject uwsgi_jvm_list(void);
int uwsgi_jvm_list_add(jobject, jobject);
jobject uwsgi_jvm_call_object(jobject, jmethodID, ...);
jobject uwsgi_jvm_call_object_static(jclass, jmethodID, ...);
+120
View File
@@ -215,15 +215,42 @@ JNIEXPORT jint JNICALL uwsgi_jvm_request_body_read_bytearray(JNIEnv *env, jobjec
return rlen;
}
JNIEXPORT jint JNICALL uwsgi_jvm_request_body_readline_bytearray(JNIEnv *env, jobject o, jobject b) {
struct wsgi_request *wsgi_req = current_wsgi_req();
ssize_t rlen = 0;
size_t len = uwsgi_jvm_array_len(b);
char *chunk = uwsgi_request_body_readline(wsgi_req, len, &rlen);
if (!chunk) {
uwsgi_jvm_throw_io("error reading request body");
return -1;
}
if (chunk == uwsgi.empty) {
return -1;
}
char *buf = (char *) (*ujvm_env)->GetByteArrayElements(ujvm_env, b, JNI_FALSE);
if (!buf) return -1;
memcpy(buf, chunk, rlen);
(*ujvm_env)->ReleaseByteArrayElements(ujvm_env, b, (jbyte *) buf, 0);
return rlen;
}
JNIEXPORT jint JNICALL uwsgi_jvm_request_body_available(JNIEnv *env, jobject o) {
struct wsgi_request *wsgi_req = current_wsgi_req();
return (jint) (wsgi_req->post_cl - wsgi_req->post_pos);
}
JNIEXPORT void JNICALL uwsgi_jvm_request_body_seek(JNIEnv *env, jobject o, jint pos) {
struct wsgi_request *wsgi_req = current_wsgi_req();
uwsgi_request_body_seek(wsgi_req, pos);
}
static JNINativeMethod uwsgi_jvm_request_body_methods[] = {
{"read", "()I", (void *) &uwsgi_jvm_request_body_read},
{"read", "([B)I", (void *) &uwsgi_jvm_request_body_read_bytearray},
{"readLine", "([B)I", (void *) &uwsgi_jvm_request_body_readline_bytearray},
{"available", "()I", (void *) &uwsgi_jvm_request_body_available},
{"seek", "(I)V", (void *) &uwsgi_jvm_request_body_seek},
};
static struct uwsgi_option uwsgi_jvm_options[] = {
@@ -684,6 +711,23 @@ void uwsgi_jvm_local_unref(jobject obj) {
(*ujvm_env)->DeleteLocalRef(ujvm_env, obj);
}
jobject uwsgi_jvm_list() {
// optimization
static jmethodID mid = 0;
if (!mid) {
mid = uwsgi_jvm_get_method_id(ujvm.list_class, "<init>", "()V");
if (!mid) return NULL;
}
jobject ll = (*ujvm_env)->NewObject(ujvm_env, ujvm.list_class, mid);
if (uwsgi_jvm_exception()) {
return NULL;
}
return ll;
}
jobject uwsgi_jvm_hashmap() {
// optimization
static jmethodID mid = 0;
@@ -712,6 +756,18 @@ int uwsgi_jvm_hashmap_put(jobject hm, jobject key, jobject value) {
return uwsgi_jvm_call(hm, mid, key, value);
}
int uwsgi_jvm_list_add(jobject ll, jobject value) {
// optimization
static jmethodID mid = 0;
if (!mid) {
mid = uwsgi_jvm_get_method_id(ujvm.list_class, "add", "(Ljava/lang/Object;)Z");
if (!mid) return -1;
}
return uwsgi_jvm_call(ll, mid, value);
}
jobject uwsgi_jvm_hashmap_get(jobject hm, jobject key) {
// optimization
static jmethodID mid = 0;
@@ -724,6 +780,21 @@ jobject uwsgi_jvm_hashmap_get(jobject hm, jobject key) {
return uwsgi_jvm_call_object(hm, mid, key);
}
int uwsgi_jvm_hashmap_has(jobject hm, jobject key) {
// optimization
static jmethodID mid = 0;
if (!mid) {
mid = uwsgi_jvm_get_method_id(ujvm.hashmap_class, "containsKey", "(Ljava/lang/Object;)Z");
if (!mid) return 0;
}
if (uwsgi_jvm_call_bool(hm, mid, key)) {
return 1;
}
return 0;
}
jobject uwsgi_jvm_iterator(jobject set) {
// optimization
static jmethodID mid = 0;
@@ -1010,6 +1081,9 @@ static void uwsgi_jvm_create(void) {
ujvm.hashmap_class = uwsgi_jvm_class("java/util/HashMap");
if (!ujvm.hashmap_class) exit(1);
ujvm.list_class = uwsgi_jvm_class("java/util/ArrayList");
if (!ujvm.list_class) exit(1);
ujvm.set_class = uwsgi_jvm_class("java/util/Set");
if (!ujvm.set_class) exit(1);
@@ -1026,6 +1100,52 @@ static void uwsgi_jvm_create(void) {
if (!uwsgi_class) {
exit(1);
}
/*
start filling uwsgi.opt
*/
jfieldID opt_fid = (*ujvm_env)->GetStaticFieldID(ujvm_env, uwsgi_class, "opt", "Ljava/util/HashMap;");
if (uwsgi_jvm_exception()) {
exit(1);
}
jobject opt_hm = uwsgi_jvm_hashmap();
int j;
for (j = 0; j < uwsgi.exported_opts_cnt; j++) {
jstring j_opt_key = uwsgi_jvm_str(uwsgi.exported_opts[j]->key, 0);
if (uwsgi_jvm_hashmap_has(opt_hm, (jobject) j_opt_key)) {
jobject j_opt_value = uwsgi_jvm_hashmap_get(opt_hm, (jobject) j_opt_key);
if (uwsgi_jvm_object_is_instance(j_opt_value, ujvm.list_class)) {
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_list_add(j_opt_value, (jobject) 1);
}
else {
uwsgi_jvm_list_add(j_opt_value, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
}
}
else {
jobject ll = uwsgi_jvm_list();
uwsgi_jvm_list_add(ll, j_opt_value);
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_list_add(ll, (jobject) 1);
}
else {
uwsgi_jvm_list_add(ll, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
}
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, ll);
}
}
else {
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, (jobject) 1);
}
else {
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
}
}
}
(*ujvm_env)->SetStaticObjectField(ujvm_env, uwsgi_class, opt_fid, opt_hm);
(*ujvm_env)->RegisterNatives(ujvm_env, uwsgi_class, uwsgi_jvm_api_methods, sizeof(uwsgi_jvm_api_methods)/sizeof(uwsgi_jvm_api_methods[0]));
if (uwsgi_jvm_exception()) {
exit(1);
+5
View File
@@ -1,11 +1,16 @@
import java.io.*;
import java.util.*;
public class uwsgi {
static HashMap<String,Object> opt;
public static class RequestBody extends InputStream {
public native int read();
public native int read(byte[] b);
public native int readLine(byte[] b);
public native int available();
public native void seek(int pos);
}
public interface SignalHandler {
+33 -10
View File
@@ -9,6 +9,7 @@ struct uwsgi_jwsgi {
char *app;
jmethodID app_mid;
jclass app_class;
jobject app_instance;
} ujwsgi;
static struct uwsgi_option uwsgi_jwsgi_options[] = {
@@ -20,7 +21,16 @@ static int uwsgi_jwsgi_add_request_item(jobject hm, char *key, uint16_t key_len,
jobject j_key = uwsgi_jvm_str(key, key_len);
if (!j_key) return -1;
jobject j_value = uwsgi_jvm_str(value, value_len);
jobject j_value = NULL;
// avoid clobbering vars
if (value_len > 0) {
j_value = uwsgi_jvm_str(value, value_len);
}
else {
char *tmp = uwsgi_str("");
j_value = uwsgi_jvm_str(tmp, 0);
free(tmp);
}
if (!j_value) {
uwsgi_jvm_local_unref(j_value);
return -1;
@@ -72,7 +82,12 @@ static int uwsgi_jwsgi_request(struct wsgi_request *wsgi_req) {
if (uwsgi_jwsgi_add_request_input(hm, "jwsgi.input", 11)) goto end;
response = uwsgi_jvm_call_object_static(ujwsgi.app_class, ujwsgi.app_mid, hm);
if (!ujwsgi.app_instance) {
response = uwsgi_jvm_call_object_static(ujwsgi.app_class, ujwsgi.app_mid, hm);
}
else {
response = uwsgi_jvm_call_object(ujwsgi.app_instance, ujwsgi.app_mid, hm);
}
if (!response) goto end;
if (uwsgi_jvm_array_len(response) != 3) {
@@ -135,23 +150,31 @@ static int uwsgi_jwsgi_setup() {
char *app = uwsgi_str(ujwsgi.app);
char *method = "application";
char *colon = strchr(app, ':');
if (!colon) {
uwsgi_log("invalid JWSGI app definition, must be class:method\n");
exit(1);
if (colon) {
*colon = 0;
method = colon + 1;
}
*colon = 0;
ujwsgi.app_class = uwsgi_jvm_class(app);
if (!ujwsgi.app_class) {
exit(1);
}
ujwsgi.app_mid = uwsgi_jvm_get_static_method_id(ujwsgi.app_class, colon+1, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
if (!ujwsgi.app_mid) {
exit(1);
ujwsgi.app_mid = uwsgi_jvm_get_static_method_id_quiet(ujwsgi.app_class, method, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
if (uwsgi_jvm_exception() || !ujwsgi.app_mid) {
jmethodID mid = uwsgi_jvm_get_method_id(ujwsgi.app_class, "<init>", "()V");
if (uwsgi_jvm_exception() || !mid) exit(1);
ujwsgi.app_instance = (*ujvm_env)->NewObject(ujvm_env, ujwsgi.app_class, mid);
if (uwsgi_jvm_exception() || !ujwsgi.app_instance) {
exit(1);
}
ujwsgi.app_mid = uwsgi_jvm_get_method_id(ujwsgi.app_class, method, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
if (uwsgi_jvm_exception() || !ujwsgi.app_mid) {
exit(1);
}
}
uwsgi_log("JWSGI app \"%s\" loaded\n", ujwsgi.app);
+1 -1
View File
@@ -547,7 +547,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
pthread_mutex_lock(&umono.lock_loader);
}
// check if the mean time, something changed
// check if in the mean time, something changed
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
if (wsgi_req->app_id == -1) {
+5
View File
@@ -0,0 +1,5 @@
#include <uwsgi.h>
struct uwsgi_plugin objc_gc_plugin = {
.name = "objc_gc",
};
+5
View File
@@ -0,0 +1,5 @@
NAME="objc_gc"
CFLAGS=["-fobjc-gc"]
LDFLAGS=[]
LIBS=[]
GCC_LIST=['objc_gc.m']
+21 -10
View File
@@ -394,33 +394,44 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
return -1;
}
if (wsgi_req->dynamic) {
if (uwsgi.threads > 1) {
pthread_mutex_lock(&uperl.lock_loader);
}
}
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, psgi_plugin.modifier1);
// if it is -1, try to load a dynamic app
if (wsgi_req->app_id == -1) {
if (wsgi_req->dynamic) {
if (uwsgi.threads > 1) {
pthread_mutex_lock(&uperl.lock_loader);
}
if (wsgi_req->script_len > 0) {
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->script, wsgi_req->script_len, NULL);
}
else if (wsgi_req->file_len > 0) {
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->file, wsgi_req->file_len, NULL);
}
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&uperl.lock_loader);
}
}
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
if (uwsgi_apps[uwsgi.default_app].modifier1 == psgi_plugin.modifier1) {
wsgi_req->app_id = uwsgi.default_app;
}
}
}
if (wsgi_req->dynamic) {
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&uperl.lock_loader);
}
}
if (wsgi_req->app_id == -1) {
uwsgi_500(wsgi_req);
uwsgi_log("--- unable to find perl application ---\n");
// nothing to clear/free
return UWSGI_OK;
}
}
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
wi->requests++;
@@ -712,7 +723,7 @@ static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t a
STRLEN rlen;
SV *response = POPs;
char *value = SvPV(response, rlen );
ret = UMIN(UMAX16, rlen);
ret = UMIN(UMAX16-1, rlen);
memcpy(buffer, value, ret);
}
+12
View File
@@ -81,6 +81,16 @@ XS(XS_signal) {
XSRETURN_UNDEF;
}
XS(XS_set_user_harakiri) {
dXSARGS;
psgi_check_args(1);
set_user_harakiri( SvIV(ST(0)) );
XSRETURN_UNDEF;
}
XS(XS_reload) {
dXSARGS;
@@ -549,5 +559,7 @@ void init_perl_embedded_module() {
psgi_xs(add_timer);
psgi_xs(add_rb_timer);
psgi_xs(set_user_harakiri);
}
+30
View File
@@ -0,0 +1,30 @@
This is a bit convoluted, but you run it (so far) this way:
You have to compile PyPy with strange options. I'll explain them below.
In the pypy checkout, run:
./rpython/bin/rpython -Ojit --shared --gcrootfinder=shadowstack pypy/goal/targetpypystandalone
Options:
-Ojit - standard PyPy build with JIT
--shared - as expected, creates a .so
--gcrootfinder - on linux, the default rootfinder is asmgcc which has trouble
with position independent code. This option is not needed
on OS X or windows.
If for some strange/dangerous/wrong reason your uWSGI binary is linked with cpython you could have name collisions
with pypy cpyext. In such crazy case you can remove cpyext support with:
./rpython/bin/rpython -Ojit --shared --gcrootfinder=shadowstack pypy/goal/targetpypystandalone --withoutmod-cpyext
By default the pypy uWSGI plugin will load the libpypy-c.so library. You should have it in the LD_LIBRARY_PATH, otherwise you can set its path
with --pypy-lib option (pass an absolute path to it)
You have to specify the pypy home too, you can use the --pypy-home option or the PYPY_HOME var
PYPY_HOME=/home/user/pypy/lib_pypy uwsgi --pypy-lib /opt/pypy/libpypy-c.so --http-socket :9090 --pypy-wsgi werkzeug.testapp:test_app
The funny part about the uWSGI pypy plugin is that it is mainly written in python. The pypy_setup.py script is linked to the plugin, but you can override
it with the --pypy-setup option
+334
View File
@@ -0,0 +1,334 @@
/*******************************************************************
This is the C part of the PyPy plugin (with the main logic being in
Python, see pypy_setup.py).
Idea and initial implementation by Maciej Fijalkowski
*******************************************************************/
#include <uwsgi.h>
struct uwsgi_pypy {
void *handler;
char *lib;
char *setup;
char *home;
char *wsgi;
char *wsgi_file;
struct uwsgi_string_list *eval;
struct uwsgi_string_list *eval_post_fork;
struct uwsgi_string_list *exec;
struct uwsgi_string_list *exec_post_fork;
struct uwsgi_string_list *pp;
} upypy;
// the functions exposed by libpypy-c
char *(*rpython_startup_code)(void);
int (*pypy_setup_home)(char *, int);
int (*pypy_execute_source)(char *);
void (*pypy_thread_attach)(void);
void (*pypy_init_threads)(void);
// the hooks you can override with pypy
void (*uwsgi_pypy_hook_loader)(char *);
void (*uwsgi_pypy_hook_file_loader)(char *);
void (*uwsgi_pypy_hook_pythonpath)(char *);
void (*uwsgi_pypy_hook_request)(void *, int);
void (*uwsgi_pypy_post_fork_hook)(void);
extern struct uwsgi_server uwsgi;
struct uwsgi_plugin pypy_plugin;
static int uwsgi_pypy_init() {
size_t rlen = 0;
char *buffer = NULL;
void *is_cpython_loaded = dlsym(RTLD_DEFAULT, "Py_Initialize");
if (is_cpython_loaded) {
uwsgi_log("!!! Loading both PyPy and CPython in the same process IS PURE EVIL AND IT IS NOT SUPPORTED !!!\n");
exit(1);
}
if (upypy.lib) {
upypy.handler = dlopen(upypy.lib, RTLD_NOW | RTLD_GLOBAL);
}
else {
if (upypy.home) {
#ifdef __APPLE__
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dylib");
#else
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.so");
#endif
if (uwsgi_file_exists(libpath)) {
upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL);
}
free(libpath);
}
// fallback to standard library search path
if (!upypy.handler) {
#ifdef __APPLE__
upypy.handler = dlopen("libpypy-c.dylib", RTLD_NOW | RTLD_GLOBAL);
#else
upypy.handler = dlopen("libpypy-c.so", RTLD_NOW | RTLD_GLOBAL);
#endif
}
}
if (!upypy.handler) {
uwsgi_log("unable to load pypy library: %s\n", dlerror());
exit(1);
}
rpython_startup_code = dlsym(upypy.handler, "rpython_startup_code");
if (!rpython_startup_code) {
uwsgi_log("unable to find rpython_startup_code() symbol\n");
exit(1);
}
pypy_setup_home = dlsym(upypy.handler, "pypy_setup_home");
if (!pypy_setup_home) {
uwsgi_log("unable to find pypy_setup_home() symbol\n");
exit(1);
}
pypy_execute_source = dlsym(upypy.handler, "pypy_execute_source");
if (!pypy_execute_source) {
uwsgi_log("unable to find pypy_execute_source() symbol\n");
exit(1);
}
pypy_thread_attach = dlsym(upypy.handler, "pypy_thread_attach");
if (!pypy_thread_attach) {
uwsgi_log("!!! WARNING your libpypy-c does not export pypy_thread_attach, multithreading will not work !!!\n");
}
pypy_init_threads = dlsym(upypy.handler, "pypy_init_threads");
if (!pypy_init_threads) {
uwsgi_log("!!! WARNING your libpypy-c does not export pypy_init_threads, multithreading will not work !!!\n");
}
rpython_startup_code();
if (!upypy.home) {
upypy.home = getenv("PYPY_HOME");
if (!upypy.home) {
uwsgi_log("you have to specify a pypy home with --pypy-home\n");
exit(1);
}
}
if (pypy_setup_home(upypy.home, 0)) {
char *retry = uwsgi_concat2(upypy.home, "/lib_pypy");
if (uwsgi_is_dir(retry)) {
// this time we use debug
if (!pypy_setup_home(retry, 1)) {
free(retry);
goto ready;
}
}
uwsgi_log("unable to set pypy home to \"%s\"\n", upypy.home);
exit(1);
}
ready:
if (upypy.setup) {
buffer = uwsgi_open_and_read(upypy.setup, &rlen, 1, NULL);
}
else {
char *start = dlsym(RTLD_DEFAULT, "uwsgi_pypy_setup_start");
char *end = dlsym(RTLD_DEFAULT, "uwsgi_pypy_setup_end");
if (start && end) {
buffer = uwsgi_concat2n(start, end-start, "", 0);
}
}
if (!buffer) {
uwsgi_log("you have to load a pypy setup file with --pypy-setup\n");
exit(1);
}
if (pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
// add items to the pythonpath
struct uwsgi_string_list *usl = upypy.pp;
while(usl) {
if (uwsgi_pypy_hook_pythonpath) {
uwsgi_pypy_hook_pythonpath(usl->value);
}
usl = usl->next;
}
return 0;
}
static void uwsgi_pypy_preinit_apps() {
struct uwsgi_string_list *usl = upypy.eval;
while(usl) {
if (pypy_execute_source(usl->value)) {
exit(1);
}
usl = usl->next;
}
usl = upypy.exec;
while(usl) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(usl->value, &rlen, 1, NULL);
if (pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
usl = usl->next;
}
}
static int uwsgi_pypy_request(struct wsgi_request *wsgi_req) {
/* Standard WSGI request */
if (!wsgi_req->uh->pktsize) {
uwsgi_log( "Empty pypy request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
if (uwsgi_pypy_hook_request) {
uwsgi_pypy_hook_request(wsgi_req, wsgi_req->async_id);
}
return UWSGI_OK;
}
static void uwsgi_pypy_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
static void uwsgi_pypy_init_apps() {
if (uwsgi_pypy_hook_loader && upypy.wsgi) {
uwsgi_pypy_hook_loader(upypy.wsgi);
}
if (uwsgi_pypy_hook_file_loader && upypy.wsgi_file) {
uwsgi_pypy_hook_file_loader(upypy.wsgi_file);
}
}
/*
static void uwsgi_pypy_atexit() {
if (pypy_debug_file)
fflush(pypy_debug_file);
}
*/
static struct uwsgi_option uwsgi_pypy_options[] = {
{"pypy-lib", required_argument, 0, "set the path/name of the pypy library", uwsgi_opt_set_str, &upypy.lib, 0},
{"pypy-setup", required_argument, 0, "set the path of the python setup script", uwsgi_opt_set_str, &upypy.setup, 0},
{"pypy-home", required_argument, 0, "set the home of pypy library", uwsgi_opt_set_str, &upypy.home, 0},
{"pypy-wsgi", required_argument, 0, "load a WSGI module", uwsgi_opt_set_str, &upypy.wsgi, 0},
{"pypy-wsgi-file", required_argument, 0, "load a WSGI/mod_wsgi file", uwsgi_opt_set_str, &upypy.wsgi_file, 0},
{"pypy-eval", required_argument, 0, "evaluate pypy code before fork()", uwsgi_opt_add_string_list, &upypy.eval, 0},
{"pypy-eval-post-fork", required_argument, 0, "evaluate pypy code soon after fork()", uwsgi_opt_add_string_list, &upypy.eval_post_fork, 0},
{"pypy-exec", required_argument, 0, "execute pypy code from file before fork()", uwsgi_opt_add_string_list, &upypy.exec, 0},
{"pypy-exec-post-fork", required_argument, 0, "execute pypy code from file soon after fork()", uwsgi_opt_add_string_list, &upypy.exec_post_fork, 0},
{"pypy-pp", required_argument, 0, "add an item to the pythonpath", uwsgi_opt_add_string_list, &upypy.pp, 0},
{"pypy-python-path", required_argument, 0, "add an item to the pythonpath", uwsgi_opt_add_string_list, &upypy.pp, 0},
{"pypy-pythonpath", required_argument, 0, "add an item to the pythonpath", uwsgi_opt_add_string_list, &upypy.pp, 0},
{0, 0, 0, 0, 0, 0, 0},
};
static void uwsgi_pypy_enable_threads() {
if (pypy_init_threads) {
pypy_init_threads();
}
}
static void uwsgi_pypy_init_thread() {
if (pypy_thread_attach) {
pypy_thread_attach();
}
}
static int uwsgi_pypy_signal_handler(uint8_t sig, void *handler) {
void (*pypy_func)(int) = (void(*)(int)) handler;
pypy_func(sig);
return 0;
}
static uint16_t uwsgi_pypy_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
int iargvs[UMAX8];
int i;
int (*pypy_func)(int, char **, int*, char *) = (int (*)(int, char **, int*, char *)) func;
// we convert 16bit to int
for(i=0;i<argc;i++) {
iargvs[i] = (int) argvs[i];
}
return pypy_func(argc, argv, iargvs, buffer);
}
static void uwsgi_pypy_post_fork() {
struct uwsgi_string_list *usl = upypy.eval_post_fork;
while(usl) {
if (pypy_execute_source(usl->value)) {
exit(1);
}
usl = usl->next;
}
usl = upypy.exec_post_fork;
while(usl) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(usl->value, &rlen, 1, NULL);
if (pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
usl = usl->next;
}
if (uwsgi_pypy_post_fork_hook) {
uwsgi_pypy_post_fork_hook();
}
}
static void uwsgi_pypy_onload() {
#ifdef UWSGI_PYPY_HOME
upypy.home = UWSGI_PYPY_HOME;
#endif
}
static int uwsgi_pypy_mule(char *opt) {
if (uwsgi_endswith(opt, ".py")) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(opt, &rlen, 1, NULL);
pypy_execute_source(buffer);
free(buffer);
return 1;
}
return 0;
}
struct uwsgi_plugin pypy_plugin = {
.name = "pypy",
.modifier1 = 0,
.on_load = uwsgi_pypy_onload,
.init = uwsgi_pypy_init,
.request = uwsgi_pypy_request,
.after_request = uwsgi_pypy_after_request,
.options = uwsgi_pypy_options,
.preinit_apps = uwsgi_pypy_preinit_apps,
.init_apps = uwsgi_pypy_init_apps,
.init_thread = uwsgi_pypy_init_thread,
.signal_handler = uwsgi_pypy_signal_handler,
.enable_threads = uwsgi_pypy_enable_threads,
.rpc = uwsgi_pypy_rpc,
.post_fork = uwsgi_pypy_post_fork,
.mule = uwsgi_pypy_mule,
};
+899
View File
@@ -0,0 +1,899 @@
import sys
import os
sys.path.insert(0, '.')
sys.path.extend(os.environ.get('PYTHONPATH','').split(os.pathsep))
import imp
import traceback
__name__ = '__main__'
mainmodule = type(sys)('__main__')
sys.modules['__main__'] = mainmodule
import cffi
# this is a list holding object we do not want to be freed (like callback and handlers)
uwsgi_gc = []
# the main ffi
ffi = cffi.FFI()
# the hooks we need to patch
hooks = '''
void free(void *);
ssize_t read(int, void *, size_t);
ssize_t write(int, const void *, size_t);
int close(int);
void (*uwsgi_pypy_hook_loader)(char *);
void (*uwsgi_pypy_hook_file_loader)(char *);
void (*uwsgi_pypy_hook_pythonpath)(char *);
void (*uwsgi_pypy_hook_request)(struct wsgi_request *);
void (*uwsgi_pypy_post_fork_hook)(void);
'''
# here we load CFLAGS and uwsgi.h from the binary
defines0 = '''
char *uwsgi_get_cflags();
char *uwsgi_get_dot_h();
'''
ffi.cdef(defines0)
lib0 = ffi.verify(defines0)
# this is ugly, we should find a better approach
# basically it build a list of #define from binary CFLAGS
uwsgi_cdef = []
uwsgi_defines = []
uwsgi_cflags = ffi.string(lib0.uwsgi_get_cflags()).split()
for cflag in uwsgi_cflags:
if cflag.startswith('-D'):
line = cflag[2:]
if '=' in line:
(key, value) = line.split('=', 1)
uwsgi_cdef.append('#define %s ...' % key)
uwsgi_defines.append('#define %s %s' % (key, value.replace('\\"','"').replace('""','"')))
else:
uwsgi_cdef.append('#define %s ...' % line)
uwsgi_defines.append('#define %s 1' % line)
uwsgi_dot_h = ffi.string(lib0.uwsgi_get_dot_h())
# uwsgi definitions
cdefines = '''
%s
struct iovec {
void *iov_base;
size_t iov_len;
...;
};
struct uwsgi_header {
uint8_t modifier1;
...;
};
struct wsgi_request {
int fd;
int async_id;
uint16_t var_cnt;
struct iovec *hvec;
int async_ready_fd;
int async_last_ready_fd;
int suspended;
struct uwsgi_header *uh;
...;
};
struct uwsgi_opt {
char *key;
char *value;
...;
};
struct uwsgi_worker {
int id;
int pid;
uint64_t requests;
uint64_t delta_requests;
uint64_t signals;
int cheaped;
int suspended;
int sig;
uint8_t signum;
uint64_t running_time;
uint64_t avg_response_time;
uint64_t tx;
...;
};
struct uwsgi_plugin {
uint8_t modifier1;
void (*suspend) (struct wsgi_request *);
void (*resume) (struct wsgi_request *);
...;
};
struct uwsgi_buffer {
char *buf;
size_t pos;
...;
};
struct uwsgi_server {
char hostname[];
int mywid;
int muleid;
int master_process;
struct uwsgi_opt **exported_opts;
int exported_opts_cnt;
struct uwsgi_worker *workers;
int signal_socket;
int numproc;
int async;
void (*schedule_to_main) (struct wsgi_request *);
void (*schedule_to_req) (void);
struct wsgi_request *(*current_wsgi_req) (void);
struct wsgi_request *wsgi_req;
struct uwsgi_plugin *p[];
...;
};
struct uwsgi_server uwsgi;
struct uwsgi_plugin *pypy_plugin;
const char *uwsgi_pypy_version;
char *uwsgi_binary_path();
int uwsgi_response_prepare_headers(struct wsgi_request *, char *, size_t);
int uwsgi_response_add_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
int uwsgi_response_write_body_do(struct wsgi_request *, char *, size_t);
int uwsgi_response_sendfile_do_can_close(struct wsgi_request *, int, size_t, size_t, int);
char *uwsgi_request_body_read(struct wsgi_request *, ssize_t , ssize_t *);
char *uwsgi_request_body_readline(struct wsgi_request *, ssize_t, ssize_t *);
void uwsgi_buffer_destroy(struct uwsgi_buffer *);
int uwsgi_is_again();
int uwsgi_register_rpc(char *, struct uwsgi_plugin *, uint8_t, void *);
int uwsgi_register_signal(uint8_t, char *, void *, uint8_t);
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint16_t *);
void uwsgi_set_processname(char *);
int uwsgi_signal_send(int, uint8_t);
uint64_t uwsgi_worker_exceptions(int);
int uwsgi_worker_is_busy(int);
char *uwsgi_cache_magic_get(char *, uint16_t, uint64_t *, uint64_t *, char *);
int uwsgi_cache_magic_set(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t, char *);
int uwsgi_cache_magic_del(char *, uint16_t, char *);
int uwsgi_cache_magic_exists(char *, uint16_t, char *);
int uwsgi_cache_magic_clear(char *);
int uwsgi_add_file_monitor(uint8_t, char *);
int uwsgi_add_timer(uint8_t, int);
int uwsgi_signal_add_rb_timer(uint8_t, int, int);
int uwsgi_user_lock(int);
int uwsgi_user_unlock(int);
int uwsgi_signal_registered(uint8_t);
int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int);
void uwsgi_alarm_trigger(char *, char *, size_t);
void async_schedule_to_req_green(void);
void async_add_timeout(struct wsgi_request *, int);
int async_add_fd_write(struct wsgi_request *, int, int);
int async_add_fd_read(struct wsgi_request *, int, int);
int uwsgi_connect(char *, int, int);
int uwsgi_websocket_handshake(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
int uwsgi_websocket_send(struct wsgi_request *, char *, size_t);
struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *);
struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *);
char *uwsgi_chunked_read(struct wsgi_request *, size_t *, int, int);
void uwsgi_disconnect(struct wsgi_request *);
int uwsgi_ready_fd(struct wsgi_request *);
void set_user_harakiri(int);
%s
''' % ('\n'.join(uwsgi_cdef), hooks)
cverify = '''
%s
const char *uwsgi_pypy_version = UWSGI_VERSION;
%s
extern struct uwsgi_server uwsgi;
extern struct uwsgi_plugin *pypy_plugin;
%s
''' % ('\n'.join(uwsgi_defines), uwsgi_dot_h, hooks)
ffi.cdef(cdefines)
lib = ffi.verify(cverify)
libc = ffi.dlopen(None)
"""
this is a global object point the the WSGI callable
it sucks, i will fix it in the near future...
"""
wsgi_application = None
sys.argv.insert(0, ffi.string(lib.uwsgi_binary_path()))
"""
load a wsgi module
"""
@ffi.callback("void(char *)")
def uwsgi_pypy_loader(module):
global wsgi_application
m = ffi.string(module)
c = 'application'
if ':' in m:
m, c = m.split(':')
if '.' in m:
mod = __import__(m, None, None, '*')
else:
mod = __import__(m)
wsgi_application = getattr(mod, c)
"""
load a mod_wsgi compliant .wsgi file
"""
@ffi.callback("void(char *)")
def uwsgi_pypy_file_loader(filename):
global wsgi_application
w = ffi.string(filename)
c = 'application'
mod = imp.load_source('uwsgi_file_wsgi', w)
wsgi_application = getattr(mod, c)
"""
.post_fork_hook
"""
@ffi.callback("void()")
def uwsgi_pypy_post_fork_hook():
import uwsgi
if hasattr(uwsgi, 'post_fork_hook'):
uwsgi.post_fork_hook()
"""
add an item to the pythonpath
"""
@ffi.callback("void(char *)")
def uwsgi_pypy_pythonpath(item):
path = ffi.string(item)
sys.path.append(path)
print "added %s to pythonpath" % path
"""
class implementing wsgi.file_wrapper
"""
class WSGIfilewrapper(object):
def __init__(self, wsgi_req, f, chunksize=0):
self.wsgi_req = wsgi_req
self.f = f
self.chunksize = chunksize
if hasattr(f, 'close'):
self.close = f.close
def __iter__(self):
return self
def sendfile(self):
if hasattr(self.f, 'fileno'):
lib.uwsgi_response_sendfile_do_can_close(self.wsgi_req, self.f.fileno(), 0, 0, 0)
elif hasattr(self.f, 'read'):
if self.chunksize == 0:
chunk = self.f.read()
if len(chunk) > 0:
lib.uwsgi_response_write_body_do(self.wsgi_req, ffi.new("char[]", chunk), len(chunk))
return
while True:
chunk = self.f.read(self.chunksize)
if chunk is None or len(chunk) == 0:
break
lib.uwsgi_response_write_body_do(self.wsgi_req, ffi.new("char[]", chunk), len(chunk))
"""
class implementing wsgi.input
"""
class WSGIinput(object):
def __init__(self, wsgi_req):
self.wsgi_req = wsgi_req
def read(self, size=0):
rlen = ffi.new('int64_t*')
chunk = lib.uwsgi_request_body_read(self.wsgi_req, size, rlen)
if chunk != ffi.NULL:
return ffi.string(chunk, rlen[0])
if rlen[0] < 0:
raise IOError("error reading wsgi.input")
raise IOError("error waiting for wsgi.input")
def getline(self, hint=0):
rlen = ffi.new('ssize_t*')
chunk = lib.uwsgi_request_body_readline(self.wsgi_req, hint, rlen)
if chunk != ffi.NULL:
return ffi.string(chunk, rlen[0])
if rlen[0] < 0:
raise IOError("error reading line from wsgi.input")
raise IOError("error waiting for line on wsgi.input")
def readline(self, hint=0):
return self.getline(hint)
def readlines(self, hint=0):
lines = []
while True:
chunk = self.getline(hint)
if len(chunk) == 0:
break
lines.append(chunk)
return lines
def __iter__(self):
return self
def __next__(self):
chunk = self.getline()
if len(chunk) == 0:
raise StopIteration
return chunk
"""
the WSGI request handler
"""
@ffi.callback("void(struct wsgi_request *)")
def uwsgi_pypy_wsgi_handler(wsgi_req):
import uwsgi
global wsgi_application
def writer(data):
lib.uwsgi_response_write_body_do(wsgi_req, ffi.new("char[]", data), len(data))
def start_response(status, headers, exc_info=None):
if exc_info:
traceback.print_exception(*exc_info)
lib.uwsgi_response_prepare_headers(wsgi_req, ffi.new("char[]", status), len(status))
for hh in headers:
lib.uwsgi_response_add_header(wsgi_req, ffi.new("char[]", hh[0]), len(hh[0]), ffi.new("char[]", hh[1]), len(hh[1]))
return writer
environ = {}
iov = wsgi_req.hvec
for i in range(0, wsgi_req.var_cnt, 2):
environ[ffi.string(ffi.cast("char*", iov[i].iov_base), iov[i].iov_len)] = ffi.string(ffi.cast("char*", iov[i+1].iov_base), iov[i+1].iov_len)
environ['wsgi.version'] = (1, 0)
scheme = 'http'
if 'HTTPS' in environ:
if environ['HTTPS'] in ('on', 'ON', 'On', '1', 'true', 'TRUE', 'True'):
scheme = 'https'
environ['wsgi.url_scheme'] = environ.get('UWSGI_SCHEME', scheme)
environ['wsgi.input'] = WSGIinput(wsgi_req)
environ['wsgi.errors'] = sys.stderr
environ['wsgi.run_once'] = False
environ['wsgi.file_wrapper'] = lambda f, chunksize=0: WSGIfilewrapper(wsgi_req, f, chunksize)
environ['wsgi.multithread'] = True
environ['wsgi.multiprocess'] = True
environ['uwsgi.core'] = wsgi_req.async_id
environ['uwsgi.node'] = uwsgi.hostname
response = wsgi_application(environ, start_response)
if type(response) is str:
writer(response)
else:
try:
if isinstance(response, WSGIfilewrapper):
response.sendfile()
else:
for chunk in response:
if isinstance(chunk, WSGIfilewrapper):
try:
chunk.sendfile()
finally:
chunk.close()
else:
writer(chunk)
finally:
if hasattr(response, 'close'):
response.close()
lib.uwsgi_pypy_hook_loader = uwsgi_pypy_loader
lib.uwsgi_pypy_hook_file_loader = uwsgi_pypy_file_loader
lib.uwsgi_pypy_hook_pythonpath = uwsgi_pypy_pythonpath
lib.uwsgi_pypy_hook_request = uwsgi_pypy_wsgi_handler
lib.uwsgi_pypy_post_fork_hook = uwsgi_pypy_post_fork_hook
"""
Here we define the "uwsgi" virtual module
"""
uwsgi = imp.new_module('uwsgi')
sys.modules['uwsgi'] = uwsgi
uwsgi.version = ffi.string(lib.uwsgi_pypy_version)
uwsgi.hostname = ffi.string(lib.uwsgi.hostname)
def uwsgi_pypy_uwsgi_register_signal(signum, kind, handler):
cb = ffi.callback('void(int)', handler)
uwsgi_gc.append(cb)
if lib.uwsgi_register_signal(signum, ffi.new("char[]", kind), cb, lib.pypy_plugin.modifier1) < 0:
raise Exception("unable to register signal %d" % signum)
uwsgi.register_signal = uwsgi_pypy_uwsgi_register_signal
class uwsgi_pypy_RPC(object):
def __init__(self, func):
self.func = func
def __call__(self, argc, argv, argvs, buf):
pargs = []
for i in range(0, argc):
pargs.append(ffi.string(argv[i], argvs[i]))
response = self.func(*pargs)
if len(response) > 0 and len(response) <= 65535:
dst = ffi.buffer(buf, 65536)
dst[:len(response)] = response
return len(response)
def uwsgi_pypy_uwsgi_register_rpc(name, func, argc=0):
rpc_func = uwsgi_pypy_RPC(func)
cb = ffi.callback("int(int, char*[], int[], char*)", rpc_func)
uwsgi_gc.append(cb)
if lib.uwsgi_register_rpc(ffi.new("char[]", name), lib.pypy_plugin, argc, cb) < 0:
raise Exception("unable to register rpc func %s" % name)
uwsgi.register_rpc = uwsgi_pypy_uwsgi_register_rpc
def uwsgi_pypy_rpc(node, func, *args):
argc = 0
argv = ffi.new('char*[256]')
argvs = ffi.new('uint16_t[256]')
rsize = ffi.new('uint16_t*')
for arg in args:
if argc >= 255:
raise Exception('invalid number of rpc arguments')
if len(arg) >= 65535:
raise Exception('invalid rpc argument size (must be < 65535)')
argv[argc] = ffi.new('char[]', arg)
argvs[argc] = len(arg)
argc += 1
if node:
c_node = ffi.new("char[]", node)
else:
c_node = ffi.NULL
response = lib.uwsgi_do_rpc(c_node, ffi.new("char[]",func), argc, argv, argvs, rsize)
if response:
ret = ffi.string(response, rsize[0])
lib.free(response)
return ret
return None
uwsgi.rpc = uwsgi_pypy_rpc
def uwsgi_pypy_call(func, *args):
node = None
if '@' in func:
(func, node) = func.split('@')
return uwsgi_pypy_rpc(node, func, *args)
uwsgi.call = uwsgi_pypy_call
uwsgi.signal = lambda x: lib.uwsgi_signal_send(lib.uwsgi.signal_socket, x)
def uwsgi_pypy_uwsgi_cache_get(key, cache=ffi.NULL):
vallen = ffi.new('uint64_t*')
value = lib.uwsgi_cache_magic_get(key, len(key), vallen, ffi.NULL, cache)
if value == ffi.NULL:
return None
ret = ffi.string(value, vallen[0])
libc.free(value)
return ret
uwsgi.cache_get = uwsgi_pypy_uwsgi_cache_get
def uwsgi_pypy_uwsgi_cache_set(key, value, expires=0, cache=ffi.NULL):
if lib.uwsgi_cache_magic_set(key, len(key), value, len(value), expires, 0, cache) < 0:
raise Exception('unable to store item in the cache')
uwsgi.cache_set = uwsgi_pypy_uwsgi_cache_set
def uwsgi_pypy_uwsgi_cache_update(key, value, expires=0, cache=ffi.NULL):
if lib.uwsgi_cache_magic_set(key, len(key), value, len(value), expires, 1 << 1, cache) < 0:
raise Exception('unable to store item in the cache')
uwsgi.cache_update = uwsgi_pypy_uwsgi_cache_update
def uwsgi_pypy_uwsgi_cache_del(key, cache=ffi.NULL):
if lib.uwsgi_cache_magic_del(key, len(key), cache) < 0:
raise Exception('unable to delete item from the cache')
uwsgi.cache_del = uwsgi_pypy_uwsgi_cache_del
def uwsgi_pypy_uwsgi_add_timer(signum, secs):
if lib.uwsgi_add_timer(signum, secs) < 0:
raise Exception("unable to register timer")
uwsgi.add_timer = uwsgi_pypy_uwsgi_add_timer
def uwsgi_pypy_uwsgi_add_rb_timer(signum, secs):
if lib.uwsgi_signal_add_rb_timer(signum, secs, 0) < 0:
raise Exception("unable to register redblack timer")
uwsgi.add_rb_timer = uwsgi_pypy_uwsgi_add_rb_timer
def uwsgi_pypy_uwsgi_add_file_monitor(signum, filename):
if lib.uwsgi_add_file_monitor(signum, ffi.new("char[]", filename)) < 0:
raise Exception("unable to register file monitor")
uwsgi.add_file_monitor = uwsgi_pypy_uwsgi_add_file_monitor
def uwsgi_pypy_lock(num=0):
if lib.uwsgi_user_lock(num) < 0:
raise Exception("invalid lock")
uwsgi.lock = uwsgi_pypy_lock
def uwsgi_pypy_unlock(num=0):
if lib.uwsgi_user_unlock(num) < 0:
raise Exception("invalid lock")
uwsgi.unlock = uwsgi_pypy_unlock
def uwsgi_pypy_masterpid():
if lib.uwsgi.master_process:
return lib.uwsgi.workers[0].pid
return 0
uwsgi.masterpid = uwsgi_pypy_masterpid
uwsgi.worker_id = lambda: lib.uwsgi.mywid
uwsgi.mule_id = lambda: lib.uwsgi.muleid
def uwsgi_pypy_signal_registered(signum):
if lib.uwsgi_signal_registered(signum) > 0:
return True
return False
uwsgi.signal_registered = uwsgi_pypy_signal_registered
def uwsgi_pypy_alarm(alarm, msg):
lib.uwsgi_alarm_trigger(ffi.new('char[]', alarm), ffi.new('char[]', msg), len(msg))
uwsgi.alarm = uwsgi_pypy_alarm
uwsgi.setprocname = lambda name: lib.uwsgi_set_processname(ffi.new('char[]', name))
def uwsgi_pypy_add_cron(signum, minute, hour, day, month, week):
if lib.uwsgi_signal_add_cron(signum, minute, hour, day, month, week) < 0:
raise Exception("unable to register cron")
uwsgi.add_cron = uwsgi_pypy_add_cron
"""
populate uwsgi.opt
"""
uwsgi.opt = {}
for i in range(0, lib.uwsgi.exported_opts_cnt):
uo = lib.uwsgi.exported_opts[i]
k = ffi.string(uo.key)
if uo.value == ffi.NULL:
v = True
else:
v = ffi.string(uo.value)
if k in uwsgi.opt:
if type(uwsgi.opt[k]) is list:
uwsgi.opt[k].append(v)
else:
uwsgi.opt[k] = [uwsgi.opt[k], v]
else:
uwsgi.opt[k] = v
def uwsgi_pypy_current_wsgi_req():
wsgi_req = lib.uwsgi.current_wsgi_req()
if wsgi_req == ffi.NULL:
raise Exception("unable to get current wsgi_request, check your setup !!!")
return wsgi_req
"""
uwsgi.suspend()
"""
def uwsgi_pypy_suspend():
wsgi_req = uwsgi_pypy_current_wsgi_req()
if lib.uwsgi.schedule_to_main:
lib.uwsgi.schedule_to_main(wsgi_req);
uwsgi.suspend = uwsgi_pypy_suspend
"""
uwsgi.workers()
"""
def uwsgi_pypy_workers():
workers = []
for i in range(1, lib.uwsgi.numproc+1):
worker = {}
worker['id'] = lib.uwsgi.workers[i].id
worker['pid'] = lib.uwsgi.workers[i].pid
worker['requests'] = lib.uwsgi.workers[i].requests
worker['delta_requests'] = lib.uwsgi.workers[i].delta_requests
worker['signals'] = lib.uwsgi.workers[i].signals
worker['exceptions'] = lib.uwsgi_worker_exceptions(i);
worker['apps'] = []
if lib.uwsgi.workers[i].cheaped:
worker['status'] == 'cheap'
elif lib.uwsgi.workers[i].suspended and not lib.uwsgi_worker_is_busy(i):
worker['status'] == 'pause'
else:
if lib.uwsgi.workers[i].sig:
worker['status'] = 'sig%d' % lib.uwsgi.workers[i].signum
elif lib.uwsgi_worker_is_busy(i):
worker['status'] = 'busy'
else:
worker['status'] = 'idle'
worker['running_time'] = lib.uwsgi.workers[i].running_time
worker['avg_rt'] = lib.uwsgi.workers[i].avg_response_time
worker['tx'] = lib.uwsgi.workers[i].tx
workers.append(worker)
return workers
uwsgi.workers = uwsgi_pypy_workers
"""
uwsgi.async_sleep(timeout)
"""
def uwsgi_pypy_async_sleep(timeout):
if timeout > 0:
wsgi_req = uwsgi_pypy_current_wsgi_req();
lib.async_add_timeout(wsgi_req, timeout);
uwsgi.async_sleep = uwsgi_pypy_async_sleep
"""
uwsgi.async_connect(addr)
"""
def uwsgi_pypy_async_connect(addr):
fd = lib.uwsgi_connect(ffi.new('char[]', addr), 0, 1)
if fd < 0:
raise Exception("unable to connect to %s" % addr)
return fd
uwsgi.async_connect = uwsgi_pypy_async_connect
uwsgi.connection_fd = lambda: uwsgi_pypy_current_wsgi_req().fd
"""
uwsgi.wait_fd_read(fd, timeout=0)
"""
def uwsgi_pypy_wait_fd_read(fd, timeout=0):
wsgi_req = uwsgi_pypy_current_wsgi_req();
if lib.async_add_fd_read(wsgi_req, fd, timeout) < 0:
raise Exception("unable to add fd %d to the event queue" % fd)
uwsgi.wait_fd_read = uwsgi_pypy_wait_fd_read
"""
uwsgi.wait_fd_write(fd, timeout=0)
"""
def uwsgi_pypy_wait_fd_write(fd, timeout=0):
wsgi_req = uwsgi_pypy_current_wsgi_req();
if lib.async_add_fd_write(wsgi_req, fd, timeout) < 0:
raise Exception("unable to add fd %d to the event queue" % fd)
uwsgi.wait_fd_write = uwsgi_pypy_wait_fd_write
"""
uwsgi.ready_fd()
"""
def uwsgi_pypy_ready_fd():
wsgi_req = uwsgi_pypy_current_wsgi_req();
return lib.uwsgi_ready_fd(wsgi_req)
uwsgi.ready_fd = uwsgi_pypy_ready_fd
"""
uwsgi.send(fd=None,data)
"""
def uwsgi_pypy_send(*args):
if len(args) == 0:
raise ValueError("uwsgi.send() takes at least 1 argument")
elif len(args) == 1:
wsgi_req = uwsgi_pypy_current_wsgi_req();
fd = wsgi_req.fd
data = args[0]
else:
fd = args[0]
data = args[1]
rlen = libc.write(fd, data, len(data))
if rlen <= 0:
raise IOError("unable to send data")
return rlen
uwsgi.send = uwsgi_pypy_send
"""
uwsgi.recv(fd=None,len)
"""
def uwsgi_pypy_recv(*args):
if len(args) == 0:
raise ValueError("uwsgi.recv() takes at least 1 argument")
elif len(args) == 1:
wsgi_req = uwsgi_pypy_current_wsgi_req();
fd = wsgi_req.fd
l = args[0]
else:
fd = args[0]
l = args[1]
data = ffi.new('char[%d]' % l)
rlen = libc.read(fd, data, l)
if rlen <= 0:
raise IOError("unable to receive data")
return ffi.string(data[0:rlen])
uwsgi.recv = uwsgi_pypy_recv
"""
uwsgi.close(fd)
"""
uwsgi.close = lambda fd: lib.close(fd)
"""
uwsgi.disconnect()
"""
uwsgi.disconnect = lambda: lib.uwsgi_disconnect(uwsgi_pypy_current_wsgi_req())
"""
uwsgi.websocket_recv()
"""
def uwsgi_pypy_websocket_recv():
wsgi_req = uwsgi_pypy_current_wsgi_req();
ub = lib.uwsgi_websocket_recv(wsgi_req);
if ub == ffi.NULL:
raise IOError("unable to receive websocket message")
ret = ffi.string(ub.buf, ub.pos)
lib.uwsgi_buffer_destroy(ub)
return ret
uwsgi.websocket_recv = uwsgi_pypy_websocket_recv
"""
uwsgi.websocket_recv_nb()
"""
def uwsgi_pypy_websocket_recv_nb():
wsgi_req = uwsgi_pypy_current_wsgi_req();
ub = lib.uwsgi_websocket_recv_nb(wsgi_req);
if ub == ffi.NULL:
raise IOError("unable to receive websocket message")
ret = ffi.string(ub.buf, ub.pos)
lib.uwsgi_buffer_destroy(ub)
return ret
uwsgi.websocket_recv_nb = uwsgi_pypy_websocket_recv_nb
"""
uwsgi.websocket_handshake(key, origin)
"""
def uwsgi_pypy_websocket_handshake(key, origin=''):
wsgi_req = uwsgi_pypy_current_wsgi_req();
if lib.uwsgi_websocket_handshake(wsgi_req, ffi.new('char[]', key), len(key), ffi.new('char[]',origin), len(origin)) < 0:
raise IOError("unable to complete websocket handshake")
uwsgi.websocket_handshake = uwsgi_pypy_websocket_handshake
"""
uwsgi.websocket_send(msg)
"""
def uwsgi_pypy_websocket_send(msg):
wsgi_req = uwsgi_pypy_current_wsgi_req();
if lib.uwsgi_websocket_send(wsgi_req, ffi.new('char[]', msg), len(msg)) < 0:
raise IOError("unable to send websocket message")
uwsgi.websocket_send = uwsgi_pypy_websocket_send
"""
uwsgi.chunked_read(timeout=0)
"""
def uwsgi_pypy_chunked_read(timeout=0):
wsgi_req = uwsgi_pypy_current_wsgi_req();
rlen = ffi.new("size_t*")
chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, timeout, 0)
if chunk == ffi.NULL:
raise IOError("unable to receive chunked part")
return ffi.string(chunk, rlen[0])
uwsgi.chunked_read = uwsgi_pypy_chunked_read
"""
uwsgi.chunked_read_nb()
"""
def uwsgi_pypy_chunked_read_nb():
wsgi_req = uwsgi_pypy_current_wsgi_req();
rlen = ffi.new("size_t*")
chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, 0, 1)
if chunk == ffi.NULL:
if lib.uwsgi_is_again() > 0:
return None
raise IOError("unable to receive chunked part")
return ffi.string(chunk, rlen[0])
uwsgi.chunked_read_nb = uwsgi_pypy_chunked_read_nb
"""
uwsgi.set_user_harakiri(sec)
"""
uwsgi.set_user_harakiri = lambda x: lib.set_user_harakiri(x)
print "Initialized PyPy with Python", sys.version
print "PyPy Home:", sys.prefix
"""
Continulets support
"""
# this is the dictionary of continulets (one per-core)
uwsgi_pypy_continulets = {}
def uwsgi_pypy_continulet_wrapper(cont):
lib.async_schedule_to_req_green()
@ffi.callback("void()")
def uwsgi_pypy_continulet_schedule():
id = lib.uwsgi.wsgi_req.async_id
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
# generate a new continulet
if not lib.uwsgi.wsgi_req.suspended:
from _continuation import continulet
uwsgi_pypy_continulets[id] = continulet(uwsgi_pypy_continulet_wrapper)
lib.uwsgi.wsgi_req.suspended = 1
# this is called in the main stack
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
# let's switch
uwsgi_pypy_continulets[id].switch()
# back to the main stack
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(ffi.NULL)
@ffi.callback("void(struct wsgi_request *)")
def uwsgi_pypy_continulet_switch(wsgi_req):
id = wsgi_req.async_id
modifier1 = wsgi_req.uh.modifier1;
# this is called in the current continulet
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(wsgi_req)
uwsgi_pypy_continulets[id].switch()
# back to the continulet
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(wsgi_req)
# update current running continulet
lib.uwsgi.wsgi_req = wsgi_req
def uwsgi_pypy_setup_continulets():
if lib.uwsgi.async <= 1:
raise Exception("pypy continulets require async mode !!!")
lib.uwsgi.schedule_to_main = uwsgi_pypy_continulet_switch
lib.uwsgi.schedule_to_req = uwsgi_pypy_continulet_schedule
print "*** PyPy Continulets engine loaded ***"
+10 -11
View File
@@ -1,13 +1,12 @@
import os,sys
from distutils import sysconfig
NAME='pypy'
GCC_LIST = ['../python/python_plugin', '../python/pyutils', '../python/pyloader', '../python/wsgi_handlers', '../python/wsgi_headers', '../python/wsgi_subhandler',
'../python/web3_subhandler', '../python/pump_subhandler','../python/gil', '../python/uwsgi_pymodule', '../python/profiler', '../python/symimporter']
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
CFLAGS.append('-DUWSGI_PYPY')
LIBS = ['-lpypy-c']
LDFLAGS = []
LIBS = []
GCC_LIST = ['pypy_plugin']
BINARY_LIST = [ ('uwsgi_pypy_setup','pypy_setup.py')]
CFLAGS = []
try:
import __pypy__
import sys
CFLAGS.append('-DUWSGI_PYPY_HOME="\\"%s\\""' % sys.prefix)
except:
pass
+2 -2
View File
@@ -5,7 +5,7 @@ extern struct uwsgi_python up;
void gil_real_get() {
//uwsgi_log("LOCK %d\n", uwsgi.mywid);
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
#if !defined(PYTHREE)
PyEval_AcquireLock();
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_gil_key));
#else
@@ -17,7 +17,7 @@ void gil_real_get() {
void gil_real_release() {
//uwsgi_log("UNLOCK %d\n", uwsgi.mywid);
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
#if !defined(PYTHREE)
pthread_setspecific(up.upt_gil_key, (void *) PyThreadState_Swap(NULL));
PyEval_ReleaseLock();
#else
-4
View File
@@ -15,7 +15,6 @@ int PyFrame_GetLineNumber(PyFrameObject *frame) {
int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
#ifndef UWSGI_PYPY
static uint64_t last_ts = 0;
uint64_t now = uwsgi_micros();
uint64_t delta = 0;
@@ -42,14 +41,12 @@ int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, Py
PyEval_GetFuncName(arg), frame->f_code->co_argcount, frame->f_code->co_stacksize);
break;
}
#endif
return 0;
}
int uwsgi_python_tracer(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
#ifndef UWSGI_PYPY
static uint64_t last_ts = 0;
uint64_t now = uwsgi_micros();
uint64_t delta = 0;
@@ -64,7 +61,6 @@ int uwsgi_python_tracer(PyObject *obj, PyFrameObject *frame, int what, PyObject
last_ts = now;
uwsgi_log("[uWSGI Python profiler %llu] file %s line %d: %s argc:%d\n", (unsigned long long)delta, PyString_AsString(frame->f_code->co_filename), PyFrame_GetLineNumber(frame), PyString_AsString(frame->f_code->co_name), frame->f_code->co_argcount);
}
#endif
return 0;
}
-5
View File
@@ -672,10 +672,6 @@ PyObject *uwsgi_paste_loader(void *arg1) {
PyObject *uwsgi_eval_loader(void *arg1) {
#ifdef UWSGI_PYPY
uwsgi_log("the eval loader is currently not supported under PyPy !!!\n");
return NULL;
#else
char *code = (char *) arg1;
PyObject *wsgi_eval_module, *wsgi_eval_callable = NULL;
@@ -731,7 +727,6 @@ PyObject *uwsgi_eval_loader(void *arg1) {
}
return wsgi_eval_callable;
#endif
}
+12 -45
View File
@@ -52,11 +52,7 @@ void uwsgi_opt_pyrun(char *opt, char *value, void *foobar) {
}
void uwsgi_opt_pyver(char *opt, char *foo, void *bar) {
#ifndef UWSGI_PYPY
const char *version = Py_GetVersion();
#else
const char *version = PYPY_VERSION;
#endif
const char *space = strchr(version, ' ');
if (space) {
fprintf(stdout, "%.*s\n", (int) (space-version), version);
@@ -136,9 +132,7 @@ struct uwsgi_option uwsgi_python_options[] = {
{"ini-paste-logged", required_argument, 0, "load a paste.deploy config file containing uwsgi section (load loggers too)", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
{"reload-os-env", no_argument, 0, "force reload of os.environ at each request", uwsgi_opt_true, &up.reload_os_env, 0},
#ifndef __CYGWIN__
#ifndef UWSGI_PYPY
{"no-site", no_argument, 0, "do not import site module", uwsgi_opt_true, &Py_NoSiteFlag, 0},
#endif
#endif
{"pyshell", optional_argument, 0, "run an interactive python shell in the uWSGI environment", uwsgi_opt_pyshell, NULL, 0},
{"pyshell-oneshot", optional_argument, 0, "run an interactive python shell in the uWSGI environment (one-shot variant)", uwsgi_opt_pyshell, NULL, 0},
@@ -147,9 +141,8 @@ struct uwsgi_option uwsgi_python_options[] = {
{"py", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
{"pyrun", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
#ifndef UWSGI_PYPY
{"py-tracebacker", required_argument, 0, "enable the uWSGI python tracebacker", uwsgi_opt_set_str, &up.tracebacker, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
#endif
{"py-auto-reload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
{"py-autoreload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
{"python-auto-reload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
@@ -183,7 +176,6 @@ PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARG
int uwsgi_python_init() {
#ifndef UWSGI_PYPY
char *pyversion = strchr(Py_GetVersion(), '\n');
if (!pyversion) {
uwsgi_log_initial("Python version: %s\n", Py_GetVersion());
@@ -191,9 +183,6 @@ int uwsgi_python_init() {
else {
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
}
#else
uwsgi_log_initial("PyPy version: %s\n", PYPY_VERSION);
#endif
if (up.home != NULL) {
#ifdef PYTHREE
@@ -245,9 +234,7 @@ pep405:
#endif
#ifndef UWSGI_PYPY
Py_OptimizeFlag = up.optimize;
#endif
Py_Initialize();
@@ -286,9 +273,6 @@ void uwsgi_python_reset_random_seed() {
random_seed = PyDict_GetItemString(random_dict, "seed");
if (random_seed) {
PyObject *random_args = PyTuple_New(1);
#ifdef UWSGI_PYPY
Py_INCREF(Py_None);
#endif
// pass no args
PyTuple_SetItem(random_args, 0, Py_None);
PyEval_CallObject(random_seed, random_args);
@@ -375,13 +359,11 @@ void uwsgi_python_post_fork() {
pthread_t par_tid;
pthread_create(&par_tid, NULL, uwsgi_python_autoreloader_thread, NULL);
}
#ifndef UWSGI_PYPY
if (up.tracebacker) {
// spawn the tracebacker thread
pthread_t ptb_tid;
pthread_create(&ptb_tid, NULL, uwsgi_python_tracebacker_thread, NULL);
}
#endif
}
UWSGI_RELEASE_GIL
@@ -390,10 +372,6 @@ UWSGI_RELEASE_GIL
PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
#ifdef UWSGI_PYPY
uwsgi_log("import by filename is currently not supported on PyPy !!!\n");
return NULL;
#else
FILE *pyfile;
struct _node *py_file_node = NULL;
PyObject *py_compiled_node, *py_file_module;
@@ -479,7 +457,6 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
Py_DECREF(py_compiled_node);
return py_file_module;
#endif
}
@@ -500,7 +477,11 @@ void init_uwsgi_vars() {
#ifdef PYTHREE
// fix stdout and stderr
PyObject *new_stdprint = PyFile_NewStdPrinter(2);
#ifdef HAS_NO_ERRORS_IN_PyFile_FromFd
PyObject *new_stdprint = PyFile_FromFd(2, NULL, "w", _IOLBF, NULL, NULL, 0);
#else
PyObject *new_stdprint = PyFile_FromFd(2, NULL, "w", _IOLBF, NULL, NULL, NULL, 0);
#endif
PyDict_SetItemString(pysys_dict, "stdout", new_stdprint);
PyDict_SetItemString(pysys_dict, "__stdout__", new_stdprint);
PyDict_SetItemString(pysys_dict, "stderr", new_stdprint);
@@ -1067,13 +1048,11 @@ void uwsgi_python_init_apps() {
UWSGI_GET_GIL;
}
#ifndef UWSGI_PYPY
// prepare for stack suspend/resume
if (uwsgi.async > 1) {
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
}
#endif
// setup app loaders
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
@@ -1160,7 +1139,6 @@ next:
init_uwsgi_app(LOADER_UWSGI, up.wsgi_lite, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI_LITE);
}
#ifndef UWSGI_PYPY
if (uwsgi.profiler) {
if (!strcmp(uwsgi.profiler, "pycall")) {
PyEval_SetProfile(uwsgi_python_profiler_call, NULL);
@@ -1169,7 +1147,6 @@ next:
PyEval_SetTrace(uwsgi_python_tracer, NULL);
}
}
#endif
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
if (uwsgi_dict) {
@@ -1425,7 +1402,6 @@ void *uwsgi_python_autoreloader_thread(void *foobar) {
return NULL;
}
#ifndef UWSGI_PYPY
void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
PyGILState_STATE pgst = PyGILState_Ensure();
@@ -1442,7 +1418,6 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
}
}
#endif
char *uwsgi_python_code_string(char *id, char *code, char *function, char *key, uint16_t keylen) {
@@ -1637,7 +1612,6 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si
return -1;
}
#ifndef UWSGI_PYPY
void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
PyGILState_STATE pgst = PyGILState_Ensure();
@@ -1654,7 +1628,6 @@ void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
}
}
#endif
void uwsgi_python_fixup() {
// set hacky modifier 30
@@ -1668,7 +1641,6 @@ void uwsgi_python_hijack(void) {
// the pyshell will be execute only in the first worker
#ifndef UWSGI_PYPY
FILE *pyfile;
if (up.pyrun) {
uwsgi.workers[uwsgi.mywid].hijacked = 1;
@@ -1682,7 +1654,6 @@ void uwsgi_python_hijack(void) {
// could be never executed
exit(0);
}
#endif
if (up.pyshell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
uwsgi.workers[uwsgi.mywid].hijacked = 0;
@@ -1708,9 +1679,7 @@ void uwsgi_python_hijack(void) {
else {
PyImport_ImportModule("readline");
#ifndef UWSGI_PYPY
ret = PyRun_InteractiveLoop(stdin, "uwsgi");
#endif
}
if (up.pyshell_oneshot) {
exit(UWSGI_DE_HIJACKED_CODE);
@@ -1787,7 +1756,12 @@ void uwsgi_python_harakiri(int wid) {
}
}
/*
# you can use this logger to offload logging to python
# be sure to configure it to not log to stderr otherwise you will generate a loop
import logging
logging.basicConfig(filename='/tmp/pippo.log')
*/
ssize_t uwsgi_python_logger(struct uwsgi_logger *ul, char *message, size_t len) {
if (!Py_IsInitialized()) return -1;
@@ -1830,13 +1804,8 @@ void uwsgi_python_on_load() {
uwsgi_register_logger("python", uwsgi_python_logger);
}
#ifndef UWSGI_PYPY
struct uwsgi_plugin python_plugin = {
.name = "python",
#else
struct uwsgi_plugin pypy_plugin = {
.name = "pypy",
#endif
.alias = "python",
.modifier1 = 0,
.init = uwsgi_python_init,
@@ -1858,10 +1827,8 @@ struct uwsgi_plugin pypy_plugin = {
.magic = uwsgi_python_magic,
#ifndef UWSGI_PYPY
.suspend = uwsgi_python_suspend,
.resume = uwsgi_python_resume,
#endif
.harakiri = uwsgi_python_harakiri,
+5 -4
View File
@@ -10,14 +10,14 @@ int manage_python_response(struct wsgi_request *wsgi_req) {
char *uwsgi_python_get_exception_type(PyObject *exc) {
char *class_name = NULL;
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
#if !defined(PYTHREE)
if (PyClass_Check(exc)) {
class_name = PyString_AsString( ((PyClassObject*)(exc))->cl_name );
}
else {
#endif
class_name = (char *) ((PyTypeObject*)exc)->tp_name;
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
#if !defined(PYTHREE)
}
#endif
@@ -301,8 +301,9 @@ void init_pyargv() {
#endif
if (*ap != '\0') {
#ifdef PYTHREE
mbstowcs( wcargv + strlen(ap), ap, strlen(ap));
up.py_argv[up.argc] = wcargv + strlen(ap);
mbstowcs( wcargv, ap, strlen(ap));
up.py_argv[up.argc] = wcargv;
wcargv += strlen(ap) + 1;
#else
up.py_argv[up.argc] = ap;
#endif
-4
View File
@@ -1,7 +1,5 @@
#include "uwsgi_python.h"
#ifndef UWSGI_PYPY
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
@@ -806,5 +804,3 @@ int uwsgi_init_symbol_import() {
return 0;
}
#endif
+48 -9
View File
@@ -1063,6 +1063,42 @@ PyObject *py_uwsgi_websocket_send(PyObject * self, PyObject * args) {
return Py_None;
}
PyObject *py_uwsgi_chunked_read(PyObject * self, PyObject * args) {
int timeout = 0;
if (!PyArg_ParseTuple(args, "|i:chunked_read", &timeout)) {
return NULL;
}
size_t len = 0;
struct wsgi_request *wsgi_req = py_current_wsgi_req();
UWSGI_RELEASE_GIL
char *chunk = uwsgi_chunked_read(wsgi_req, &len, timeout, 0);
UWSGI_GET_GIL
if (!chunk) {
return PyErr_Format(PyExc_IOError, "unable to receive chunked part");
}
return PyString_FromStringAndSize(chunk, len);
}
PyObject *py_uwsgi_chunked_read_nb(PyObject * self, PyObject * args) {
size_t len = 0;
struct wsgi_request *wsgi_req = py_current_wsgi_req();
UWSGI_RELEASE_GIL
char *chunk = uwsgi_chunked_read(wsgi_req, &len, 0, 1);
UWSGI_GET_GIL
if (!chunk) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
Py_INCREF(Py_None);
return Py_None;
}
return PyErr_Format(PyExc_IOError, "unable to receive chunked part");
}
return PyString_FromStringAndSize(chunk, len);
}
PyObject *py_uwsgi_websocket_recv(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = py_current_wsgi_req();
UWSGI_RELEASE_GIL
@@ -2234,17 +2270,15 @@ PyObject *py_uwsgi_disconnect(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = py_current_wsgi_req();
#ifdef UWSGI_DEBUG
uwsgi_log("disconnecting worker %d (pid :%d) from session...\n", uwsgi.mywid, uwsgi.mypid);
#endif
uwsgi_disconnect(wsgi_req);
if (wsgi_req->socket) {
wsgi_req->socket->proto_close(wsgi_req);
}
wsgi_req->fd_closed = 1;
Py_INCREF(Py_None);
return Py_None;
}
Py_INCREF(Py_True);
return Py_True;
PyObject *py_uwsgi_ready_fd(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = py_current_wsgi_req();
return PyInt_FromLong(uwsgi_ready_fd(wsgi_req));
}
PyObject *py_uwsgi_parse_file(PyObject * self, PyObject * args) {
@@ -2484,6 +2518,11 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"websocket_send", py_uwsgi_websocket_send, METH_VARARGS, ""},
{"websocket_handshake", py_uwsgi_websocket_handshake, METH_VARARGS, ""},
{"chunked_read", py_uwsgi_chunked_read, METH_VARARGS, ""},
{"chunked_read_nb", py_uwsgi_chunked_read_nb, METH_VARARGS, ""},
{"ready_fd", py_uwsgi_ready_fd, METH_VARARGS, ""},
{NULL, NULL},
};
+4
View File
@@ -22,6 +22,10 @@
#define HAS_NOT_PyFrame_GetLineNumber
#endif
#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0
#define HAS_NO_ERRORS_IN_PyFile_FromFd
#endif
#if PY_MAJOR_VERSION > 2
#define PYTHREE
#endif
-4
View File
@@ -14,10 +14,6 @@ NAME='python'
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter', 'tracebacker']
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
if 'pypy_version_info' in sys.__dict__:
CFLAGS.append('-DUWSGI_PYPY')
LDFLAGS = []
if not 'UWSGI_PYTHON_NOLIB' in os.environ:
+9 -1
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
PyObject *uwsgi_Input_iter(PyObject *self) {
@@ -339,7 +340,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
}
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, python_plugin.modifier1)) == -1) {
if (wsgi_req->dynamic) {
UWSGI_GET_GIL
if (uwsgi.single_interpreter) {
@@ -350,6 +351,12 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
UWSGI_RELEASE_GIL
}
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
if (uwsgi_apps[uwsgi.default_app].modifier1 == python_plugin.modifier1) {
wsgi_req->app_id = uwsgi.default_app;
}
}
}
if (wsgi_req->dynamic) {
@@ -358,6 +365,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
}
if (wsgi_req->app_id == -1) {
uwsgi_500(wsgi_req);
uwsgi_log("--- no python application found, check your startup logs for errors ---\n");
+2 -1
View File
@@ -80,7 +80,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
Py_DECREF(zero);
#endif
return PyErr_Format(PyExc_TypeError, "unable to set HTTP status line");
goto end;
}
#ifdef PYTHREE
@@ -193,6 +193,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
UWSGI_GET_GIL
}
end:
Py_INCREF(up.wsgi_writeout);
return up.wsgi_writeout;
}
+59 -8
View File
@@ -4,6 +4,44 @@ extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern PyTypeObject uwsgi_InputType;
/*
this is a hack for supporting non-file object passed to wsgi.file_wrapper
*/
static void uwsgi_python_consume_file_wrapper_read(struct wsgi_request *wsgi_req, PyObject *pychunk) {
PyObject *read_method_args = NULL;
PyObject *read_method = PyObject_GetAttrString(pychunk, "read");
if (wsgi_req->sendfile_fd_chunk > 0) {
read_method_args = PyTuple_New(1);
PyTuple_SetItem(read_method_args, 0, PyInt_FromLong(wsgi_req->sendfile_fd_chunk));
}
else {
read_method_args = PyTuple_New(0);
}
for(;;) {
PyObject *read_method_output = PyEval_CallObject(read_method, read_method_args);
if (PyErr_Occurred()) {
uwsgi_manage_exception(wsgi_req, 0);
break;
}
if (!read_method_output) break;
if (PyString_Check(read_method_output)) {
char *content = PyString_AsString(read_method_output);
size_t content_len = PyString_Size(read_method_output);
if (content_len == 0) {
Py_DECREF(read_method_output);
break;
}
UWSGI_RELEASE_GIL
uwsgi_response_write_body_do(wsgi_req, content, content_len);
UWSGI_GET_GIL
}
Py_DECREF(read_method_output);
if (wsgi_req->sendfile_fd_chunk == 0) break;
}
Py_DECREF(read_method_args);
Py_DECREF(read_method);
}
void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
@@ -143,10 +181,16 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
}
if (wsgi_req->sendfile_obj == wsgi_req->async_result && wsgi_req->sendfile_fd != -1) {
UWSGI_RELEASE_GIL
uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0);
UWSGI_GET_GIL
if (wsgi_req->sendfile_obj == wsgi_req->async_result) {
if (wsgi_req->sendfile_fd >= 0) {
UWSGI_RELEASE_GIL
uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0);
UWSGI_GET_GIL
}
// we do not have an iterable, check for read() method
else if (PyObject_HasAttrString((PyObject *)wsgi_req->async_result, "read")) {
uwsgi_python_consume_file_wrapper_read(wsgi_req, (PyObject *)wsgi_req->async_result);
}
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
}
@@ -190,10 +234,17 @@ exception:
}
}
else if (wsgi_req->sendfile_obj == pychunk && wsgi_req->sendfile_fd != -1) {
UWSGI_RELEASE_GIL
uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0);
UWSGI_GET_GIL
else if (wsgi_req->sendfile_obj == pychunk) {
if (wsgi_req->sendfile_fd >= 0) {
UWSGI_RELEASE_GIL
uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0);
UWSGI_GET_GIL
}
// we do not have an iterable, check for read() method
else if (PyObject_HasAttrString(pychunk, "read")) {
uwsgi_python_consume_file_wrapper_read(wsgi_req, pychunk);
}
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
Py_DECREF(pychunk);
+60 -51
View File
@@ -7,7 +7,7 @@ extern struct uwsgi_plugin rack_plugin;
#define uwsgi_rack_api(x, y, z) rb_define_module_function(rb_uwsgi_embedded, x, y, z)
VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
static VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
Check_Type(rbmessage, T_STRING);
char *message = RSTRING_PTR(rbmessage);
@@ -26,7 +26,14 @@ VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
return Qnil;
}
VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
static VALUE rack_uwsgi_user_harakiri(VALUE *class, VALUE sec) {
Check_Type(sec, T_FIXNUM);
set_user_harakiri(NUM2INT(sec));
return Qnil;
}
static VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
Check_Type(msg, T_STRING);
@@ -35,7 +42,7 @@ VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
return Qnil;
}
VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
static VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
if (uwsgi.i_am_a_spooler) {
return Qtrue;
}
@@ -43,7 +50,7 @@ VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
}
#ifdef UWSGI_SSL
VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
static VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
Check_Type(legion_name, T_STRING);
if (uwsgi_legion_i_am_the_lord(RSTRING_PTR(legion_name))) {
return Qtrue;
@@ -54,7 +61,7 @@ VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
static VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
Check_Type(rbname, T_STRING);
char *name = RSTRING_PTR(rbname);
@@ -63,7 +70,7 @@ VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
return Qnil;
}
VALUE rack_uwsgi_mem(VALUE *class) {
static VALUE rack_uwsgi_mem(VALUE *class) {
uint64_t rss=0, vsz = 0;
VALUE ml = rb_ary_new2(2);
@@ -77,23 +84,23 @@ VALUE rack_uwsgi_mem(VALUE *class) {
}
VALUE rack_uwsgi_request_id(VALUE *class) {
static VALUE rack_uwsgi_request_id(VALUE *class) {
return ULONG2NUM(uwsgi.workers[uwsgi.mywid].requests);
}
VALUE rack_uwsgi_worker_id(VALUE *class) {
static VALUE rack_uwsgi_worker_id(VALUE *class) {
return INT2NUM(uwsgi.mywid);
}
VALUE rack_uwsgi_mule_id(VALUE *class) {
static VALUE rack_uwsgi_mule_id(VALUE *class) {
return INT2NUM(uwsgi.muleid);
}
VALUE rack_uwsgi_logsize(VALUE *class) {
static VALUE rack_uwsgi_logsize(VALUE *class) {
return ULONG2NUM(uwsgi.shared->logsize);
}
VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
int fd = -1;
int mule_id = -1;
@@ -151,7 +158,7 @@ VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
static int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
Check_Type(key, T_SYMBOL);
ID key_id = SYM2ID(key);
const char *key_name = rb_id2name(key_id);
@@ -172,7 +179,7 @@ int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
return 0;
}
VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
int manage_signals = 1;
int manage_farms = 1;
@@ -228,7 +235,7 @@ VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
}
VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
int lock_num = 0;
@@ -246,7 +253,7 @@ VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
return Qnil;
}
VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
int lock_num = 0;
@@ -268,7 +275,7 @@ VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
VALUE rack_uwsgi_cache_set(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_set(int argc, VALUE *argv, VALUE *class) {
if (argc < 2) goto error;
@@ -304,7 +311,7 @@ error:
}
VALUE rack_uwsgi_cache_update(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_update(int argc, VALUE *argv, VALUE *class) {
if (argc < 2) goto error;
@@ -341,7 +348,7 @@ error:
}
VALUE rack_uwsgi_cache_set_exc(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_set_exc(int argc, VALUE *argv, VALUE *class) {
VALUE ret = rack_uwsgi_cache_set(argc, argv, class);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to set value in uWSGI cache");
@@ -349,7 +356,7 @@ VALUE rack_uwsgi_cache_set_exc(int argc, VALUE *argv, VALUE *class) {
return ret;
}
VALUE rack_uwsgi_cache_update_exc(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_update_exc(int argc, VALUE *argv, VALUE *class) {
VALUE ret = rack_uwsgi_cache_update(argc, argv, class);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to update value in uWSGI cache");
@@ -357,7 +364,7 @@ VALUE rack_uwsgi_cache_update_exc(int argc, VALUE *argv, VALUE *class) {
return ret;
}
VALUE rack_uwsgi_cache_del(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_del(int argc, VALUE *argv, VALUE *class) {
if (argc == 0) goto error;
@@ -383,7 +390,7 @@ error:
return Qnil;
}
VALUE rack_uwsgi_cache_del_exc(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_del_exc(int argc, VALUE *argv, VALUE *class) {
VALUE ret = rack_uwsgi_cache_del(argc, argv, class);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to delete object from uWSGI cache");
@@ -393,7 +400,7 @@ VALUE rack_uwsgi_cache_del_exc(int argc, VALUE *argv, VALUE *class) {
VALUE rack_uwsgi_cache_exists(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_exists(int argc, VALUE *argv, VALUE *class) {
if (argc == 0) goto error;
@@ -421,7 +428,7 @@ error:
VALUE rack_uwsgi_cache_clear(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_clear(int argc, VALUE *argv, VALUE *class) {
char *cache = NULL;
@@ -437,7 +444,7 @@ VALUE rack_uwsgi_cache_clear(int argc, VALUE *argv, VALUE *class) {
return Qnil;
}
VALUE rack_uwsgi_cache_clear_exc(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_clear_exc(int argc, VALUE *argv, VALUE *class) {
VALUE ret = rack_uwsgi_cache_clear(argc, argv, class);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to clear the uWSGI cache");
@@ -447,7 +454,7 @@ VALUE rack_uwsgi_cache_clear_exc(int argc, VALUE *argv, VALUE *class) {
VALUE rack_uwsgi_cache_get(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_get(int argc, VALUE *argv, VALUE *class) {
if (argc == 0) goto error;
@@ -477,7 +484,7 @@ error:
}
VALUE rack_uwsgi_cache_get_exc(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_get_exc(int argc, VALUE *argv, VALUE *class) {
VALUE ret = rack_uwsgi_cache_get(argc, argv, class);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to get value from uWSGI cache");
@@ -488,7 +495,7 @@ VALUE rack_uwsgi_cache_get_exc(int argc, VALUE *argv, VALUE *class) {
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
static VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(rbmin, T_FIXNUM);
@@ -514,7 +521,7 @@ VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhou
VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
static VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(secs, T_FIXNUM);
@@ -532,7 +539,7 @@ VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
static VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(secs, T_FIXNUM);
@@ -550,7 +557,7 @@ VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
}
VALUE rack_uwsgi_alarm(VALUE *class, VALUE alarm, VALUE msg) {
static VALUE rack_uwsgi_alarm(VALUE *class, VALUE alarm, VALUE msg) {
Check_Type(alarm, T_STRING);
Check_Type(msg, T_STRING);
@@ -560,7 +567,7 @@ VALUE rack_uwsgi_alarm(VALUE *class, VALUE alarm, VALUE msg) {
return Qnil;
}
VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
static VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(rbfilename, T_STRING);
@@ -577,7 +584,7 @@ VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename
}
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
static VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
Check_Type(arg1, T_FIXNUM);
Check_Type(arg2, T_FIXNUM);
@@ -595,7 +602,7 @@ VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
return Qtrue;
}
VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
static VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
Check_Type(arg1, T_FIXNUM);
Check_Type(arg2, T_FIXNUM);
@@ -612,7 +619,7 @@ VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
return Qtrue;
}
VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
static VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
Check_Type(arg, T_STRING);
@@ -622,7 +629,7 @@ VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
}
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
static VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
Check_Type(arg, T_FIXNUM);
@@ -636,7 +643,7 @@ VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
return Qtrue;
}
VALUE uwsgi_ruby_masterpid(VALUE *class) {
static VALUE uwsgi_ruby_masterpid(VALUE *class) {
if (uwsgi.master_process) {
return INT2NUM(uwsgi.workers[0].pid);
@@ -644,7 +651,7 @@ VALUE uwsgi_ruby_masterpid(VALUE *class) {
return INT2NUM(0);
}
VALUE uwsgi_ruby_suspend(VALUE *class) {
static VALUE uwsgi_ruby_suspend(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -655,7 +662,7 @@ VALUE uwsgi_ruby_suspend(VALUE *class) {
}
VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
static VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
int wait_for_specific_signal = 0;
@@ -687,7 +694,7 @@ VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
return Qnil;
}
VALUE uwsgi_ruby_signal_received(VALUE *class) {
static VALUE uwsgi_ruby_signal_received(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -695,7 +702,7 @@ VALUE uwsgi_ruby_signal_received(VALUE *class) {
}
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
static VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
Check_Type(signum, T_FIXNUM);
@@ -708,7 +715,7 @@ VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
return Qfalse;
}
VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
static VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
char *node = NULL, *func;
uint16_t size = 0;
@@ -759,7 +766,7 @@ clear:
return Qnil;
}
VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
static VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
int rb_argc = 0;
@@ -785,7 +792,7 @@ clear:
return Qtrue;
}
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
static VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
Check_Type(signum, T_FIXNUM);
Check_Type(sigkind, T_STRING);
@@ -805,7 +812,7 @@ VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALU
}
VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
static VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
if (argc < 1) {
rb_raise(rb_eRuntimeError, "you have to specify a signum");
@@ -872,7 +879,7 @@ int rack_uwsgi_build_spool(VALUE rbkey, VALUE rbval, VALUE argv) {
}
VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
static VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
char spool_filename[1024];
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -926,10 +933,10 @@ VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
rb_hash_foreach(args, rack_uwsgi_build_spool, (VALUE) argv);
if (numprio) {
priority = uwsgi_num2str(numprio);
priority = uwsgi_num2str((int)numprio);
}
int ret = spool_request(uwsgi.spoolers, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, argv[0] - spool_buffer, priority, at, body, body_len);
int ret = spool_request(uwsgi.spoolers, spool_filename, (int)(uwsgi.workers[0].requests + 1), wsgi_req->async_id, spool_buffer, (int)(argv[0] - spool_buffer), priority, at, body, body_len);
if (priority) {
free(priority);
@@ -950,7 +957,7 @@ VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
}
VALUE uwsgi_ruby_websocket_handshake(int argc, VALUE *argv, VALUE *class) {
static VALUE uwsgi_ruby_websocket_handshake(int argc, VALUE *argv, VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -978,7 +985,7 @@ VALUE uwsgi_ruby_websocket_handshake(int argc, VALUE *argv, VALUE *class) {
return Qnil;
}
VALUE uwsgi_ruby_websocket_send(VALUE *class, VALUE *msg) {
static VALUE uwsgi_ruby_websocket_send(VALUE *class, VALUE *msg) {
Check_Type(msg, T_STRING);
char *message = RSTRING_PTR(msg);
size_t message_len = RSTRING_LEN(msg);
@@ -989,7 +996,7 @@ VALUE uwsgi_ruby_websocket_send(VALUE *class, VALUE *msg) {
return Qnil;
}
VALUE uwsgi_ruby_websocket_recv(VALUE *class) {
static VALUE uwsgi_ruby_websocket_recv(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_buffer *ub = uwsgi_websocket_recv(wsgi_req);
@@ -1003,7 +1010,7 @@ VALUE uwsgi_ruby_websocket_recv(VALUE *class) {
}
VALUE uwsgi_ruby_websocket_recv_nb(VALUE *class) {
static VALUE uwsgi_ruby_websocket_recv_nb(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_buffer *ub = uwsgi_websocket_recv_nb(wsgi_req);
@@ -1069,6 +1076,8 @@ void uwsgi_rack_init_api() {
uwsgi_rack_api("set_warning_message", rack_uwsgi_warning, 1);
uwsgi_rack_api("set_user_harakiri", rack_uwsgi_user_harakiri, 1);
uwsgi_rack_api("rpc", uwsgi_ruby_do_rpc, -1);
+7 -5
View File
@@ -141,13 +141,13 @@ static struct uwsgi_buffer *uwsgi_ruby_backtrace(struct wsgi_request *wsgi_req)
// ok let's start the C dance to parse the backtrace
char *colon = strchr(bt, ':');
if (!colon) continue;
filename = uwsgi_concat2n(bt, colon-bt, "", 0);
filename = uwsgi_concat2n(bt, (int) (colon-bt), "", 0);
uint16_t filename_len = colon-bt;
colon++; if (*colon == 0) goto error;
char *lineno_ptr = colon;
colon = strchr(lineno_ptr, ':');
if (!colon) goto error;
int64_t lineno = uwsgi_str_num(lineno_ptr, colon-lineno_ptr);
int64_t lineno = uwsgi_str_num(lineno_ptr, (int) (colon-lineno_ptr));
colon++; if (*colon == 0) goto error;
colon = strchr(lineno_ptr, '`');
if (!colon) goto error;
@@ -155,7 +155,7 @@ static struct uwsgi_buffer *uwsgi_ruby_backtrace(struct wsgi_request *wsgi_req)
char *function_ptr = colon;
char *function_end = strchr(function_ptr, '\'');
if (!function_end) goto error;
function = uwsgi_concat2n(function_ptr, function_end-function_ptr, "", 0);
function = uwsgi_concat2n(function_ptr, (int) (function_end-function_ptr), "", 0);
uint16_t function_len = function_end-function_ptr;
if (uwsgi_buffer_u16le(ub, filename_len)) goto error;
@@ -312,7 +312,7 @@ VALUE init_rack_app(VALUE);
VALUE rack_call_rpc_handler(VALUE args) {
VALUE rpc_args = rb_ary_entry(args, 1);
return rb_funcall2(rb_ary_entry(args, 0), rb_intern("call"), RARRAY_LEN(rpc_args), RARRAY_PTR(rpc_args));
return rb_funcall2(rb_ary_entry(args, 0), rb_intern("call"), (int) RARRAY_LEN(rpc_args), RARRAY_PTR(rpc_args));
}
@@ -888,7 +888,9 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
status = rb_obj_as_string(RARRAY_PTR(ret)[0]);
// get the status code
uwsgi_response_prepare_headers(wsgi_req, RSTRING_PTR(status), RSTRING_LEN(status));
if (uwsgi_response_prepare_headers(wsgi_req, RSTRING_PTR(status), RSTRING_LEN(status))) {
goto clear;
}
headers = RARRAY_PTR(ret)[1] ;
if (rb_respond_to( headers, rb_intern("each") )) {
+9 -4
View File
@@ -112,13 +112,15 @@ static ssize_t rr_xclient_write(struct corerouter_peer *peer) {
if (!len) return 0;
if (cr_write_complete_buf(peer, rr->xclient)) {
if (peer->session->main_peer->out) {
if (peer->session->main_peer->out_pos > 0) {
// (eventually) send previous data
peer->last_hook_read = rr_instance_read;
cr_write_to_main(peer, rr_write);
}
else {
// reset to standard behaviour
cr_reset_hooks(peer);
peer->in->pos = 0;
cr_reset_hooks_and_read(peer, rr_instance_read);
}
}
@@ -140,10 +142,10 @@ static ssize_t rr_xclient_read(struct corerouter_peer *peer) {
return -1;
}
// banner received (skip it, will be sent later)
size_t remains = peer->in->pos - (len - (i+1));
size_t remains = len - (i+1);
if (remains > 0) {
peer->session->main_peer->out = peer->in;
peer->session->main_peer->out_pos = remains;
peer->session->main_peer->out_pos = (peer->in->pos - remains) ;
}
cr_write_to_backend(peer, rr_xclient_write);
return len;
@@ -163,6 +165,8 @@ static ssize_t rr_instance_connected(struct corerouter_peer *peer) {
struct rawrouter_session *rr = (struct rawrouter_session *) cs;
cr_peer_connected(peer, "rr_instance_connected()");
peer->can_retry = 0;
if (rr->xclient) {
cr_reset_hooks_and_read(peer, rr_xclient_read);
return 1;
@@ -251,6 +255,7 @@ static int rawrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_ga
return -1;
}
peer->can_retry = 1;
cr_connect(peer, rr_instance_connected);
return 0;
}
+9
View File
@@ -56,6 +56,7 @@ struct uwsgi_router_cache_conf {
char *status_str;
int status;
char *no_offload;
};
// this is allocated for each transformation
@@ -189,6 +190,13 @@ static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_
if (uwsgi_response_add_expires(wsgi_req, expires)) goto error;
}
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
if (wsgi_req->socket->can_offload && !ur->custom && !urcc->no_offload) {
if (!uwsgi_offload_request_memory_do(wsgi_req, value, valsize)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
return UWSGI_ROUTE_BREAK;
}
}
uwsgi_response_write_body_do(wsgi_req, value, valsize);
free(value);
if (ur->custom)
@@ -369,6 +377,7 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
"content_encoding", &urcc->content_encoding,
"mime", &urcc->mime,
"name", &urcc->name,
"no_offload", &urcc->no_offload,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
+146
View File
@@ -0,0 +1,146 @@
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
extern struct uwsgi_server uwsgi;
/*
by Unbit
syntax:
route = /^foobar1(.*)/ hash:key=foo$1poo,algo=murmur2,var=MYHASH,items=node1;node2;node3
*/
struct uwsgi_router_hash_conf {
char *key;
size_t key_len;
char *var;
size_t var_len;
char *algo;
char *items;
size_t items_len;
};
static int uwsgi_routing_func_hash(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_hash_conf *urhc = (struct uwsgi_router_hash_conf *) ur->data2;
struct uwsgi_hash_algo *uha = uwsgi_hash_algo_get(urhc->algo);
if (!uha) {
uwsgi_log("[uwsgi-hash-router] unable to find hash algo \"%s\"\n", urhc->algo);
return UWSGI_ROUTE_BREAK;
}
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urhc->key, urhc->key_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uint32_t h = uha->func(ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
// now count the number of items
uint32_t items = 1;
size_t i, ilen = urhc->items_len;
for(i=0;i<ilen;i++) {
if (urhc->items[i] == ';') items++;
}
// skip last semicolon
if (urhc->items[ilen-1] == ';') items--;
uint32_t hashed_result = h % items;
uint32_t found = 0;
char *value = urhc->items;
uint16_t vallen = 0;
for(i=0;i<ilen;i++) {
if (!value) {
value = urhc->items + i;
}
if (urhc->items[i] == ';') {
if (found == hashed_result) {
vallen = (urhc->items+i) - value;
break;
}
value = NULL;
found++;
}
}
if (vallen == 0) {
// first item
if (hashed_result == 0) {
value = urhc->items;
vallen = urhc->items_len;
}
// last item
else {
vallen = (urhc->items + urhc->items_len) - value;
}
}
if (!vallen) {
uwsgi_log("[uwsgi-hash-router] BUG !!! unable to hash items\n");
return UWSGI_ROUTE_BREAK;
}
if (!uwsgi_req_append(wsgi_req, urhc->var, urhc->var_len, value, vallen)) {
uwsgi_log("[uwsgi-hash-router] unable to append hash var to the request\n");
return UWSGI_ROUTE_BREAK;
}
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_hash(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_hash;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_hash_conf *urhc = uwsgi_calloc(sizeof(struct uwsgi_router_hash_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"key", &urhc->key,
"var", &urhc->var,
"algo", &urhc->algo,
"items", &urhc->items,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (!urhc->key || !urhc->var || !urhc->items) {
uwsgi_log("invalid route syntax: you need to specify a hash key, a var and a set of items\n");
exit(1);
}
urhc->key_len = strlen(urhc->key);
urhc->var_len = strlen(urhc->var);
urhc->items_len = strlen(urhc->items);
if (!urhc->algo) urhc->algo = "djb33x";
ur->data2 = urhc;
return 0;
}
static void router_hash_register() {
uwsgi_register_router("hash", uwsgi_router_hash);
}
struct uwsgi_plugin router_hash_plugin = {
.name = "router_hash",
.on_load = router_hash_register,
};
#else
struct uwsgi_plugin router_hash_plugin = {
.name = "router_hash",
};
#endif
+6
View File
@@ -0,0 +1,6 @@
NAME='router_hash'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['router_hash']
+174 -33
View File
@@ -1,20 +1,24 @@
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
#define MEMCACHED_BUFSIZE 8192
extern struct uwsgi_server uwsgi;
/*
memcached internal router
memcached internal router and transformation
route = /^foobar1(.*)/ memcached:addr=127.0.0.1:11211,key=foo$1poo,type=body
route = /^foobar1(.*)/ memcached:addr=127.0.0.1:11211,key=foo$1poo
route = /^foobar1(.*)/ memcachedstore:addr=127.0.0.1:11211,key=foo$1poo
*/
struct uwsgi_router_memcached_conf {
char *addr;
size_t addr_len;
char *key;
size_t key_len;
@@ -22,12 +26,19 @@ struct uwsgi_router_memcached_conf {
char *content_type;
size_t content_type_len;
// 0 -> full, 1 -> body
char *type;
int type_num;
char *no_offload;
char *expires;
};
// this is allocated for each transformation
struct uwsgi_transformation_memcached_conf {
struct uwsgi_buffer *addr;
struct uwsgi_buffer *key;
char *expires;
};
static size_t memcached_firstline_parse(char *buf, size_t len) {
// check for "VALUE x 0 0"
if (len < 11) return 0;
@@ -48,6 +59,86 @@ static size_t memcached_firstline_parse(char *buf, size_t len) {
}
}
// store an item in memcached
static void memcached_store(char *addr, struct uwsgi_buffer *key, struct uwsgi_buffer *value, char *expires) {
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
int fd = uwsgi_connect(addr, 0, 1);
if (fd < 0) return;
// wait for connection
int ret = uwsgi.wait_write_hook(fd, timeout);
if (ret <= 0) goto end;
// build the request
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
if (uwsgi_buffer_append(ub, "set ", 4)) goto end2;
if (uwsgi_buffer_append(ub, key->buf, key->pos)) goto end2;
if (uwsgi_buffer_append(ub, " 0 " , 3)) goto end2;
if (uwsgi_buffer_append(ub, expires, strlen(expires))) goto end2;
if (uwsgi_buffer_append(ub, " " , 1)) goto end2;
if (uwsgi_buffer_num64(ub, value->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) goto end2;
if (uwsgi_write_true_nb(fd, value->buf, value->pos, timeout)) goto end2;
if (uwsgi_write_true_nb(fd, "\r\n", 2, timeout)) goto end2;
// we are not interested in command result... (ugly but it works)
end2:
uwsgi_buffer_destroy(ub);
end:
close(fd);
}
static int transform_memcached(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
struct uwsgi_transformation_memcached_conf *utmc = (struct uwsgi_transformation_memcached_conf *) ut->data;
struct uwsgi_buffer *ub = ut->chunk;
// store only successfull response
if (wsgi_req->write_errors == 0 && wsgi_req->status == 200 && ub->pos > 0) {
memcached_store(utmc->addr->buf, utmc->key, ub, utmc->expires);
}
// free resources
uwsgi_buffer_destroy(utmc->key);
uwsgi_buffer_destroy(utmc->addr);
free(utmc);
return 0;
}
// be tolerant on errors
static int uwsgi_routing_func_memcached_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_memcached_conf *urmc = (struct uwsgi_router_memcached_conf *) ur->data2;
struct uwsgi_transformation_memcached_conf *utmc = uwsgi_calloc(sizeof(struct uwsgi_transformation_memcached_conf));
// build key and name
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
utmc->key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->key, urmc->key_len);
if (!utmc->key) goto error;
utmc->addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->addr, urmc->addr_len);
if (!utmc->addr) goto error;
utmc->expires = urmc->expires;
uwsgi_add_transformation(wsgi_req, transform_memcached, utmc);
return UWSGI_ROUTE_NEXT;
error:
if (utmc->key) uwsgi_buffer_destroy(utmc->key);
if (utmc->addr) uwsgi_buffer_destroy(utmc->addr);
free(utmc);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
// this is the buffer for the memcached response
char buf[MEMCACHED_BUFSIZE];
@@ -62,13 +153,24 @@ static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uw
struct uwsgi_buffer *ub_key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->key, urmc->key_len);
if (!ub_key) return UWSGI_ROUTE_BREAK;
int fd = uwsgi_connect(urmc->addr, 0, 1);
if (fd < 0) { uwsgi_buffer_destroy(ub_key) ; goto end; }
struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->addr, urmc->addr_len);
if (!ub_addr) {
uwsgi_buffer_destroy(ub_key);
return UWSGI_ROUTE_BREAK;
}
int fd = uwsgi_connect(ub_addr->buf, 0, 1);
if (fd < 0) {
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
goto end;
}
// wait for connection;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
uwsgi_buffer_destroy(ub_key) ;
uwsgi_buffer_destroy(ub_addr);
close(fd);
goto end;
}
@@ -77,11 +179,13 @@ static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uw
char *cmd = uwsgi_concat3n("get ", 4, ub_key->buf, ub_key->pos, "\r\n", 2);
if (uwsgi_write_true_nb(fd, cmd, 6+ub_key->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
free(cmd);
close(fd);
goto end;
}
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
free(cmd);
// ok, start reading the response...
@@ -130,26 +234,34 @@ read:
goto end;
}
if (urmc->type_num == 1) {
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) { close(fd); goto end; }
if (uwsgi_response_add_content_type(wsgi_req, urmc->content_type, urmc->content_type_len)) { close(fd); goto end; }
if (uwsgi_response_add_content_length(wsgi_req, response_size)) { close(fd); goto end; }
}
// from now on, every error will trigger a BREAK...
// send headers
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
if (uwsgi_response_add_content_type(wsgi_req, urmc->content_type, urmc->content_type_len)) goto error;
if (uwsgi_response_add_content_length(wsgi_req, response_size)) goto error;
// the first chunk could already contains part of the body
size_t remains = pos-(found+2);
if (remains >= response_size) {
uwsgi_response_write_body_do(wsgi_req, buf+found+2, response_size);
close(fd);
goto end;
goto done;
}
// send what we have
if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) {
close(fd);
goto end;
}
if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) goto error;
// and now start reading til the output is consumed
response_size -= remains;
// try to offload via the pipe engine
if (wsgi_req->socket->can_offload && !ur->custom && !urmc->no_offload) {
if (!uwsgi_offload_request_pipe_do(wsgi_req, fd, response_size)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
return UWSGI_ROUTE_BREAK;
}
}
while(response_size > 0) {
ssize_t len = read(fd, buf, UMIN(MEMCACHED_BUFSIZE, response_size));
if (len > 0) goto write;
@@ -165,23 +277,22 @@ wait2:
}
goto error;
write:
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) {
goto error;
}
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) goto error;
response_size -= len;
}
done:
close(fd);
if (ur->custom)
return UWSGI_ROUTE_NEXT;
return UWSGI_ROUTE_BREAK;
error:
close(fd);
return UWSGI_ROUTE_BREAK;
end:
if (ur->custom)
return UWSGI_ROUTE_NEXT;
return UWSGI_ROUTE_BREAK;
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_memcached(struct uwsgi_route *ur, char *args) {
@@ -193,27 +304,23 @@ static int uwsgi_router_memcached(struct uwsgi_route *ur, char *args) {
"addr", &urmc->addr,
"key", &urmc->key,
"content_type", &urmc->content_type,
"type", &urmc->type, NULL)) {
"no_offload", &urmc->no_offload,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (!urmc->key || !urmc->addr) {
uwsgi_log("invalid route syntax: you need to specify a memcached address and key pattern\n");
exit(1);
return -1;
}
urmc->key_len = strlen(urmc->key);
urmc->addr_len = strlen(urmc->addr);
if (!urmc->type) urmc->type = "full";
if (!urmc->content_type) urmc->content_type = "text/html";
urmc->content_type_len = strlen(urmc->content_type);
if (!strcmp(urmc->type, "body")) {
urmc->type_num = 1;
}
ur->data2 = urmc;
return 0;
}
@@ -224,12 +331,46 @@ static int uwsgi_router_memcached_continue(struct uwsgi_route *ur, char *args) {
return 0;
}
static int uwsgi_router_memcached_store(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_memcached_store;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_memcached_conf *urmc = uwsgi_calloc(sizeof(struct uwsgi_router_memcached_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"addr", &urmc->addr,
"key", &urmc->key,
"expires", &urmc->expires, NULL)) {
uwsgi_log("invalid memcachedstore route syntax: %s\n", args);
return -1;
}
if (!urmc->key || !urmc->addr) {
uwsgi_log("invalid memcachedstore route syntax: you need to specify an address and a key\n");
return -1;
}
urmc->key_len = strlen(urmc->key);
urmc->addr_len = strlen(urmc->addr);
if (!urmc->expires) urmc->expires = "0";
ur->data2 = urmc;
return 0;
}
static void router_memcached_register() {
uwsgi_register_router("memcached", uwsgi_router_memcached);
uwsgi_register_router("memcached-continue", uwsgi_router_memcached_continue);
uwsgi_register_router("memcachedstore", uwsgi_router_memcached_store);
uwsgi_register_router("memcached-store", uwsgi_router_memcached_store);
}
#endif
struct uwsgi_plugin router_memcached_plugin = {
.name = "router_memcached",
#ifdef UWSGI_ROUTING
.on_load = router_memcached_register,
#endif
};
+374
View File
@@ -0,0 +1,374 @@
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
#define REDIS_BUFSIZE 8192
extern struct uwsgi_server uwsgi;
/*
redis internal router and transformation
route = /^foobar1(.*)/ redis:addr=127.0.0.1:11211,key=foo$1poo
route = /^foobar1(.*)/ redisstore:addr=127.0.0.1:11211,key=foo$1poo
*/
struct uwsgi_router_redis_conf {
char *addr;
size_t addr_len;
char *key;
size_t key_len;
char *content_type;
size_t content_type_len;
char *no_offload;
char *expires;
};
// this is allocated for each transformation
struct uwsgi_transformation_redis_conf {
struct uwsgi_buffer *addr;
struct uwsgi_buffer *key;
char *expires;
};
static size_t redis_firstline_parse(char *buf, size_t len) {
// check for "$0"
if (len < 2) return 0;
if (buf[0] != '$') return 0;
if (buf[1] == '-') return 0;
return uwsgi_str_num(buf + 1, len - 1);
}
// store an item in redis
static void redis_store(char *addr, struct uwsgi_buffer *key, struct uwsgi_buffer *value, char *expires) {
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
int fd = uwsgi_connect(addr, 0, 1);
if (fd < 0) return;
// wait for connection
int ret = uwsgi.wait_write_hook(fd, timeout);
if (ret <= 0) goto end;
// build the request
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
if (uwsgi_buffer_append(ub, "*3\r\n$3\r\nSET\r\n$", 14)) goto end2;
if (uwsgi_buffer_num64(ub, key->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_buffer_append(ub, key->buf, key->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n$" , 3)) goto end2;
if (uwsgi_buffer_num64(ub, value->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) goto end2;
if (uwsgi_write_true_nb(fd, value->buf, value->pos, timeout)) goto end2;
ub->pos = 0;
if (strcmp(expires, "0")) {
if (uwsgi_buffer_append(ub, "\r\n*3\r\n$6\r\nEXPIRE\r\n$" , 19)) goto end2;
if (uwsgi_buffer_num64(ub, key->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_buffer_append(ub, key->buf, key->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n$" , 3)) goto end2;
if (uwsgi_buffer_num64(ub, strlen(expires))) goto end2;
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_buffer_append(ub, expires, strlen(expires))) goto end2;
}
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) goto end2;
// we are not interested in command result... (ugly but it works)
end2:
uwsgi_buffer_destroy(ub);
end:
close(fd);
}
static int transform_redis(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
struct uwsgi_transformation_redis_conf *utrc = (struct uwsgi_transformation_redis_conf *) ut->data;
struct uwsgi_buffer *ub = ut->chunk;
// store only successfull response
if (wsgi_req->write_errors == 0 && wsgi_req->status == 200 && ub->pos > 0) {
redis_store(utrc->addr->buf, utrc->key, ub, utrc->expires);
}
// free resources
uwsgi_buffer_destroy(utrc->key);
uwsgi_buffer_destroy(utrc->addr);
free(utrc);
return 0;
}
// be tolerant on errors
static int uwsgi_routing_func_redis_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_redis_conf *urrc = (struct uwsgi_router_redis_conf *) ur->data2;
struct uwsgi_transformation_redis_conf *utrc = uwsgi_calloc(sizeof(struct uwsgi_transformation_redis_conf));
// build key and name
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
utrc->key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->key, urrc->key_len);
if (!utrc->key) goto error;
utrc->addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->addr, urrc->addr_len);
if (!utrc->addr) goto error;
utrc->expires = urrc->expires;
uwsgi_add_transformation(wsgi_req, transform_redis, utrc);
return UWSGI_ROUTE_NEXT;
error:
if (utrc->key) uwsgi_buffer_destroy(utrc->key);
if (utrc->addr) uwsgi_buffer_destroy(utrc->addr);
free(utrc);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_routing_func_redis(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
// this is the buffer for the redis response
char buf[REDIS_BUFSIZE];
size_t i;
char last_char = 0;
struct uwsgi_router_redis_conf *urrc = (struct uwsgi_router_redis_conf *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->key, urrc->key_len);
if (!ub_key) return UWSGI_ROUTE_BREAK;
struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->addr, urrc->addr_len);
if (!ub_addr) {
uwsgi_buffer_destroy(ub_key);
return UWSGI_ROUTE_BREAK;
}
int fd = uwsgi_connect(ub_addr->buf, 0, 1);
if (fd < 0) {
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
goto end;
}
// wait for connection;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
uwsgi_buffer_destroy(ub_key) ;
uwsgi_buffer_destroy(ub_addr);
close(fd);
goto end;
}
// build the request and send it
char *cmd = uwsgi_concat3n("get ", 4, ub_key->buf, ub_key->pos, "\r\n", 2);
if (uwsgi_write_true_nb(fd, cmd, 6+ub_key->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
free(cmd);
close(fd);
goto end;
}
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
free(cmd);
// ok, start reading the response...
// first we need to get a full line;
size_t found = 0;
size_t pos = 0;
for(;;) {
ssize_t len = read(fd, buf + pos, REDIS_BUFSIZE - pos);
if (len > 0) {
pos += len;
goto read;
}
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
}
close(fd);
goto end;
wait:
ret = uwsgi.wait_read_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
// when we have a chunk try to read the first line
if (ret > 0) {
len = read(fd, buf + pos, REDIS_BUFSIZE - pos);
if (len > 0) {
pos += len;
goto read;
}
}
close(fd);
goto end;
read:
for(i=0;i<pos;i++) {
if (last_char == '\r' && buf[i] == '\n') {
found = i-1;
break;
}
last_char = buf[i];
}
if (found) break;
}
// ok parse the first line
size_t response_size = redis_firstline_parse(buf, found);
if (response_size == 0) {
close(fd);
goto end;
}
// from now on, every error will trigger a BREAK...
// send headers
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
if (uwsgi_response_add_content_type(wsgi_req, urrc->content_type, urrc->content_type_len)) goto error;
if (uwsgi_response_add_content_length(wsgi_req, response_size)) goto error;
// the first chunk could already contains part of the body
size_t remains = pos-(found+2);
if (remains >= response_size) {
uwsgi_response_write_body_do(wsgi_req, buf+found+2, response_size);
goto done;
}
// send what we have
if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) goto error;
// and now start reading til the output is consumed
response_size -= remains;
// try to offload via the pipe engine
if (wsgi_req->socket->can_offload && !ur->custom && !urrc->no_offload) {
if (!uwsgi_offload_request_pipe_do(wsgi_req, fd, response_size)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
return UWSGI_ROUTE_BREAK;
}
}
while(response_size > 0) {
ssize_t len = read(fd, buf, UMIN(REDIS_BUFSIZE, response_size));
if (len > 0) goto write;
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait2;
}
goto error;
wait2:
ret = uwsgi.wait_read_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret > 0) {
len = read(fd, buf, UMIN(REDIS_BUFSIZE, response_size));
if (len > 0) goto write;
}
goto error;
write:
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) goto error;
response_size -= len;
}
done:
close(fd);
if (ur->custom)
return UWSGI_ROUTE_NEXT;
return UWSGI_ROUTE_BREAK;
error:
close(fd);
return UWSGI_ROUTE_BREAK;
end:
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_redis(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_redis;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_redis_conf *urrc = uwsgi_calloc(sizeof(struct uwsgi_router_redis_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"addr", &urrc->addr,
"key", &urrc->key,
"content_type", &urrc->content_type,
"no_offload", &urrc->no_offload,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (!urrc->key || !urrc->addr) {
uwsgi_log("invalid route syntax: you need to specify a redis address and key pattern\n");
return -1;
}
urrc->key_len = strlen(urrc->key);
urrc->addr_len = strlen(urrc->addr);
if (!urrc->content_type) urrc->content_type = "text/html";
urrc->content_type_len = strlen(urrc->content_type);
ur->data2 = urrc;
return 0;
}
static int uwsgi_router_redis_continue(struct uwsgi_route *ur, char *args) {
uwsgi_router_redis(ur, args);
ur->custom = 1;
return 0;
}
static int uwsgi_router_redis_store(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_redis_store;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_redis_conf *urrc = uwsgi_calloc(sizeof(struct uwsgi_router_redis_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"addr", &urrc->addr,
"key", &urrc->key,
"expires", &urrc->expires, NULL)) {
uwsgi_log("invalid redisstore route syntax: %s\n", args);
return -1;
}
if (!urrc->key || !urrc->addr) {
uwsgi_log("invalid redisstore route syntax: you need to specify an address and a key\n");
return -1;
}
urrc->key_len = strlen(urrc->key);
urrc->addr_len = strlen(urrc->addr);
if (!urrc->expires) urrc->expires = "0";
ur->data2 = urrc;
return 0;
}
static void router_redis_register() {
uwsgi_register_router("redis", uwsgi_router_redis);
uwsgi_register_router("redis-continue", uwsgi_router_redis_continue);
uwsgi_register_router("redisstore", uwsgi_router_redis_store);
uwsgi_register_router("redis-store", uwsgi_router_redis_store);
}
#endif
struct uwsgi_plugin router_redis_plugin = {
.name = "router_redis",
#ifdef UWSGI_ROUTING
.on_load = router_redis_register,
#endif
};
+6
View File
@@ -0,0 +1,6 @@
NAME='router_redis'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['router_redis']
+121 -2
View File
@@ -1,9 +1,23 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
extern struct uwsgi_server uwsgi;
struct uwsgi_router_file_conf {
char *filename;
size_t filename_len;
char *status;
size_t status_len;
char *content_type;
size_t content_type_len;
char *mime;
};
int uwsgi_routing_func_static(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
@@ -17,8 +31,71 @@ int uwsgi_routing_func_static(struct wsgi_request *wsgi_req, struct uwsgi_route
return UWSGI_ROUTE_BREAK;
}
int uwsgi_routing_func_file(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
int uwsgi_router_static(struct uwsgi_route *ur, char *args) {
char buf[32768];
struct stat st;
int ret = UWSGI_ROUTE_BREAK;
struct uwsgi_router_file_conf *urfc = (struct uwsgi_router_file_conf *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->filename, urfc->filename_len);
if (!ub) return UWSGI_ROUTE_BREAK;
int fd = open(ub->buf, O_RDONLY);
if (fd < 0) {
if (ur->custom)
ret = UWSGI_ROUTE_NEXT;
goto end;
}
if (fstat(fd, &st)) {
goto end2;
}
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
if (!ub_s) goto end2;
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
uwsgi_buffer_destroy(ub_s);
goto end2;
}
uwsgi_buffer_destroy(ub_s);
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end2;
if (urfc->mime) {
size_t mime_type_len = 0;
char *mime_type = uwsgi_get_mime_type(ub->buf, ub->pos, &mime_type_len);
if (mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end2;
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
}
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
}
size_t remains = st.st_size;
while(remains) {
ssize_t rlen = read(fd, buf, UMIN(32768, remains));
if (rlen <= 0) goto end2;
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) goto end2;
remains -= rlen;
}
end2:
close(fd);
end:
uwsgi_buffer_destroy(ub);
return ret;
}
static int uwsgi_router_static(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_static;
ur->data = args;
@@ -26,10 +103,52 @@ int uwsgi_router_static(struct uwsgi_route *ur, char *args) {
return 0;
}
static int uwsgi_router_file(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_file;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_file_conf *urfc = uwsgi_calloc(sizeof(struct uwsgi_router_file_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"filename", &urfc->filename,
"status", &urfc->status,
"content_type", &urfc->content_type,
"mime", &urfc->mime,
NULL)) {
uwsgi_log("invalid file route syntax: %s\n", args);
return -1;
}
if (!urfc->filename) {
uwsgi_log("you have to specifify a filename for the \"file\" router\n");
return -1;
}
urfc->filename_len = strlen(urfc->filename);
if (!urfc->content_type) {
urfc->content_type = "text/html";
}
urfc->content_type_len = strlen(urfc->content_type);
if (!urfc->status) {
urfc->status = "200 OK";
}
urfc->status_len = strlen(urfc->status);
ur->data2 = urfc;
return 0;
}
static int uwsgi_router_file_next(struct uwsgi_route *ur, char *args) {
ur->custom = 1;
return uwsgi_router_file(ur, args);
}
static void router_static_register(void) {
uwsgi_register_router("static", uwsgi_router_static);
uwsgi_register_router("file", uwsgi_router_file);
uwsgi_register_router("file-next", uwsgi_router_file_next);
}
struct uwsgi_plugin router_static_plugin = {
+75
View File
@@ -0,0 +1,75 @@
#include <uwsgi.h>
#ifndef UWSGI_XML_LIBXML2
#error you need a libxml2-enabled build of uWSGI to use the router_xmldir plugin
#endif
#include <libxml/tree.h>
static int uwsgi_routing_func_xmldir(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);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
struct dirent **tasklist;
int n = scandir(ub->buf, &tasklist, 0, versionsort);
uwsgi_buffer_destroy(ub);
if (n < 0) return UWSGI_ROUTE_BREAK;
int i;
xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
xmlNode *rtree = xmlNewNode(NULL, BAD_CAST "tree");
xmlDocSetRootElement(rdoc, rtree);
for(i=0;i<n;i++) {
if (tasklist[i]->d_name[0] == '.') goto next;
switch (tasklist[i]->d_type) {
case DT_DIR:
xmlNewTextChild(rtree, NULL, BAD_CAST "directory", BAD_CAST tasklist[i]->d_name);
break;
case DT_LNK:
xmlNewTextChild(rtree, NULL, BAD_CAST "link", BAD_CAST tasklist[i]->d_name);
break;
case DT_REG:
xmlNewTextChild(rtree, NULL, BAD_CAST "file", BAD_CAST tasklist[i]->d_name);
break;
default:
xmlNewTextChild(rtree, NULL, BAD_CAST "unknown", BAD_CAST tasklist[i]->d_name);
break;
}
next:
free(tasklist[i]);
}
free(tasklist);
xmlChar *xmlbuf;
int xlen = 0;
xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);
uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6);
uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);
xmlFreeDoc(rdoc);
xmlFree(xmlbuf);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_xmldir(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_xmldir;
ur->data = args;
ur->data_len = strlen(args);
return 0;
}
static void router_xmldir_register() {
uwsgi_register_router("xmldir", uwsgi_router_xmldir);
}
struct uwsgi_plugin router_xmldir_plugin = {
.name = "router_xmldir",
.on_load = router_xmldir_register,
};
+5
View File
@@ -0,0 +1,5 @@
NAME='router_xmldir'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['router_xmldir']
+197
View File
@@ -1,7 +1,125 @@
#include <uwsgi.h>
#ifdef UWSGI_XML_LIBXML2
#include <libxml/parser.h>
#include <libxml/tree.h>
#endif
extern struct uwsgi_server uwsgi;
/*
rpc-HTTP interface.
modifier2 changes the parsser behaviours:
0 -> return uwsgi header + rpc response
1 -> return raw rpc response
2 -> split PATH_INFO to get func name and args and return as HTTP response with content_type as application/binary or Accept request header (if different from *)
3 -> set xmlrpc wrapper (requires libxml2)
4 -> set jsonrpc wrapper (requires libjansson)
*/
#ifdef UWSGI_XML_LIBXML2
// raise error on non-string args
static int uwsgi_rpc_xmlrpc_string(xmlNode *element, char **argv, uint16_t *argvs, uint8_t *argc) {
xmlNode *node;
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (strcmp((char *) node->name, "string")) {
return -1;
}
if (!node->children) return -1;
if (!node->children->content) return -1;
*argc+=1;
argv[*argc] = (char *) node->children->content;
argvs[*argc] = strlen(argv[*argc]);
}
}
return 0;
}
static int uwsgi_rpc_xmlrpc_value(xmlNode *element, char **argv, uint16_t *argvs, uint8_t *argc) {
xmlNode *node;
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, "value")) {
if (uwsgi_rpc_xmlrpc_string(node, argv, argvs, argc)) {
return -1;
}
}
}
}
return 0;
}
static int uwsgi_rpc_xmlrpc_args(xmlNode *element, char **argv, uint16_t *argvs, uint8_t *argc) {
xmlNode *node;
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, "param")) {
if (uwsgi_rpc_xmlrpc_value(node, argv, argvs, argc)) {
return -1;
}
}
}
}
return 0;
}
static int uwsgi_rpc_xmlrpc(struct wsgi_request *wsgi_req, xmlDoc *doc, char **argv, uint16_t *argvs, uint8_t *argc, char *response_buf) {
char *method = NULL;
xmlNode *element = xmlDocGetRootElement(doc);
if (!element) return -1;
if (strcmp((char *) element->name, "methodCall")) return -1;
*argc = 0;
xmlNode *node;
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, "methodName") && node->children) {
method = (char *) node->children->content;
}
else if (!strcmp((char *) node->name, "params")) {
if (uwsgi_rpc_xmlrpc_args(node, argv, argvs, argc)) return -1;
}
}
}
if (!method) return -1;
wsgi_req->uh->pktsize = uwsgi_rpc(method, *argc, argv+1, argvs+1, response_buf);
if (!wsgi_req->uh->pktsize) return -1;
if (wsgi_req->uh->pktsize == UMAX16-1) return -1;
// add final NULL byte
response_buf[wsgi_req->uh->pktsize] = 0;
xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
xmlNode *m_response = xmlNewNode(NULL, BAD_CAST "methodResponse");
xmlDocSetRootElement(rdoc, m_response);
xmlNode *x_params = xmlNewChild(m_response, NULL, BAD_CAST "params", NULL);
xmlNode *x_param = xmlNewChild(x_params, NULL, BAD_CAST "param", NULL);
xmlNode *x_value = xmlNewChild(x_param, NULL, BAD_CAST "value", NULL);
xmlNewTextChild(x_value, NULL, BAD_CAST "string", BAD_CAST response_buf);
xmlChar *xmlbuf;
int xlen = 0;
xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);
uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6);
uwsgi_response_add_content_length(wsgi_req, xlen);
uwsgi_response_add_content_type(wsgi_req, "application/xml", 15);
uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);
xmlFreeDoc(rdoc);
xmlFree(xmlbuf);
return 0;
}
#endif
static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
@@ -20,6 +138,82 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
return -1;
}
if (wsgi_req->uh->modifier2 == 2) {
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid RPC request. skip.\n");
return -1;
}
if (wsgi_req->path_info_len == 0) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
char *args = NULL;
if (wsgi_req->path_info[0] == '/') {
args = uwsgi_concat2n(wsgi_req->path_info+1, wsgi_req->path_info_len-1, "", 0);
}
else {
args = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
}
argc = 0;
argv[0] = strtok(args, "/");
if (!argv[0]) {
free(args);
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
char *p = strtok(NULL, "/");
while(p) {
argc++;
argv[argc] = p;
argvs[argc] = strlen(p);
p = strtok(NULL, "/");
}
wsgi_req->uh->pktsize = uwsgi_rpc(argv[0], argc, argv+1, argvs+1, response_buf);
free(args);
if (!wsgi_req->uh->pktsize) {
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return 1;
if (uwsgi_response_add_content_length(wsgi_req, wsgi_req->uh->pktsize)) return -1;
uint16_t ctype_len = 0;
char *ctype = uwsgi_get_var(wsgi_req, "HTTP_ACCEPT", 11, &ctype_len);
if (ctype && strcmp(ctype, "*/*") && strcmp(ctype, "*")) {
if (uwsgi_response_add_content_type(wsgi_req, ctype, ctype_len)) return -1;
}
else {
if (uwsgi_response_add_content_type(wsgi_req, "application/binary", 18)) return -1;
}
goto sendbody;
}
#ifdef UWSGI_XML_LIBXML2
if (wsgi_req->uh->modifier2 == 3) {
if (wsgi_req->post_cl == 0) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
ssize_t body_len = 0;
char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len);
xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0);
if (!doc) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
int ret = uwsgi_rpc_xmlrpc(wsgi_req, doc, argv, argvs, &argc, response_buf);
xmlFreeDoc(doc);
if (ret) {
uwsgi_500(wsgi_req);
}
return UWSGI_OK;
}
#endif
if (uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh->pktsize, argv, argvs, &argc)) {
uwsgi_log("Invalid RPC request. skip.\n");
return -1;
@@ -34,6 +228,9 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
return -1;
}
}
sendbody:
// write the response
uwsgi_response_write_body_do(wsgi_req, response_buf, wsgi_req->uh->pktsize);
+2
View File
@@ -193,6 +193,7 @@ static ssize_t sr_instance_read(struct corerouter_peer *peer) {
// the instance is connected now we cannot retry connections
static ssize_t sr_instance_connected(struct corerouter_peer *peer) {
cr_peer_connected(peer, "sr_instance_connected()");
peer->can_retry = 0;
// set the output buffer as the main_peer output one
peer->out = peer->session->main_peer->in;
peer->out_pos = 0;
@@ -307,6 +308,7 @@ static ssize_t sr_read(struct corerouter_peer *main_peer) {
return -1;
}
peer->can_retry = 1;
cr_connect(peer, sr_instance_connected);
return 1;
}
+138
View File
@@ -0,0 +1,138 @@
#include <uwsgi.h>
#if defined(UWSGI_ROUTING)
/*
offload transformation
each chunk is buffered to the transformation custom buffer
if the buffer grows higher than the specified limit, the response will be buffered to disk
on final the memory (or the tmpfile) will be offloaded
even if we are talking about buffering, this is a streaming transformation
as we need to hold control on memory usage
"offload" MUST BE the last transformation in the chain. Hellish things will happen otherwise...
*/
static int transform_offload(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
if (ut->is_final) {
struct uwsgi_transformation *orig_ut = (struct uwsgi_transformation *) ut->data;
// sendfile offload
if (orig_ut->fd > -1) {
if (!uwsgi_offload_request_sendfile_do(wsgi_req, orig_ut->fd, orig_ut->len)) {
// the fd will be closed by the offload engine
orig_ut->fd = -1;
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->response_size += orig_ut->len;
return 0;
}
// fallback to non-offloaded write
if (uwsgi_simple_sendfile(wsgi_req, orig_ut->fd, 0, orig_ut->len)) {
return -1;
}
wsgi_req->response_size += orig_ut->len;
return 0;
}
// memory offload
if (orig_ut->ub) {
if (!uwsgi_offload_request_memory_do(wsgi_req, orig_ut->ub->buf, orig_ut->ub->pos)) {
// memory will be freed by the offload engine
orig_ut->ub->buf = NULL;
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->response_size += orig_ut->ub->pos;
return 0;
}
// fallback to non-offloaded write
if (uwsgi_simple_write(wsgi_req, orig_ut->ub->buf, orig_ut->ub->pos)) {
return -1;
}
wsgi_req->response_size += orig_ut->ub->pos;
return -1;
}
return 0;
}
// check if we need to start buffering to disk
if (ut->fd == -1 && ut->len + ut->chunk->pos > ut->custom64) {
ut->fd = uwsgi_tmpfd();
if (ut->fd < 0) return -1;
// save already buffered data
if (ut->ub) {
ssize_t wlen = write(ut->fd, ut->ub->buf, ut->ub->pos);
if (wlen != (ssize_t) ut->ub->pos) {
uwsgi_error("transform_offload/write()");
return -1;
}
}
}
// if fd > -1, append to file
if (ut->fd > -1) {
ssize_t wlen = write(ut->fd, ut->chunk->buf, ut->chunk->pos);
if (wlen != (ssize_t) ut->chunk->pos) {
uwsgi_error("transform_offload/write()");
return -1;
}
ut->len += wlen;
goto done;
}
// buffer to memory
if (!ut->ub) {
ut->ub = uwsgi_buffer_new(ut->chunk->pos);
}
// append the chunk to the custom buffer
if (uwsgi_buffer_append(ut->ub, ut->chunk->buf, ut->chunk->pos)) return -1;
ut->len += ut->chunk->pos;
done:
// reset the chunk !!!
ut->chunk->pos = 0;
return 0;
}
static int uwsgi_routing_func_offload(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
if (!wsgi_req->socket->can_offload) {
uwsgi_log("unable to use the offload transformation without offload threads !!!\n");
return UWSGI_ROUTE_BREAK;
}
struct uwsgi_transformation *ut = uwsgi_add_transformation(wsgi_req, transform_offload, NULL);
ut->can_stream = 1;
ut->custom64 = ur->custom;
// add a "final" transformation to add the trailing chunk
ut = uwsgi_add_transformation(wsgi_req, transform_offload, ut);
ut->is_final = 1;
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_offload(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_offload;
if (args[0] == 0) {
// 1 MB limit
ur->custom = 1024 * 1024;
}
else {
ur->custom = strtoul(args, NULL, 10);
}
return 0;
}
static void router_offload_register(void) {
uwsgi_register_router("offload", uwsgi_router_offload);
}
struct uwsgi_plugin transformation_offload_plugin = {
.name = "transformation_offload",
.on_load = router_offload_register,
};
#else
struct uwsgi_plugin transformation_offload_plugin = {
.name = "transformation_offload",
};
#endif
@@ -0,0 +1,6 @@
NAME='transformation_offload'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['offload']
+18 -2
View File
@@ -150,11 +150,17 @@ parse:
ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf, size_t len) {
int has_read = 0;
if (wsgi_req->proto_parser_remains > 0) {
size_t remains = UMIN(wsgi_req->proto_parser_remains, len);
memcpy(buf, wsgi_req->proto_parser_remains_buf, remains);
wsgi_req->proto_parser_remains -= remains;
wsgi_req->proto_parser_remains_buf += remains;
// we consumed all of the body, we can safely move the memory
if (wsgi_req->proto_parser_remains == 0 && wsgi_req->proto_parser_move) {
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_move, wsgi_req->proto_parser_pos);
wsgi_req->proto_parser_move = 0;
}
return remains;
}
@@ -176,7 +182,14 @@ ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf,
// copy remaining
wsgi_req->proto_parser_remains = fcgi_len - remains;
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf + sizeof(struct fcgi_record) + remains;
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
// we consumed all of the body, we can safely move the memory
if (wsgi_req->proto_parser_remains == 0) {
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
}
else {
// postpone memory move
wsgi_req->proto_parser_move = fcgi_all_len;
}
wsgi_req->proto_parser_pos -= fcgi_all_len;
return remains;
}
@@ -192,12 +205,15 @@ ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf,
wsgi_req->proto_parser_buf = tmp_buf;
wsgi_req->proto_parser_buf_size += fcgi_all_len - (wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
}
goto gather;
if (!has_read) goto gather;
errno = EAGAIN;
return -1;
}
else {
gather:
rlen = read(wsgi_req->fd, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos, wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
if (rlen > 0) {
has_read = 1;
wsgi_req->proto_parser_pos += rlen;
continue;
}
+11 -1
View File
@@ -12,13 +12,23 @@ from setuptools.command.build_ext import build_ext
"""
This is a hack allowing you installing
uWSGI and uwsgidecorators via pip and easy_install
since 1.9.11 it automatically detects pypy
"""
uwsgi_compiled = False
def get_profile():
profile = os.environ.get('UWSGI_PROFILE', 'buildconf/default.ini')
is_pypy = False
try:
import __pypy__
is_pypy = True
except ImportError:
pass
if is_pypy:
profile = os.environ.get('UWSGI_PROFILE', 'buildconf/pypy.ini')
else:
profile = os.environ.get('UWSGI_PROFILE', 'buildconf/default.ini')
if not profile.endswith('.ini'):
profile = "%s.ini" % profile
if not '/' in profile:
+40
View File
@@ -0,0 +1,40 @@
"""
simplified test for continulet without checking for partial writes
to enable continulets you only need to call uwsgi_pypy_setup_continulets() soon after startup:
uwsgi --pypy-wsgi-file t/pypy/t_continulet1.py --http-socket :9090 --pypy-home /opt/pypy --pypy-eval "uwsgi_pypy_setup_continulets()" --async 8
"""
import uwsgi
def application(e, sr):
sr('200 OK', [('Content-Type','text/plain')])
# call suspend 10 times and yield some value
for i in range(0,10):
print i
uwsgi.suspend()
yield str(i)
# connect to a memcached server
fd = uwsgi.async_connect('127.0.0.1:11211')
try:
# start waiting for socket availability (4 seconds max)
uwsgi.wait_fd_write(fd, 4)
# suspend execution 'til event
uwsgi.suspend()
uwsgi.send(fd, "get /foobar\r\n")
# now wait for memcached response
uwsgi.wait_fd_read(fd, 4)
uwsgi.suspend()
# read the response
data = uwsgi.recv(fd, 4096)
# return to the client
yield data
finally:
uwsgi.close(fd)
print "sleeping for 3 seconds..."
uwsgi.async_sleep(3)
uwsgi.suspend()
yield "done"
+47
View File
@@ -0,0 +1,47 @@
"""
safer test for continulet with partial writes check
to enable continulets you only need to call uwsgi_pypy_setup_continulets() soon after startup:
uwsgi --pypy-wsgi-file t/pypy/t_continulet2.py --http-socket :9090 --pypy-home /opt/pypy --pypy-eval "uwsgi_pypy_setup_continulets()" --async 8
"""
import uwsgi
def application(e, sr):
sr('200 OK', [('Content-Type','text/plain')])
# suspend 10 times and yield a value
for i in range(1,10):
print i
uwsgi.suspend()
yield str(i)
# connect to a memcached server
fd = uwsgi.async_connect('127.0.0.1:11211')
try:
command = "get /foobar\r\n"
remains = len(command)
while remains > 0:
# start waiting for socket availability (4 seconds max)
uwsgi.wait_fd_write(fd, 4)
# suspend execution 'til event
uwsgi.suspend()
pos = len(command) - remains
written = uwsgi.send(fd, command[pos:])
remains -= written
# now wait for memcached response
uwsgi.wait_fd_read(fd, 4)
uwsgi.suspend()
# read a chunk of data
data = uwsgi.recv(fd, 4096)
# .. and yield it
yield data
finally:
# always ensure sockets are closed
uwsgi.close(fd)
print "sleeping for 3 seconds..."
uwsgi.async_sleep(3)
uwsgi.suspend()
yield "done"
+14
View File
@@ -0,0 +1,14 @@
import socket
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
(addr, port) = sys.argv[1].split(':')
s.connect((addr, int(port)))
s.send("POST /send HTTP/1.1\r\n")
s.send("Transfer-Encoding: chunked\r\n\r\n")
while True:
msg = raw_input("msg >> ")
s.send("%X\r\n%s\r\n" % (len(msg), msg))
+80
View File
@@ -0,0 +1,80 @@
#!./uwsgi --http-socket :9090 --gevent 100 --module tests.websocket_chat --gevent-monkey-patch
import uwsgi
import time
import gevent.select
import redis
def application(env, sr):
ws_scheme = 'ws'
if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
ws_scheme = 'wss'
if env['PATH_INFO'] == '/':
sr('200 OK', [('Content-Type','text/html')])
return """
<html>
<head>
<script language="Javascript">
var s = new WebSocket("%s://%s/foobar/");
s.onopen = function() {
alert("connected !!!");
s.send("ciao");
};
s.onmessage = function(e) {
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
};
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
function invia() {
var value = document.getElementById('testo').value;
s.send(value);
}
</script>
</head>
<body>
<h1>WebSocket</h1>
<input type="text" id="testo"/>
<input type="button" value="invia" onClick="invia();"/>
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
</div>
</body>
</html>
""" % (ws_scheme, env['HTTP_HOST'])
elif env['PATH_INFO'] == '/favicon.ico':
return ""
elif env['PATH_INFO'] == '/foobar/':
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
print "websockets..."
r = redis.StrictRedis(host='localhost', port=6379, db=0)
channel = r.pubsub()
channel.subscribe('foobar')
websocket_fd = uwsgi.connection_fd()
redis_fd = channel.connection._sock.fileno()
while True:
# wait max 4 seconds to allow ping to be sent
ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0)
# send ping on timeout
if not ready[0]:
uwsgi.websocket_recv_nb()
for fd in ready[0]:
if fd == websocket_fd:
msg = uwsgi.websocket_recv_nb()
if msg:
r.publish('foobar', msg)
elif fd == redis_fd:
msg = channel.parse_response()
# only interested in user messages
if msg[0] == 'message':
uwsgi.websocket_send("[%s] %s" % (time.time(), msg))
+81
View File
@@ -0,0 +1,81 @@
#!./uwsgi --http-socket :9090 --async 100 ...
# same chat example but using uwsgi async api
# for pypy + continulets just run:
# uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi-file tests/websockets_chat_async.py --pypy-eval "uwsgi_pypy_setup_continulets()" --async 100
import uwsgi
import time
import redis
def application(env, sr):
ws_scheme = 'ws'
if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
ws_scheme = 'wss'
if env['PATH_INFO'] == '/':
sr('200 OK', [('Content-Type','text/html')])
return """
<html>
<head>
<script language="Javascript">
var s = new WebSocket("%s://%s/foobar/");
s.onopen = function() {
alert("connected !!!");
s.send("ciao");
};
s.onmessage = function(e) {
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
};
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
function invia() {
var value = document.getElementById('testo').value;
s.send(value);
}
</script>
</head>
<body>
<h1>WebSocket</h1>
<input type="text" id="testo"/>
<input type="button" value="invia" onClick="invia();"/>
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
</div>
</body>
</html>
""" % (ws_scheme, env['HTTP_HOST'])
elif env['PATH_INFO'] == '/favicon.ico':
return ""
elif env['PATH_INFO'] == '/foobar/':
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
print "websockets..."
r = redis.StrictRedis(host='localhost', port=6379, db=0)
channel = r.pubsub()
channel.subscribe('foobar')
websocket_fd = uwsgi.connection_fd()
redis_fd = channel.connection._sock.fileno()
while True:
uwsgi.wait_fd_read(websocket_fd)
uwsgi.wait_fd_read(redis_fd)
uwsgi.suspend()
fd = uwsgi.ready_fd()
if fd > -1:
if fd == websocket_fd:
msg = uwsgi.websocket_recv_nb()
if msg:
r.publish('foobar', msg)
elif fd == redis_fd:
msg = channel.parse_response()
# only interested in user messages
if msg[0] == 'message':
uwsgi.websocket_send("[%s] %s" % (time.time(), msg))
+1 -1
View File
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
s.name = 'uwsgi'
s.license = 'GPL-2'
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
s.date = '2013-05-11'
s.date = '2013-06-05'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+86 -10
View File
@@ -218,11 +218,6 @@ extern "C" {
#include <sys/prctl.h>
#include <linux/limits.h>
#include <sys/mount.h>
#ifdef UWSGI_PTRACE
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/reg.h>
#endif
extern int pivot_root(const char *new_root, const char *put_old);
#endif
@@ -278,7 +273,9 @@ extern int pivot_root(const char *new_root, const char *put_old);
#endif
#if defined(__HAIKU__) || defined(__CYGWIN__)
#ifndef WAIT_ANY
#define WAIT_ANY (-1)
#endif
#define PRIO_MAX 20
#endif
@@ -292,6 +289,7 @@ extern int pivot_root(const char *new_root, const char *put_old);
#include <sys/devpoll.h>
#elif defined(__HAIKU__)
#elif defined(__CYGWIN__)
#elif defined(__HURD__)
#else
#include <sys/event.h>
#endif
@@ -783,6 +781,9 @@ struct uwsgi_opt {
#elif defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#elif defined(__HAIKU__)
#elif defined(__HURD__)
#define PATH_MAX 8192
#define RTLD_DEFAULT ((void *) 0)
#else
#include <machine/endian.h>
#endif
@@ -1044,6 +1045,7 @@ struct uwsgi_spooler {
uint64_t tasks;
struct uwsgi_lock_item *lock;
time_t harakiri;
time_t user_harakiri;
int mode;
@@ -1082,6 +1084,7 @@ struct uwsgi_route {
int (*if_func)(struct wsgi_request *, struct uwsgi_route *);
int if_negate;
int if_status;
int (*func) (struct wsgi_request *, struct uwsgi_route *);
@@ -1215,6 +1218,10 @@ struct uwsgi_transformation {
uint8_t flushed;
void *data;
uint64_t round;
int fd;
struct uwsgi_buffer *ub;
uint64_t len;
uint64_t custom64;
struct uwsgi_transformation *next;
};
@@ -1393,6 +1400,7 @@ struct wsgi_request {
int headers_hvec;
uint64_t proto_parser_pos;
uint64_t proto_parser_move;
int64_t proto_parser_status;
void *proto_parser_buf;
uint64_t proto_parser_buf_size;
@@ -1421,16 +1429,29 @@ struct wsgi_request {
time_t websocket_last_pong;
int websocket_closed;
struct uwsgi_buffer *chunked_input_buf;
uint8_t chunked_input_parser_status;
ssize_t chunked_input_chunk_len;
size_t chunked_input_need;
uint8_t chunked_input_complete;
uint64_t stream_id;
// avoid routing loops
int is_routing;
int is_final_routing;
int is_error_routing;
int routes_applied;
// internal routing vm program counter
uint32_t route_pc;
uint32_t error_route_pc;
uint32_t final_route_pc;
// internal routing goto instruction
uint32_t route_goto;
uint32_t error_route_goto;
uint32_t final_route_goto;
int ignore_body;
struct uwsgi_transformation *transformations;
char *transformed_chunk;
@@ -1858,6 +1879,8 @@ struct uwsgi_server {
struct uwsgi_regexp_list *log_req_route;
#endif
int use_abort;
int alarm_freq;
uint64_t alarm_msg_size;
struct uwsgi_string_list *alarm_list;
@@ -1932,6 +1955,8 @@ struct uwsgi_server {
struct uwsgi_offload_engine *offload_engines;
struct uwsgi_offload_engine *offload_engine_sendfile;
struct uwsgi_offload_engine *offload_engine_transfer;
struct uwsgi_offload_engine *offload_engine_memory;
struct uwsgi_offload_engine *offload_engine_pipe;
int offload_threads;
int offload_threads_events;
struct uwsgi_thread **offload_thread;
@@ -1982,6 +2007,7 @@ struct uwsgi_server {
struct uwsgi_string_list *touch_logrotate;
struct uwsgi_string_list *touch_logreopen;
struct uwsgi_string_list *touch_exec;
struct uwsgi_string_list *touch_signal;
int propagate_touch;
@@ -2085,6 +2111,7 @@ struct uwsgi_server {
struct uwsgi_mule *mules;
struct uwsgi_string_list *farms_list;
struct uwsgi_farm *farms;
int mule_msg_size;
pid_t mypid;
int mywid;
@@ -2115,6 +2142,7 @@ struct uwsgi_server {
struct uwsgi_router *routers;
struct uwsgi_route *routes;
struct uwsgi_route *final_routes;
struct uwsgi_route *error_routes;
struct uwsgi_route_condition *route_conditions;
struct uwsgi_route_var *route_vars;
#endif
@@ -2148,6 +2176,7 @@ struct uwsgi_server {
#ifdef __linux__
struct uwsgi_string_list *cgroup;
struct uwsgi_string_list *cgroup_opt;
char *cgroup_dir_mode;
char *ns;
char *ns_net;
struct uwsgi_string_list *ns_keep_mount;
@@ -2170,6 +2199,7 @@ struct uwsgi_server {
struct uwsgi_string_list *map_socket;
struct uwsgi_cron *crons;
time_t cron_harakiri;
time_t respawn_delta;
@@ -2220,6 +2250,7 @@ struct uwsgi_server {
size_t lock_size;
size_t rwlock_size;
struct uwsgi_string_list *add_cache_item;
struct uwsgi_string_list *load_file_in_cache;
#ifdef UWSGI_ZLIB
struct uwsgi_string_list *load_file_in_cache_gzip;
@@ -2322,6 +2353,9 @@ struct uwsgi_server {
int websockets_pong_tolerance;
uint64_t websockets_max_size;
int chunked_input_timeout;
uint64_t chunked_input_limit;
int (*wait_write_hook) (int, int);
int (*wait_read_hook) (int, int);
@@ -2371,6 +2405,16 @@ struct uwsgi_cron {
#endif
void (*func)(struct uwsgi_cron *, time_t);
time_t started_at;
// next harakiri timestamp
time_t harakiri;
// number of seconds to wait before calling harakiri on cron
int mercy;
uint8_t unique;
pid_t pid;
struct uwsgi_cron *next;
};
@@ -2541,6 +2585,7 @@ struct uwsgi_mule {
uint8_t signum;
time_t harakiri;
time_t user_harakiri;
char name[0xff];
};
@@ -2905,7 +2950,8 @@ struct uwsgi_async_request {
int event_queue_read(void);
int event_queue_write(void);
void uwsgi_help(char *opt, char *val, void *);
void uwsgi_help(char *, char *, void *);
void uwsgi_print_sym(char *, char *, void *);
int uwsgi_str2_num(char *);
int uwsgi_str3_num(char *);
@@ -2929,7 +2975,7 @@ char *uwsgi_amqp_consume(int, uint64_t *, char **);
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t, int);
int uwsgi_starts_with(char *, int, char *, int);
int uwsgi_static_want_gzip(struct wsgi_request *, char *, size_t, struct stat *);
int uwsgi_static_want_gzip(struct wsgi_request *, char *, size_t *, struct stat *);
#ifdef __sun__
time_t timegm(struct tm *);
@@ -3148,6 +3194,7 @@ void mule_send_msg(int, char *, size_t);
uint32_t djb33x_hash(char *, uint64_t);
void create_signal_pipe(int *);
void create_msg_pipe(int *, int);
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **, char *, uint16_t);
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **, char *, uint16_t, char *, uint16_t);
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **, char *, uint16_t);
@@ -3198,6 +3245,7 @@ struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *, char *);
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int, char *);
void escape_shell_arg(char *, size_t, char *);
void escape_json(char *, size_t, char *);
void *uwsgi_malloc_shared(size_t);
void *uwsgi_calloc_shared(size_t);
@@ -3240,12 +3288,15 @@ void uwsgi_opt_add_shared_socket(char *, char *, void *);
void uwsgi_opt_add_socket(char *, char *, void *);
void uwsgi_opt_add_lazy_socket(char *, char *, void *);
void uwsgi_opt_add_cron(char *, char *, void *);
void uwsgi_opt_add_cron2(char *, char *, void *);
void uwsgi_opt_add_unique_cron(char *, char *, void *);
void uwsgi_opt_load_plugin(char *, char *, void *);
void uwsgi_opt_load_dl(char *, char *, void *);
void uwsgi_opt_load(char *, char *, void *);
void uwsgi_opt_safe_fd(char *, char *, void *);
#ifdef UWSGI_SSL
void uwsgi_opt_add_legion_cron(char *, char *, void *);
void uwsgi_opt_add_unique_legion_cron(char *, char *, void *);
void uwsgi_opt_sni(char *, char *, void *);
struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *, char *, char *, char *, char *);
#endif
@@ -3323,13 +3374,15 @@ void uwsgi_opt_set_cap(char *, char *, void *);
void uwsgi_opt_set_unshare(char *, char *, void *);
#endif
char *uwsgi_tmpname(char *, char *);
int uwsgi_tmpfd();
FILE *uwsgi_tmpfile();
#ifdef UWSGI_ROUTING
struct uwsgi_router *uwsgi_register_router(char *, int (*)(struct uwsgi_route *, char *));
void uwsgi_opt_add_route(char *, char *, void *);
int uwsgi_apply_routes(struct wsgi_request *);
void uwsgi_apply_final_routes(struct wsgi_request *);
int uwsgi_apply_error_routes(struct wsgi_request *);
int uwsgi_apply_routes_do(struct uwsgi_route *, struct wsgi_request *, char *, uint16_t);
void uwsgi_register_embedded_routers(void);
void uwsgi_routing_dump();
@@ -3457,9 +3510,13 @@ char *uwsgi_substitute(char *, char *, char *);
void uwsgi_opt_add_custom_option(char *, char *, void *);
void uwsgi_opt_cflags(char *, char *, void *);
void uwsgi_opt_dot_h(char *, char *, void *);
void uwsgi_opt_connect_and_read(char *, char *, void *);
void uwsgi_opt_extract(char *, char *, void *);
char *uwsgi_get_dot_h();
char *uwsgi_get_cflags();
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *, char *, size_t);
void trigger_harakiri(int);
@@ -3736,6 +3793,11 @@ void uwsgi_offload_engines_register_all(void);
struct uwsgi_thread *uwsgi_offload_thread_start(void);
int uwsgi_offload_request_sendfile_do(struct wsgi_request *, int, size_t);
int uwsgi_offload_request_net_do(struct wsgi_request *, char *, struct uwsgi_buffer *);
int uwsgi_offload_request_memory_do(struct wsgi_request *, char *, size_t);
int uwsgi_offload_request_pipe_do(struct wsgi_request *, int, size_t);
int uwsgi_simple_sendfile(struct wsgi_request *, int, size_t, size_t);
int uwsgi_simple_write(struct wsgi_request *, char *, size_t);
void uwsgi_subscription_set_algo(char *);
@@ -3764,8 +3826,8 @@ int uwsgi_plugin_modifier1(char *);
void *cache_udp_server_loop(void *);
void uwsgi_user_lock(int);
void uwsgi_user_unlock(int);
int uwsgi_user_lock(int);
int uwsgi_user_unlock(int);
void simple_loop_run_int(int);
@@ -3818,6 +3880,8 @@ int uwsgi_websocket_send(struct wsgi_request *, char *, size_t);
struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *);
struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *);
char *uwsgi_chunked_read(struct wsgi_request *, size_t *, int, int);
uint16_t uwsgi_be16(char *);
uint32_t uwsgi_be32(char *);
uint64_t uwsgi_be64(char *);
@@ -3830,6 +3894,7 @@ int uwsgi_response_add_header(struct wsgi_request *, char *, uint16_t, char *, u
int uwsgi_response_add_header_force(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
int uwsgi_response_commit_headers(struct wsgi_request *);
int uwsgi_response_sendfile_do(struct wsgi_request *, int, size_t, size_t);
int uwsgi_response_sendfile_do_can_close(struct wsgi_request *, int, size_t, size_t, int);
struct uwsgi_buffer *uwsgi_proto_base_add_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
@@ -3874,6 +3939,7 @@ void uwsgi_master_check_workers_deadline(void);
void uwsgi_master_check_gateways_deadline(void);
void uwsgi_master_check_mules_deadline(void);
void uwsgi_master_check_spoolers_deadline(void);
void uwsgi_master_check_crons_deadline(void);
int uwsgi_master_check_spoolers_death(int);
int uwsgi_master_check_emperor_death(int);
int uwsgi_master_check_mules_death(int);
@@ -3959,9 +4025,11 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *);
#ifdef UWSGI_ZLIB
#include <zlib.h>
int uwsgi_deflate_init(z_stream *, char *, size_t);
int uwsgi_inflate_init(z_stream *, char *, size_t);
char *uwsgi_deflate(z_stream *, char *, size_t, size_t *);
void uwsgi_crc32(uint32_t *, char *, size_t);
struct uwsgi_buffer *uwsgi_gzip(char *, size_t);
struct uwsgi_buffer *uwsgi_zlib_decompress(char *, size_t);
int uwsgi_gzip_fix(z_stream *, uint32_t, struct uwsgi_buffer *, size_t);
char *uwsgi_gzip_chunk(z_stream *, uint32_t *, char *, size_t, size_t *);
int uwsgi_gzip_prepare(z_stream *, char *, size_t, uint32_t *);
@@ -4002,11 +4070,19 @@ void uwsgi_mule_run(void);
void uwsgi_spooler_run(void);
void uwsgi_takeover(void);
char *uwsgi_binary_path(void);
int uwsgi_is_again();
void uwsgi_disconnect(struct wsgi_request *);
int uwsgi_ready_fd(struct wsgi_request *);
void uwsgi_check_emperor(void);
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int, char **, char **);
#endif
int uwsgi_master_check_cron_death(int);
#ifdef __cplusplus
}
#endif
-55
View File
@@ -1,55 +0,0 @@
send_message()
send_multi_message()
reload()
workers()
masterpid()
total_requests()
getoption(id)
get_option(id)
setoption(id, value)
set_option(id, value)
sorry_i_need_to_block()
request_id()
worker_id()
log(message)
disconnect()
grunt()
load_plugin()
lock()
unlock()
send()
cl()
req_fd()
signal(num)
sendfile()
set_warning_message()
mem()
has_hook()
logsize()
send_multicast_message
cluster_nodes
cluster_best_node
async_sleep
async_connect
async_send_message
green_schedule
suspend
wait_fd_read(fd, [timeout])
wait_fd_write(fd, timeout)
is_connected()
send
recv()
recv_block
recv_frame
close
parsefile
sharedarea_read
sharedarea_write
sharedarea_readbyte
sharedarea_writebyte
sharedarea_readlong
sharedarea_writelong
sharedarea_inclong
register_signal(num, targer, handler)
register_rpc(name, func[,args])
rpc(node, name[,args,...])

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