Compare commits

...
233 Commits
Author SHA1 Message Date
roberto@gambit 97ec789bbe fixed casting 2011-08-18 06:13:51 +02:00
roberto@debian32 14b403c046 fixed a post-buffering bug 2011-08-17 12:42:12 +02:00
roberto@debian32 bc01d25068 uWSGI can now be built as a shardd library 2011-08-17 11:21:22 +02:00
roberto@fedora64 69808c34a8 fixed callable and start_response refcnt 2011-08-16 17:00:15 +02:00
roberto@debian32 273181daf5 another threading fix 2011-08-16 08:00:09 +02:00
roberto@debian32 8d2394eba1 better name handling in --wsgi-file 2011-08-16 07:33:46 +02:00
roberto@debian32 6f5b468b11 fix threading bug in pyshell 2011-08-16 07:31:20 +02:00
roberta@mrspurr c9e759bc14 allow threads in gateways 2011-08-14 07:46:29 +02:00
roberto@debian32 e6d064f5c1 allows fastrouter cache to set modifier1 2011-08-13 11:25:06 +02:00
roberto@debian32 8f7ed02475 a bunch of lua fixes 2011-08-13 11:12:10 +02:00
roberto@debian32 f7edcebbdc added --fastrouter-use-code-string 2011-08-13 08:39:17 +02:00
roberto@debian32 a19b392ba6 applications list is now shared 2011-08-12 08:08:39 +02:00
roberto@mrspurr 287df9ef86 fixed a stupid bug with thread stacksize 2011-08-11 07:32:02 +02:00
roberto@juggernaut de7be379c4 shut up gcc on ubuntu lucid 2011-08-10 14:43:57 +02:00
roberto@debian32 1e4d41795c allows setting threads stacksize 2011-08-10 12:13:46 +02:00
roberto@debian32 e2e973a20e we are now at 0.9.9-dev 2011-08-09 08:25:09 +02:00
roberto@debian32 5d993fbfc0 implemented UWSGI_APPID var 2011-08-09 08:20:12 +02:00
roberto@debian32 a94a8ea287 added a check on spooler unlink 2011-08-05 06:53:43 +02:00
roberto@debian32 55d8677a46 fixed a spooler thread problem 2011-08-04 18:20:44 +02:00
roberto@debian32 4004aeb54e fileno() for wsgi.input 2011-08-04 16:53:39 +02:00
roberto@debian32 2de2898d86 fix a stupid bug 2011-08-04 16:28:47 +02:00
roberto@debian32 8c1b48a88d a new kick-ass feature for the spooler 2011-08-04 16:25:17 +02:00
roberto@debian32 9bd3022a5e a bunch of threading fixes in the spooler 2011-08-04 14:11:40 +02:00
roberto@debian32 eb0ce609f0 wakeup spooler (if possibile) after each submission 2011-08-04 11:15:24 +02:00
roberto@debian32 5353eba35b improved the pyshell 2011-08-04 07:05:39 +02:00
roberto@debian32 4f94ceed5e fix for solaris 2011-08-03 16:00:35 +02:00
roberto@debian32 cd29998b40 --pyshell and fix for wsgi.url_scheme in pep3333 2011-08-03 15:07:15 +02:00
roberto@debian32 9aad6be26a better realoding in lazy mode 2011-08-03 06:54:48 +02:00
roberto@debian32 19edee88bc fixed --log-master 2011-08-02 21:15:10 +02:00
roberto@debian32 42e6a7d024 wait max 60 seconds for gracefull reload 2011-08-02 20:36:16 +02:00
roberto@debian32 1890290d05 fixed reload-mercy in lazy mode 2011-08-02 20:28:31 +02:00
roberto@debian32 c85231be96 improved picasso test 2011-08-02 16:10:17 +02:00
roberto@debian32 0ca89771d6 fixed pump method 2011-08-02 16:01:06 +02:00
roberto@debian32 d203b12464 fixed --http-var 2011-08-02 15:48:54 +02:00
roberto@debian32 b64690bdd6 allow compilation of pump in python3 2011-08-02 15:38:41 +02:00
roberto@debian32 e76c696678 completed pump support 2011-08-02 15:31:39 +02:00
roberto@debian32 f1ad2090fc remove incompatible LDFLAGS 2011-08-02 15:13:21 +02:00
roberto@debian32 f0be3c3966 fixed rack.scheme 2011-08-02 15:02:26 +02:00
roberto@debian32 8b7abc956f first round for pump support 2011-08-02 13:56:52 +02:00
roberto@debian32 25a8af392b fixed a leak in web3 subhandler 2011-08-02 12:48:15 +02:00
roberto@debian32 ebe1b3497e updated web3 handler 2011-08-02 09:33:49 +02:00
roberto@debian32 6a7246fe5a a little fix 2011-07-31 19:47:54 +02:00
roberto@debian32 1d64e46fcd support for data:// in import/module 2011-07-31 19:42:24 +02:00
roberto@debian32 6d5e089e4e uwsgi.ZipImporter 2011-07-31 19:32:14 +02:00
roberto@debian32 845bc1d41b added data:// facility 2011-07-31 18:51:10 +02:00
roberto@solarixexpress 007cd73ac5 solaris fix 2011-07-31 19:13:01 +00:00
roberto@freebsd64 651a7e4078 added freebsd binary detection 2011-07-31 17:47:15 +02:00
roberto@debian32 c3423370ec added binary detection for sun 2011-07-31 16:07:36 +02:00
roberto@mrspurr 500f1e37f6 better binary detection in osx 2011-07-31 17:25:10 +02:00
roberto@debian32 699a9bfa8e better binary detection on linux 2011-07-31 15:39:36 +02:00
roberto@debian32 90aa7f0d0e fixed --set 2011-07-31 14:44:36 +02:00
roberto@debian32 527819703e added -S/--set option 2011-07-31 14:35:54 +02:00
roberto@debian32 47adc8fe48 added --http-socket and --fastcgi-socket 2011-07-29 14:26:07 +02:00
roberto@debian32 865ad5d631 virtualhosting for http protocol 2011-07-29 13:59:29 +02:00
roberto@debian32 877b99c1d5 extreme optimization for http protocol 2011-07-29 13:49:22 +02:00
roberto@debian32 45bb124200 fixed a typo 2011-07-29 10:04:10 +02:00
roberto@debian32 147af04342 fixed apache2 module, adding uWSGImaxVars directive (bug #31) 2011-07-29 08:06:13 +02:00
roberto@debian32 b30e54bdc1 close bug #35 2011-07-29 07:30:24 +02:00
roberto@debian32 1b7484cf22 closed bug #34 2011-07-29 07:27:03 +02:00
roberto@debian32 c04513f8bd fixed SERVER_PORT in http protocol handler 2011-07-29 06:13:50 +02:00
roberto@debian32 c29db6ee6f cache fixed WSGI values 2011-07-29 05:53:54 +02:00
roberto@debian32 0d60b001fb uwsgi.cache_update 2011-07-28 10:27:37 +02:00
roberto@dexter ea7d428c1b added UWSGI.signal_registered 2011-07-27 11:11:30 +02:00
roberto@dexter 55ac61dbb0 signal framework ported to ruby.rack plugin 2011-07-27 10:58:03 +02:00
roberto@mrspurr 048878b197 added uwsgi.signal to ruby interface 2011-07-27 08:27:24 +02:00
roberto@dexter 1e479de839 auto-set post-buffering in rack plugin 2011-07-26 09:46:11 +02:00
roberto@debian32 5b34f6c515 fixed multiprotocol uwsgi.sendfile 2011-07-26 07:06:46 +02:00
roberto@centos6 8fcf83769c a zombie cannot be avoided... 2011-07-25 08:58:17 +02:00
roberto@centos6 d1ca55da55 get rid of a zombie in http-only mode 2011-07-25 08:23:05 +02:00
roberto@gambit 375328623b Added tag 0.9.8.3 for changeset f4d3c4dcd7a6 2011-07-23 08:27:35 +02:00
roberto@gambit be15137a49 uWSGI 0.9.8.3 2011-07-23 08:26:42 +02:00
roberto@dexter 43d89b2eaf added --freebind option (Linux only) 2011-07-22 13:11:14 +02:00
roberto@fedora15 d590a189ed added support for systemd socket activation 2011-07-22 13:03:18 +02:00
roberto@dexter c26861bff6 fixed fd 0 inheritance for xinetd support 2011-07-22 11:11:03 +02:00
roberto@mrspurr b4923deae2 fixed OSX build 2011-07-21 18:50:00 +02:00
roberto@natty32 20e7a65d92 finalized zip import 2011-07-19 21:19:15 +02:00
roberto@natty32 fc895d105e added bootstrap2.py for uwsgi.SymZipImporter class 2011-07-19 20:28:45 +02:00
roberto@natty32 e0e8dbe6b6 added uwsgi.SymZipImporter class 2011-07-19 20:28:04 +02:00
roberto@sirius 8e5834dcbb Added tag 0.9.8.2 for changeset 7169ef1d68d3 2011-07-19 07:53:44 +02:00
roberto@natty32 668c173969 uWSGI 0.9.8.2 2011-07-19 07:36:11 +02:00
roberto@debian32 4c19a941eb disabled embedded loading in python 3.x 2011-07-18 19:18:00 +02:00
roberto@debian32 9761153ab0 symbol based python importer in C 2011-07-18 18:24:01 +02:00
roberto@debian32 140a1b1587 added a django template loader for embedded files 2011-07-16 09:15:14 +02:00
roberto@debian32 e5f5f40f3c added bootstrap.py 2011-07-16 08:20:52 +02:00
roberto@debian32 2e13622ecc build directory 2011-07-16 08:05:26 +02:00
roberto@debian32 a4fb281859 allow directories to be embedded 2011-07-16 08:01:07 +02:00
roberto@dexter 75ba4e2220 better translation in import by filename 2011-07-15 12:02:42 +02:00
roberto@dexter 24b17da2ea added AUTHORS file 2011-07-15 11:15:07 +02:00
roberto@dexter c4664fe6e3 thunder_lock enabled only in threading mode 2011-07-15 10:51:35 +02:00
roberto@debian32 a1ab298609 Changelog for 0.9.8.2 2011-07-15 05:53:05 +02:00
roberto@natty32 533f9f8323 fixed an ini and yaml parsing bug spotted by Raffaele Colace 2011-07-14 20:03:20 +02:00
roberto@sirius 6d5912f307 a couple of spooler improvements 2011-07-13 19:41:56 +02:00
roberto@centos6 3d2b7c136a drop privileges after chown-socket (second-try) 2011-07-12 20:58:40 +02:00
roberto@centos6 f25d147908 drop privileges after chown-socket 2011-07-12 20:54:35 +02:00
roberto@centos6 e119c8cc53 solaris fix 2011-07-12 20:31:48 +02:00
roberto@centos6 73e94350df return the name of the spoolfile on uwsgi.spool() 2011-07-12 20:20:55 +02:00
roberto@centos6 9d8ee5aec8 --chown-socket 2011-07-12 20:11:19 +02:00
roberto@sirius c3bbd5f54f fixed spooler decorators 2011-07-11 19:15:26 +02:00
roberto@natty32 e17be93cb6 fixed rack.input 2011-07-11 11:56:19 +02:00
roberto@natty32 1013ca340a uwsgi.embedded_data 2011-07-10 19:47:53 +02:00
roberto@natty32 b87e7c0af8 added embed_files 2011-07-10 19:31:12 +02:00
roberto@natty32 615348c5a1 new embed_config build_option 2011-07-10 18:13:02 +02:00
roberto@natty32 cae0f9bc2e fixed fd leaks generated by new signal improvements 2011-07-10 16:26:36 +02:00
roberto@sirius 93b23e3de0 fixed cache-server on 64bit 2011-07-07 12:22:36 +02:00
roberto@natty32 eebb00d2b3 cache-server implementation 2011-07-07 12:02:11 +02:00
roberto@natty32 11f9b04fd1 thunder lock (sigh) 2011-07-07 09:58:03 +02:00
roberto@natty32 bde996de75 added -f in rm for make clean 2011-07-07 09:44:57 +02:00
roberto@natty32 552163a3bd second try for fixing inheritance of build profiles 2011-07-07 09:35:14 +02:00
roberto@natty32 2e6af966a9 revert last useless fix 2011-07-07 09:27:38 +02:00
roberto@natty32 c1775967c8 fixed build system 2011-07-07 09:25:10 +02:00
roberto@natty32 034a0a594d remove json from unbitstaff 2011-07-07 09:11:26 +02:00
roberto@natty32 63a66ea82a added an hello_world 2011-07-07 08:35:23 +02:00
roberto@maverick64 6f155ebf17 spooler object debug 2011-07-06 19:43:28 +02:00
roberto@maverick64 f39d8cc5fb fixed spooler for python 3 2011-07-06 18:17:53 +02:00
roberto@maverick64 aecba7e710 export UWSGI_VASSALS_DIR even on stop-hook 2011-07-05 20:17:34 +02:00
roberto@maverick64 c365eeec76 fixed a typo 2011-07-05 15:06:51 +02:00
roberto@maverick64 5bd06402de added shebang in decoratortest.py 2011-07-05 14:56:23 +02:00
roberto@maverick64 ec899a45d5 added body to spooler 2011-07-05 14:55:10 +02:00
roberto@maverick64 513c9cee3d allow plugin to be written in C++ 2011-07-05 11:28:35 +02:00
roberto@mrspurr 850f2abd5c fixed psgi on osx 2011-07-05 07:50:27 +02:00
roberto@maverick64 8d7940ebee fixed plugin value in uwsgi.opt 2011-07-04 16:14:33 +02:00
roberto@maverick64 195e9c398e use TCP port '0' for auto-socket in http mode 2011-07-04 10:38:07 +02:00
roberto@longshot c998d6bd1b fixed a master bug in socketpair 2011-07-04 09:55:13 +02:00
roberto@maverick64 34be14ece1 updated unbit.ini 2011-07-04 09:17:34 +02:00
roberto@maverick64 c0d6f33d54 support SIGQUIT in emperor 2011-07-03 19:17:24 +02:00
roberto@maverick64 d5210283ca launch stop hook on emperor quit 2011-07-03 19:16:09 +02:00
roberto@maverick64 545784d7af fixed ticket #12 reported bugs 2011-07-03 19:08:22 +02:00
roberto@maverick64 e9726b1e75 fixed ticket #28 2011-07-03 12:59:58 +02:00
roberto@maverick64 e08b2cccf9 implemented workerN signal target 2011-07-03 12:55:18 +02:00
roberto@maverick64 0ba1b982d1 implemented target='workers' for signal infrastructure 2011-07-03 12:43:30 +02:00
roberto@maverick64 374c02c46e prefork/multithread uwsgi.signal_wait() implementation 2011-07-03 12:00:06 +02:00
roberto@maverick64 5ed59690a0 report time taken for each spooler job 2011-07-02 19:53:31 +02:00
roberto@maverick64 2de489f301 fixed uwsgi_log_verbose 2011-07-02 19:49:12 +02:00
roberto@maverick64 40a722294f added 'at' variable to the spooler 2011-07-02 11:04:25 +02:00
roberto@maverick64 9598c525cf export uwsgi.node in WSGI vars 2011-07-02 10:03:34 +02:00
roberto@maverick64 3ed6c5e943 added @lock decorator 2011-07-02 09:22:52 +02:00
roberto@maverick64 0f178c17ee report threading status in uwsgicc 2011-07-02 08:43:52 +02:00
roberto@maverick64 1c963b72a3 added @thread decorator 2011-07-02 08:35:08 +02:00
roberto@maverick64 bd1b3b8b12 allows spooler to manage signals 2011-07-01 15:17:43 +02:00
roberto@maverick64 f9a843dfd5 added @postfork decorator 2011-07-01 10:03:16 +02:00
roberto@maverick64 9df8f4ae2b better spooler check 2011-07-01 09:56:38 +02:00
roberto@maverick64 87f649b71b a new bunch of decorators 2011-07-01 09:48:54 +02:00
roberto@sirius 3585bb0a6e added spoolforever 2011-07-01 09:12:30 +02:00
roberto@sirius 750bbd64b2 new option --import, new api function uwsgi.signal_registered 2011-07-01 09:05:55 +02:00
roberto@maverick64 19c567cef3 fixed fastrouter nodes stats 2011-06-30 13:00:14 +02:00
roberto@maverick64 5024368854 gather statistics about subscribed fastrouter nodes 2011-06-30 12:56:13 +02:00
roberto@debian32 3200f88363 applied Riccardo Magliocchetti patch for spooler pid and uwsgicc 2011-06-28 15:14:49 +02:00
roberto@debian32 650c77d0d1 refactored cgroups 2011-06-28 06:46:43 +02:00
roberto@debian32 3fa29515f2 --emperor-broodlord added 2011-06-27 20:27:34 +02:00
roberto@debian32 012435747e first attempt of bloodlord mode 2011-06-27 18:18:24 +02:00
roberto@debian32 733077a437 added another example 2011-06-26 18:18:57 +02:00
roberto@debian32 6b3fa74800 fixed uwsgi.h indentation 2011-06-26 11:36:18 +02:00
roberto@freebsd64 d673627c79 FreeBSD fix and applied riccardo's patch 2011-06-26 11:35:18 +02:00
roberto@debian32 8b423d00e9 added priority keyword to spooler 2011-06-26 11:26:52 +02:00
roberto@gambit 201086c854 uWSGI 0.9.8.1 2011-06-25 10:34:50 +02:00
roberto@gambit 2441cf36b3 Added tag 0.9.8.1 for changeset fd8477b6348f 2011-06-25 10:33:43 +02:00
roberto@debian32 df0f2a549e TODO: survive to dynamic loading errors 2011-06-25 10:24:52 +02:00
roberto@debian32 9b7cbab37c preparing for official release... 2011-06-25 10:09:44 +02:00
roberto@debian32 ac46cb2371 a bit of debug junk 2011-06-25 10:08:42 +02:00
roberto@debian32 c858c88bb3 fixed a race condition 2011-06-25 09:52:42 +02:00
roberto@debian32 a05f5d9860 another series (the last i hope) of threading fixes 2011-06-25 09:36:59 +02:00
roberto@debian32 e6914b91e1 spooler task are now managed asap on startup 2011-06-25 08:13:15 +02:00
roberto@debian32 b624bd2d35 update psgix.harakiri to last spec 2011-06-25 08:03:28 +02:00
roberto@debian32 e3c9b2c0bf cheap+idle+lazy improved for threading 2011-06-25 07:58:40 +02:00
roberto@debian32 576a1e7cb2 fixed threadstate swap 2011-06-25 07:44:21 +02:00
roberto@debian32 55c3ba73d3 added Changelog for 0.9.8.1 2011-06-25 07:27:31 +02:00
roberto@debian32 2246d30bbe fixed threaded loading 2011-06-24 19:42:01 +02:00
roberto@goyle 789e333736 master_fixup on reloads 2011-06-24 07:41:01 +02:00
roberto@goyle 283904107f better master threading 2011-06-24 06:56:30 +02:00
roberto@goyle 8d92261852 re-enabled threads in master process 2011-06-23 20:50:14 +02:00
roberto@goyle e8f5d82b78 -propagate-touch 2011-06-22 12:40:00 +02:00
roberto@goyle 0a8643155e an attempt for a better touch reload in threading mode 2011-06-22 12:12:15 +02:00
roberto@goyle 61793201c7 fixed uwsgi.sendfile in threading mode 2011-06-22 11:14:02 +02:00
roberto@goyle 41f2982074 fixed stupid bug in wsgi.input readline 2011-06-22 07:19:49 +02:00
roberto@goyle 27b86f1b79 fixed a bug in dynamic touch reload 2011-06-21 17:19:28 +02:00
roberto@goyle d69892c91e @europython add --logto2 option 2011-06-21 14:53:50 +02:00
roberto@debian32 296549d1bf export %c in config files 2011-06-18 11:59:37 +02:00
roberto@debian32 7d2f147172 fixed libyaml support and support for modifiers in subscription requests 2011-06-18 11:31:38 +02:00
roberto@debian32 aa56f99ee2 reset random seed on first python spooler job 2011-06-18 09:32:23 +02:00
roberto@debian32 ca82b99f42 subscribe from file 2011-06-18 08:59:02 +02:00
roberto@debian32 d204a5b844 allow binding to port 0 (auto-assignment) 2011-06-18 07:50:37 +02:00
roberto@debian32 0a98550770 reset random seed on grunt 2011-06-18 06:58:01 +02:00
roberto@debian32 0c0c2736a7 maintain a constant mapping in vhost mode 2011-06-17 17:54:49 +02:00
roberto@debian32 27e2d984ce debug in virtualhosting 2011-06-17 17:41:48 +02:00
roberto@debian32 14eeae09b1 fix python3 + virtualenv 2011-06-17 16:31:55 +02:00
roberto@debian32 16eb47070d survive to task doing chdir() in the spooler 2011-06-17 16:20:02 +02:00
roberto@debian32 1f69f58593 fixed a stupid bug in non-async initialization 2011-06-17 08:44:32 +02:00
roberto@debian32 1b4421e013 better zeromq+clustering support 2011-06-17 08:11:56 +02:00
roberto@debian32 f13400d592 improved zeromq support 2011-06-17 07:52:38 +02:00
roberto@mrspurr e29f0323ea fixed make clean 2011-06-17 07:33:53 +02:00
roberto@debian32 15a582d046 allow clustering without a socket 2011-06-17 07:26:36 +02:00
roberto@mrspurr 1e01f8be17 fixed a typecast in fastcgi 2011-06-17 06:39:44 +02:00
roberto@debian32 8cc73991a3 added checks for decorators 2011-06-16 13:52:22 +02:00
roberto@debian32 ecce74ade5 less verbose logging in inotify 2011-06-16 10:16:06 +02:00
roberto@debian32 836efaaf70 less verbose logging in python api for clustering 2011-06-16 07:20:15 +02:00
roberto@debian32 46f8e7dc00 less verbose log in cluster joining 2011-06-16 07:17:35 +02:00
roberto@mrspurr 88cd033ca6 refactored clustering 2011-06-16 07:08:56 +02:00
roberto@debian32 984df3bcdf added signal sending in uwsgicc 2011-06-15 19:05:14 +02:00
roberto@debian32 7673cdb1aa refactored uwsgi_parse_response to uwsgi_parse_packet 2011-06-15 14:01:00 +02:00
roberto@debian32 8af700ce37 fixed rpc 2011-06-15 12:30:01 +02:00
roberto@mrspurr ffb8752190 report corrent worker id in cheap mode 2011-06-15 07:04:07 +02:00
roberto 71fa3ab3af report max buffer_size on pktsize error 2011-06-14 14:07:48 +00:00
roberto@dj1 09501cfa74 remove pipe in uwsgi_daemon 2011-06-14 13:37:33 +00:00
roberto@dj1 d84ae12733 fixed a fd leak in attach-daemon 2011-06-14 13:37:00 +00:00
roberto@dj1 05f292abe6 use setsid in attach-daemon 2011-06-14 13:22:14 +00:00
roberto@sirius a75833d322 OSX fixes 2011-06-14 11:26:03 +02:00
roberto@debian32 ca3f56de5c Zerg mode added 2011-06-14 11:24:25 +02:00
roberto@debian32 9d75f2c9c7 added psgix.harakiri.supported 2011-06-13 19:13:12 +02:00
roberto@debian32 a58cbf92b0 added psgix.harakiri 2011-06-13 16:45:19 +02:00
roberto@debian32 7bac76fae5 added PLACK_SERVER 2011-06-13 11:55:42 +02:00
roberto@debian32 9c71b39edd fixed rpc 2011-06-13 09:07:49 +02:00
roberto@debian32 52f731c6b7 fixed argv clobbering in command line module functions 2011-06-13 08:17:36 +02:00
roberto@dj1.djangocloud.com 735d1cb689 fixed fastrouter 2011-06-12 13:19:39 -05:00
roberto@debian32 5a0977f412 allows magic vars in sqlite3 db 2011-06-12 19:58:38 +02:00
roberto@dj1 1da1fccbc7 fixed plugin loading 2011-06-12 12:19:23 -05:00
roberto@debian32 ca5a528818 added UWSGI_FASTROUTER_KEY var 2011-06-12 11:45:30 +02:00
roberto@debian32 a9ef806a37 added flaskpost to address a bug reported on post-buffering 2011-06-12 09:04:59 +02:00
roberto@debian32 de112b7788 no more than 1 'async queue is full' message per-second 2011-06-12 07:16:24 +02:00
roberto@debian32 ef7baba274 process options in reverse order for better templating 2011-06-12 06:51:45 +02:00
roberto@debian32 3a9d13b011 --cron option, thanks Simon Litchfield for the idea 2011-06-11 15:05:20 +02:00
roberto@debian32 5b5493aab0 --vassals-start-hook and --vassals-stop-hook 2011-06-11 11:56:21 +02:00
roberto@debian32 5f208d8f12 remove the old proxy plugin, bug #8 2011-06-11 10:54:59 +02:00
roberto@debian32 47c077d066 closed bug #14 2011-06-11 10:45:58 +02:00
roberto@debian32 d2ac69b6c1 applied leonid borisenko patch for better automagic plugin loading 2011-06-11 09:47:42 +02:00
roberto@dj1 8860cac7dd close unneded fd in subemperor and vassals 2011-06-08 13:54:50 -05:00
roberto@debian32 28bcc73c70 reintroduced clang support 2011-06-07 21:26:07 +02:00
roberto@netbsd64 af20c2d8f0 fix CMSG_SPACE mess 2011-06-07 22:37:55 +02:00
roberto@mrspurr 44213ca510 move msg_control union to end of struct wsgi_request (as suggested by Riccardo Magliocchetti) 2011-06-07 20:02:24 +02:00
roberto@mrspurr ab21a1ac00 applied Piotr Sikora fix for OpenBSD/NetBSD 2011-06-07 20:00:36 +02:00
roberto@dj1 a67f366501 fix for abstract socket without prefix 2011-06-07 06:21:09 -05:00
roberto@mrspurr b32251e5aa osx launchd examples 2011-06-07 06:37:54 +02:00
roberto@gambit 16e0accb74 uWSGI 0.9.8 2011-06-05 08:28:03 +02:00
roberto@gambit c6ce291cbf Added tag 0.9.8 for changeset 42efe1f32900 2011-06-05 08:27:51 +02:00
143 changed files with 8215 additions and 2723 deletions
+4
View File
@@ -24,3 +24,7 @@ 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
+14
View File
@@ -0,0 +1,14 @@
- this is a incomplete list of all the contributors of the project -
Roberto De Ioris, Unbit, <roberto@unbit.it>
Riccardo Magliocchetti, Unbit, <riccardo@unbit.it>
Yann Malet, Lincoln Loop
Simon Litchfield
Masahiro Honma, <hiratara@cpan.org>
Łukasz Wróblewski <admin@nri.pl>
Giacomo Bagnoli, Asidev
Guido Notari, Link I.T. S.p.a.
Marco Beri, Link I.T. S.p.a.
Leonid Borisenko
Cal Leeming, Simplicity Media Ltd
Luigi Scarso
+76 -1
View File
@@ -1,4 +1,77 @@
*** may 2011 ***
*** july 2011 ***
* 0.9.8.3 [20110723]
- implemented uwsgi.SymZipImporter to load embedded zip files
- OSX Lion is officially supported
- fixed xinetd support (example file added in contrib)
- suppot for systemd socket activation
- added --freebind option (Linux only)
* 0.9.8.2 [20110719]
- fixed an ini and yaml parsing bug spotted by Raffaele Colace
- spooler has been extremely improved
- new option --chown-socket
- added uwsgidecorators for elegant uwsgi api access from python
- the rack plugin is now stable
- support for embedding config and generic files in the server binary
- high-performance cache-server
- accept() is now locked on all threads in the same workers
- preliminary implementation of hooks in emperor
- support for C++ in server core
- tcp port auto-bind
- implemented workers, workerN and spooler signal target
- prefork/multithread uwsgi.signal_wait() implementation
- export uwsgi.node in WSGI vars
- new option --import (python plugin)
- support for unlimited number of Linux cgroups
- broodlord mode
*** june 2011 ***
* 0.9.8.1 [20110625]
- the build system has been improved
- various threading fixes
- fix python GIL status after reload
- new option --propagate-touch
- fixed uwsgi.sendfile
- fixed readline() support in wsgi.input
- fixed dynamic touch reload
- new option --logto2
- export %c in config files
- fixed libyaml support
- support passing modifiers in subscription system
- reset random seed in spooler
- subscribe from a list in a text file
- allow binding on port 0 (auto-assignment)
- reset random seed on grunt
- fix vhost mode for empty hostname
- fixed python3+virtualenv support
- tasks are now allowed to chdir() in spooler
- better zeromq+clustering support
- clustering has been refactored
- fixed rpc
- report correct worker id in cheap mode
- fixed a fd-leak in attach-daemon
- use setsid() in attach-daemon
- zerg mode
- added psgix.harakiri
- allows magic vars in sqlite3 config db
- added UWSGI_FASTROUTER_KEY var
- slowdown async-queue-is-full messages
- new option --cron
- --vassals-start-hook and --vassals-stop-hook
- the proxy plugin has been removed
* 0.9.8 [20110605]
- support for --callable in virtualhosting mode
- a NetBSD fix
- abstract unix socket can be prefixed with \0 (nginx-style)
- add /lib to the linker in sun-like systems
- a mercy mode of 5 seconds is enabled by default on SIGINT/SIGQUIT
* 0.9.8-rc4 [20110602]
@@ -14,6 +87,8 @@
- fixed idle mode in single-process
- fixed solaris iovec
*** may 2011 ***
* 0.9.8-rc3 [20110530]
- snapshotting support
+3
View File
@@ -1,2 +1,5 @@
all:
python uwsgiconfig.py --build
clean:
python uwsgiconfig.py --clean
+74 -39
View File
@@ -51,7 +51,6 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
#include <fcntl.h>
#define MAX_VARS 64
#define DEFAULT_SOCK "/tmp/uwsgi.sock"
typedef struct {
@@ -73,6 +72,7 @@ typedef struct {
char script_name[256];
char scheme[9];
int cgi_mode ;
int max_vars;
} uwsgi_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
@@ -83,8 +83,18 @@ static uint16_t uwsgi_swap16(uint16_t x) {
}
#endif
static int uwsgi_add_var(struct iovec *vec, int i, char *key, char *value, uint16_t *pkt_size) {
static int uwsgi_add_var(struct iovec *vec, int i, request_rec *r, char *key, char *value, uint16_t *pkt_size) {
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
#if APR_IS_BIGENDIAN
if (i+6 > c->max_vars) {
#else
if (i+4 > c->max_vars) {
#endif
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: max number of uwsgi variables reached. consider increasing it with uWSGImaxVars directive");
return i;
}
#if APR_IS_BIGENDIAN
char *ptr;
@@ -150,6 +160,7 @@ static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
c->modifier1 = 0 ;
c->modifier2 = 0 ;
c->cgi_mode = 0 ;
c->max_vars = 128;
return c;
}
@@ -164,6 +175,7 @@ static void *uwsgi_dir_config(apr_pool_t *p, char *dir) {
c->modifier1 = 0 ;
c->modifier2 = 0 ;
c->cgi_mode = 0 ;
c->max_vars = 128;
return c;
}
@@ -243,11 +255,8 @@ static int uwsgi_handler(request_rec *r) {
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
#if APR_IS_BIGENDIAN
struct iovec uwsgi_vars[(MAX_VARS*6)+1] ;
#else
struct iovec uwsgi_vars[(MAX_VARS*4)+1] ;
#endif
struct iovec *uwsgi_vars;
int vecptr = 1 ;
char pkt_header[4];
uint16_t pkt_size = 0;
@@ -315,48 +324,53 @@ static int uwsgi_handler(request_rec *r) {
}
#if APR_IS_BIGENDIAN
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*6)+1);
#else
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*4)+1);
#endif
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
if (c->scheme[0] != 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
}
if (c->script_name[0] == '/') {
if (c->script_name[1] == 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri, &pkt_size) ;
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", c->script_name, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", c->script_name, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
}
}
else {
if (r->path_info) {
if (strlen(r->path_info) <= 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri, &pkt_size) ;
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri, (strlen(r->uri) - strlen(r->path_info) )) , &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->path_info, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri, (strlen(r->uri) - strlen(r->path_info) )) , &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->path_info, &pkt_size) ;
}
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri, &pkt_size) ;
}
}
@@ -364,19 +378,13 @@ static int uwsgi_handler(request_rec *r) {
headers = apr_table_elts(r->headers_in);
h = (apr_table_entry_t *) headers->elts;
// check for max vars (a bit ugly)
cnt = headers->nelts ;
if (cnt + 11 > MAX_VARS) {
cnt = MAX_VARS -11;
}
for(i=0;i< cnt;i++) {
for(i=0;i< headers->nelts;i++) {
if (h[i].key){
if (!strcasecmp(h[i].key, "Content-Type")) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_TYPE", h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_TYPE", h[i].val, &pkt_size) ;
}
else if (!strcasecmp(h[i].key, "Content-Length")) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
}
else {
penv = apr_pstrcat(r->pool, "HTTP_", h[i].key, NULL);
@@ -388,7 +396,7 @@ static int uwsgi_handler(request_rec *r) {
*cp = toupper(*cp);
}
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, penv, h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, penv, h[i].val, &pkt_size) ;
}
}
}
@@ -397,7 +405,7 @@ static int uwsgi_handler(request_rec *r) {
headers = apr_table_elts(r->subprocess_env);
h = (apr_table_entry_t*) headers->elts;
for (i = 0; i < headers->nelts; ++i) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, h[i].key, h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, h[i].key, h[i].val, &pkt_size) ;
}
@@ -418,11 +426,13 @@ static int uwsgi_handler(request_rec *r) {
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() %s", strerror(errno));
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt != pkt_size+4) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() returned wrong size");
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -434,6 +444,7 @@ static int uwsgi_handler(request_rec *r) {
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: read() client block failed !");
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -458,6 +469,7 @@ static int uwsgi_handler(request_rec *r) {
if (cnt == 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
@@ -467,6 +479,7 @@ static int uwsgi_handler(request_rec *r) {
if (errno != ECONNRESET) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else {
@@ -489,6 +502,7 @@ static int uwsgi_handler(request_rec *r) {
if (r->connection->aborted) {
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
@@ -508,6 +522,7 @@ static int uwsgi_handler(request_rec *r) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -521,6 +536,7 @@ static int uwsgi_handler(request_rec *r) {
if (!c->cgi_mode) {
if (uwsgi_http_status_read == 0) {
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -528,11 +544,13 @@ static int uwsgi_handler(request_rec *r) {
if (hret = ap_scan_script_header_err_brigade(r, bb, NULL)) {
apr_brigade_destroy(bb);
free(uwsgi_vars);
return hret;
}
}
free(uwsgi_vars);
return ap_pass_brigade(r->output_filters, bb) ;
}
@@ -564,6 +582,22 @@ static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const
}
static const char *cmd_uwsgi_max_vars(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
int val ;
if (cfg) {
c = cfg ;
}
else {
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
c->max_vars = atoi(value);
return NULL;
}
static const char * cmd_uwsgi_modifier1(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
@@ -707,6 +741,7 @@ static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
AP_INIT_TAKE1("uWSGImaxVars", cmd_uwsgi_max_vars, NULL, ACCESS_CONF, "Set the maximum allowed number of uwsgi variables (default 128)"),
{NULL}
};
+12 -2
View File
@@ -202,14 +202,20 @@ void *async_loop(void *arg1) {
int is_a_new_connection;
int proto_parser_status;
time_t now, last_now = 0;
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
void *events = event_queue_alloc(64);
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
struct uwsgi_socket *uwsgi_sock;
uwsgi.async_runqueue = NULL;
uwsgi.async_runqueue_cnt = 0;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
}
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
@@ -260,7 +266,11 @@ void *async_loop(void *arg1) {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
uwsgi_log("async queue is full !!!\n");
now = time(NULL);
if (now > last_now) {
uwsgi_log("async queue is full !!!\n");
last_now = now;
}
break;;
}
+13
View File
@@ -0,0 +1,13 @@
import struct
import sys
import os
filename = sys.argv[1]
size = os.path.getsize(filename)
f = open(filename, 'r')
print(f.read())
f.close()
print(struct.pack("<Q", size))
+4
View File
@@ -0,0 +1,4 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.SymbolsImporter())
+4
View File
@@ -0,0 +1,4 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("pygments_zip"))
+5
View File
@@ -0,0 +1,5 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("django_zip:djenv/lib/python2.6/site-packages"))
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("djapp_zip"))
+4
View File
@@ -0,0 +1,4 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.ZipImporter("data://0"))
+1
View File
@@ -0,0 +1 @@
object file for embedded files will be put here
+5
View File
@@ -28,12 +28,17 @@ bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, ugreen
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
embed_files =
embed_config =
[python]
paste = true
web3 = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embed_files = bootstrap3.py,django.zip,djapp.zip
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = default
embed_files = embedme.py,uwsgidecorators.py
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = symcall
as_shared_library = true
-4
View File
@@ -1,7 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,lua
[python]
paste = true
web3 = true
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = rack, ping, nagios, rpc
embedded_plugins = rack, ping, cache, nagios, rpc, fastrouter, http, ugreen
+13 -1
View File
@@ -2,6 +2,9 @@
xml = true
ini = true
yaml = true
json = true
sqlite3 = true
zeromq = false
snmp = false
sctp = false
spooler = true
@@ -10,14 +13,23 @@ udp = true
multicast = false
threading = true
sendfile = true
nagios = false
minterpreters = true
async = true
evdis = false
ldap = true
pcre = false
debug = false
unbit = true
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
plugins =
bin_name = /opt/unbit/bin/uwsgi
append_version = unbit
plugin_dir = /opt/unbit/uwsgi_plugins
embedded_plugins =
locking = auto
event = auto
timer = auto
filemonitor = auto
+1
View File
@@ -1,5 +1,6 @@
[uwsgi]
inherit = unbit
json = false
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
+143 -7
View File
@@ -131,7 +131,7 @@ struct uwsgi_subscriber_name *uwsgi_get_subscriber(struct uwsgi_dict *udict, cha
return ret;
}
void uwsgi_add_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *address, uint64_t address_len) {
void uwsgi_add_subscriber(struct uwsgi_dict *udict, struct uwsgi_subscribe_req *usr) {
char *ptr;
uint64_t vallen = 0;
@@ -139,11 +139,11 @@ void uwsgi_add_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen,
int found = 0;
int i;
ptr = uwsgi_dict_get(udict, key, keylen, &vallen);
ptr = uwsgi_dict_get(udict, usr->key, usr->keylen, &vallen);
if (ptr && vallen) {
usub = (struct uwsgi_subscriber *) ptr;
for(i=0;i<(int)usub->nodes;i++) {
if (!uwsgi_strncmp(usub->names[i].name, usub->names[i].len, address, address_len)) {
if (!uwsgi_strncmp(usub->names[i].name, usub->names[i].len, usr->address, usr->address_len)) {
found = 1;
break;
}
@@ -157,8 +157,10 @@ void uwsgi_add_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen,
break;
}
}
usub->names[found].len = address_len;
memcpy(usub->names[found].name, address, address_len);
usub->names[found].len = usr->address_len;
usub->names[found].modifier1 = usr->modifier1;
usub->names[found].modifier2 = usr->modifier2;
memcpy(usub->names[found].name, usr->address, usr->address_len);
if (found == (int) usub->nodes) {
usub->nodes++;
}
@@ -168,8 +170,10 @@ void uwsgi_add_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen,
else {
nusub.nodes = 1;
nusub.current = 0;
memcpy(nusub.names[0].name, address, address_len);
uwsgi_dict_set(udict, key, keylen, (char *) &nusub, sizeof(struct uwsgi_subscriber));
memcpy(nusub.names[0].name, usr->address, usr->address_len);
nusub.names[0].modifier1 = usr->modifier1;
nusub.names[0].modifier2 = usr->modifier2;
uwsgi_dict_set(udict, usr->key, usr->keylen, (char *) &nusub, sizeof(struct uwsgi_subscriber));
}
}
@@ -508,6 +512,16 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
uci->prev = last_index;
}
}
else if (flags && UWSGI_CACHE_FLAG_UPDATE) {
uci = &uwsgi.cache_items[index] ;
if (expires) {
expires += time(NULL);
uci->expires = expires;
}
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
uci->valsize = vallen;
ret = 0;
}
end:
return ret;
@@ -578,3 +592,125 @@ end:
return ret;
}
/* THIS PART IS HEAVILY OPTIMIZED: PERFORMANCE NOT ELEGANCE !!! */
void *cache_thread_loop(void *fd_ptr) {
int *fd_tmp = (int *) fd_ptr;
int fd = *fd_tmp;
int i;
ssize_t len;
char uwsgi_packet[UMAX16+4];
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi_packet;
char *val;
uint64_t vallen;
char *key;
uint16_t keylen;
struct pollfd ctl_poll;
char *watermark;
struct sockaddr_un ctl_sun;
socklen_t ctl_sun_len;
ctl_poll.events = POLLIN;
for(;;) {
ctl_sun_len = sizeof(struct sockaddr_un);
pthread_mutex_lock(&uwsgi.cache_server_lock);
ctl_poll.fd = accept(fd, (struct sockaddr *) &ctl_sun, &ctl_sun_len);
pthread_mutex_unlock(&uwsgi.cache_server_lock);
if (ctl_poll.fd < 0) {
uwsgi_error("cache accept()");
continue;
}
i = 0;
while(i < 4) {
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (len <= 0) {
uwsgi_error("cache poll()");
goto clear;
}
len = read(ctl_poll.fd, uwsgi_packet+i, 4-i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i+=len;
}
if (uh->pktsize == 0) goto clear;
while(i < 4+uh->pktsize) {
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (len <= 0) {
uwsgi_error("cache poll()");
goto clear;
}
len = read(ctl_poll.fd, uwsgi_packet+i, (4+uh->pktsize)-i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i+=len;
}
watermark = uwsgi_packet+4+uh->pktsize;
// get first parameter
memcpy(&keylen, uwsgi_packet+4, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
#endif
if (uwsgi_packet+6+keylen > watermark) goto clear;
key = uwsgi_packet+6+keylen+2;
memcpy(&keylen, key-2, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
#endif
if (key+keylen > watermark) goto clear;
val = uwsgi_cache_get(key, keylen, &vallen);
if (val && vallen > 0) {
if (write(ctl_poll.fd, val, vallen) < 0) {
uwsgi_error("cache write()");
}
}
clear:
close(ctl_poll.fd);
}
return NULL;
}
int uwsgi_cache_server(char *socket, int threads) {
int *fd = uwsgi_malloc(sizeof(int));
int i;
pthread_t thread_id;
char *tcp_port = strchr(socket, ':');
if (tcp_port) {
*fd = bind_to_tcp(socket, uwsgi.listen_queue, tcp_port);
}
else {
*fd = bind_to_unix(socket, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
pthread_mutex_init(&uwsgi.cache_server_lock, NULL);
if (threads < 1) threads = 1;
uwsgi_log("*** cache-optimized server enabled on fd %d (%d threads) ***\n", *fd, threads);
for(i=0;i<threads;i++) {
pthread_create(&thread_id, NULL, cache_thread_loop, (void *) fd);
}
return *fd;
}
+25
View File
@@ -0,0 +1,25 @@
require 'stringio'
hello = proc do |signum|
puts "Hello i am signal #{signum}"
end
file_changed = proc do |signum|
puts "/tmp has been modified"
end
UWSGI.register_signal(17, '', hello)
UWSGI.register_signal(30, '', file_changed)
UWSGI.add_rb_timer(17 , 2)
UWSGI.add_timer(17 , 1)
UWSGI.add_file_monitor(30 , '/tmp')
puts UWSGI.signal_registered(1)
puts UWSGI.signal_registered(17)
run lambda { |env|
puts env.inspect
UWSGI.signal(17)
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World!\n")]
}
+11
View File
@@ -0,0 +1,11 @@
from tasksconsumer import enqueue
def application(env, sr):
sr('200 OK', [('Content-Type','text/html')])
enqueue(queue='fast', pippo='pluto')
return "Task enqueued"
+9
View File
@@ -0,0 +1,9 @@
from tasksconsumer import *
@queueconsumer('fast', 4)
def fast_queue(arguments):
print "fast", arguments
@queueconsumer('slow')
def slow_queue(arguments):
print "foobar", arguments
+44
View File
@@ -0,0 +1,44 @@
from uwsgidecorators import *
import Queue
from threading import Thread
queues = {}
class queueconsumer(object):
def __init__(self, name, num=1, **kwargs):
self.name = name
self.num = num
self.queue = Queue.Queue()
self.threads = []
self.func = None
queues[self.name] = self
@staticmethod
def consumer(self):
while True:
req = self.queue.get()
print req
self.func(req)
self.queue.task_done()
def __call__(self, f):
self.func = f
for i in range(self.num):
t = Thread(target=self.consumer,args=(self,))
self.threads.append(t)
t.daemon = True
t.start()
@spool
def spooler_enqueuer(arguments):
if 'queue' in arguments:
queue = arguments['queue']
queues[queue].queue.put(arguments)
else:
raise Exception("You have to specify a queue name")
def enqueue(*args, **kwargs):
return spooler_enqueuer.spool(*args, **kwargs)
+14
View File
@@ -0,0 +1,14 @@
service uwsgi
{
disable = no
id = uwsgi-000
type = UNLISTED
socket_type = stream
server = /root/uwsgi/uwsgi
server_args = --chdir /root/uwsgi/ --module welcome --logto /tmp/uwsgi.log
port = 3031
bind = 127.0.0.1
user = root
wait = yes
}
+122
View File
@@ -0,0 +1,122 @@
#!./uwsgi --import decoratortest -s :3035 -M --spooler myspool --enable-threads -p 8 --spooler-ordered
import uwsgi
from uwsgidecorators import *
from uwsgicc import app as application
import time
# register rpc function helloworld
@rpc("helloworld")
def hello_world():
return "Hello World"
# register signal 1
@signal(1)
def what_time_is_it(num):
print(time.asctime())
# register signal 100
@signal(100, target='workers')
def what_time_is_it(num):
print("*** I AM THE WORKER %d AT %s ***" % (uwsgi.worker_id(), time.asctime()))
# a 3 seconds timer
@timer(3)
def salut(num):
print("Salut !!! 3 seconds elapsed and signal %d raised" % num)
# a 10 seconds red black timer (executed by the spooler)
@rbtimer(10, target='spooler')
def tenseconds(num):
print("red black timer !!! 10 seconds elapsed and signal %d raised" % num)
# monitor /tmp directory
@filemon("/tmp")
def tmpmodified(num):
print("/tmp has been modified")
# spool a long running task
@spool
def a_long_task(args):
for i in xrange(1,10):
print("%s = %d" % ( str(args), i))
time.sleep(1)
# continuosly spool a long running task
@spoolforever
def an_infinite_task(args):
for i in xrange(1,4):
print("infinite: %d %s" % (i, str(args)))
time.sleep(1)
# spool a task after 60 seconds
@spool
def delayed_task(args):
print("*** I am a delayed spool job. It is %s [%s]***" % (time.asctime(), str(args)))
# send a signal to all workers
uwsgi.signal(100)
@spool
def big_body_task(args):
print("*** managing a task with a body of %d bytes ***" % len(args['body']))
print(args['body'].swapcase())
# run a task every hour
@cron(59, -1, -1, -1, -1)
def one_hour_passed(num):
print("received signal %d after 1 hour" % num)
@thread
def a_running_thread():
while True:
time.sleep(2)
print("i am a no-args thread")
@thread
def a_running_thread_with_args(who):
while True:
time.sleep(2)
print("Hello %s (from arged-thread)" % who)
@postfork
@thread
def a_post_fork_thread():
while True:
time.sleep(3)
print("Hello from a thread in worker %d" % uwsgi.worker_id())
@postfork
def fork_happened():
print("fork() has been called [1]")
@postfork
def fork_happened2():
print("waiting for a signal...")
uwsgi.signal_wait()
print("signal received: %d" % uwsgi.signal_received())
print("fork() has been called [2] wid: %d" % uwsgi.worker_id())
@postfork
@lock
def locked_func():
print("starting locked function on worker %d" % uwsgi.worker_id())
for i in xrange(1, 100):
time.sleep(0.2)
print("[locked %d] waiting..." % uwsgi.worker_id())
print("done with locked function on worker %d" % uwsgi.worker_id())
spool_filename = a_long_task.spool({'foo':'bar'}, hello='world')
print("spool filename = %s" % spool_filename)
an_infinite_task.spool(foo='bar', priority=3)
delayed_task.spool(foo2='bar2', at=time.time()+60)
a_running_thread()
a_running_thread_with_args("uWSGI")
uwsgi_source_file = open('uwsgi.c','r')
print(big_body_task.spool(priority=9,filename='uwsgi.c',body=uwsgi_source_file.read()))
uwsgi_source_file.close()
+29
View File
@@ -0,0 +1,29 @@
from django.template.base import TemplateDoesNotExist
from django.template.loader import BaseLoader
from django.conf import settings
try:
import uwsgi
on_uwsgi = True
except:
on_uwsgi = False
class Loader(BaseLoader):
is_usable = on_uwsgi
def symbolize(self, name):
return name.replace('.','_').replace('/','_').replace('-','_')
def load_template_source(self, template_name, template_dirs=None):
filename = 'templates_' + self.symbolize(template_name)
for app in settings.INSTALLED_APPS:
try:
symbol = "%s_%s" % (self.symbolize(app), filename)
return (uwsgi.embedded_data(symbol), "sym://%s" % symbol)
except:
pass
raise TemplateDoesNotExist(template_name)
+122 -20
View File
@@ -6,37 +6,71 @@ extern struct uwsgi_server uwsgi;
extern char **environ;
int emperor_queue;
char *emperor_absolute_dir;
struct uwsgi_instance {
struct uwsgi_instance *ui_prev;
struct uwsgi_instance *ui_next;
char name[0xff];
pid_t pid;
int status;
time_t born;
time_t last_mod;
time_t last_loyal;
uint64_t respawns;
int use_config;
int pipe[2];
int pipe_config[2];
char *config;
uint32_t config_len;
int loyal;
int zerg;
};
struct uwsgi_instance *ui;
static void royal_death(int signum) {
if (uwsgi.vassals_stop_hook) {
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
uwsgi_log("running vassal stop-hook: %s %s\n", uwsgi.vassals_stop_hook, c_ui->name);
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
uwsgi_error("setenv()");
}
int stop_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_stop_hook, c_ui->name);
uwsgi_log("%s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
c_ui = c_ui->ui_next;
}
}
uwsgi_notify("The Emperor is buried.");
exit(0);
}
struct uwsgi_instance {
struct uwsgi_instance *ui_prev;
struct uwsgi_instance *ui_next;
char name[0xff];
pid_t pid;
void emperor_stats() {
int status;
time_t born;
time_t last_mod;
time_t last_loyal;
struct uwsgi_instance *c_ui = ui->ui_next;
uint64_t respawns;
int use_config;
while (c_ui) {
int pipe[2];
int pipe_config[2];
uwsgi_log("vassal instance %s (last modified %d) status %d loyal %d zerg %d\n",c_ui->name, c_ui->last_mod, c_ui->status, c_ui->loyal, c_ui->zerg);
char *config;
uint32_t config_len;
c_ui = c_ui->ui_next;
}
int loyal;
};
struct uwsgi_instance *ui;
}
struct uwsgi_instance *emperor_get_by_fd(int fd) {
@@ -84,8 +118,21 @@ void emperor_del(struct uwsgi_instance *c_ui) {
close(c_ui->pipe_config[0]);
}
if (uwsgi.vassals_stop_hook) {
uwsgi_log("running vassal stop-hook: %s %s\n", uwsgi.vassals_stop_hook, c_ui->name);
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
uwsgi_error("setenv()");
}
int stop_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_stop_hook, c_ui->name);
uwsgi_log("%s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
}
uwsgi_log("removed uwsgi instance %s\n", c_ui->name);
if (c_ui->zerg) {
uwsgi.emperor_broodlord_count--;
}
free(c_ui);
}
@@ -131,6 +178,8 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
char *uef;
char **uenvs;
int counter;
char *colon = NULL;
int i;
sleep(1);
@@ -152,6 +201,12 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
uwsgi_log("c_ui->ui_next = %p\n", c_ui->ui_next);
#endif
n_ui->ui_prev = c_ui;
if (strchr(name,':')) {
n_ui->zerg = 1;
uwsgi.emperor_broodlord_count++;
}
memcpy(n_ui->name, name, strlen(name));
n_ui->born = born;
n_ui->last_mod = born;
@@ -256,6 +311,13 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
argv[0] = uwsgi.binary_path;
if (uwsgi.emperor_broodlord) {
colon = strchr(name, ':');
if (colon) {
colon[0] = 0;
}
}
if (!strcmp(name + (strlen(name) - 4), ".xml"))
argv[1] = "--xml";
if (!strcmp(name + (strlen(name) - 4), ".ini"))
@@ -266,6 +328,10 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 3), ".js"))
argv[1] = "--json";
if (colon) {
colon[0] = ':';
}
argv[2] = name;
counter = 3;
uct = uwsgi.vassals_templates;
@@ -276,6 +342,23 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
uct = uct->next;
}
argv[counter] = NULL;
// close all of the unneded fd
for(i=3;i<sysconf(_SC_OPEN_MAX);i++) {
if (i != n_ui->pipe[1]) {
close(i);
}
}
if (uwsgi.vassals_start_hook) {
uwsgi_log("running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name);
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
uwsgi_error("setenv()");
}
int start_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_start_hook, n_ui->name);
uwsgi_log("%s start-hook returned %d\n", n_ui->name, start_hook_ret);
}
// start !!!
if (execvp(argv[0], argv)) {
uwsgi_error("execvp()");
@@ -320,6 +403,8 @@ void emperor_loop() {
signal(SIGPIPE, SIG_IGN);
uwsgi_unix_signal(SIGINT, royal_death);
uwsgi_unix_signal(SIGTERM, royal_death);
uwsgi_unix_signal(SIGQUIT, royal_death);
uwsgi_unix_signal(SIGUSR1, emperor_stats);
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
@@ -374,6 +459,7 @@ reconnect:
uwsgi_error("glob()");
exit(1);
}
emperor_absolute_dir = realpath(".", NULL);
}
ui = &ui_base;
@@ -422,6 +508,7 @@ reconnect:
ui_current->config = config;
ui_current->config_len = msgsize;
if (!msgsize) {
// SAFE
emperor_del(ui_current);
}
else {
@@ -480,6 +567,7 @@ reconnect:
char byte;
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
emperor_del(ui_current);
}
else {
@@ -489,6 +577,15 @@ reconnect:
// TODO post-start hook
}
else if (byte == 22) {
emperor_stop(ui_current);
}
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
char *zerg_name = uwsgi_concat3(ui_current->name,":","zerg");
emperor_add(zerg_name, time(NULL), NULL, 0);
free(zerg_name);
}
}
}
else {
@@ -609,25 +706,29 @@ reconnect:
if (amqp_fd > -1) {
if (!ui_current->loyal && (time(NULL)-ui_current->last_loyal) > 60) {
uwsgi_log("!!! no loyalty showed by instance %s !!!\n", ui_current->name);
// SAFE
emperor_del(ui_current);
break;
}
}
if (ui_current->status == 1) {
if (ui_current->config) free(ui_current->config);
// SAFE
emperor_del(ui_current);
break;
}
else if (!ui_current->use_config && strncmp(ui_current->name, "http://",7) && stat(ui_current->name, &st)) {
else if (!ui_current->use_config && strncmp(ui_current->name, "http://",7) && stat(ui_current->name, &st) && !ui_current->zerg) {
emperor_stop(ui_current);
}
else if (ui_current->pid == diedpid) {
if (ui_current->status == 0) {
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
// SAFE
emperor_del(ui_current);
}
else {
// UNSAFE
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len);
emperor_del(ui_current);
}
@@ -636,6 +737,7 @@ reconnect:
else if (ui_current->status == 1) {
// remove 'marked for dead' instance
if (ui_current->config) free(ui_current->config);
// SAFE
emperor_del(ui_current);
break;
}
+4 -2
View File
@@ -591,7 +591,9 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
*id = inotify_add_watch(ifd, filename, IN_ATTRIB|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MODIFY|IN_MOVE_SELF|IN_MOVED_FROM|IN_MOVED_TO);
#ifdef UWSGI_DEBUG
uwsgi_log("added watch %d for filename %s\n", *id, filename);
#endif
if (add_to_queue) {
return event_queue_add_fd_read(eq, ifd);
@@ -630,7 +632,9 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
}
else {
items = isize/(sizeof(struct inotify_event));
#ifdef UWSGI_DEBUG
uwsgi_log("inotify returned %d items\n", items);
#endif
for(j=0;j<items;j++) {
iie = &bie[j];
for(i=0;i<ushared->files_monitored_cnt;i++) {
@@ -816,8 +820,6 @@ int event_queue_add_timer(int eq, int *id, int sec) {
*id = timer_id ;
timer_id++;
uwsgi_log("registering timer %d\n", sec);
EV_SET(&kev, *id, EVFILT_TIMER, EV_ADD, 0, sec*1000, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
+12
View File
@@ -0,0 +1,12 @@
from flask import Flask, request
app = Flask(__name__)
app.debug = True
@app.route('/')
def hello_world():
return "<form method='POST' enctype='multipart/form-data' action='/upload'><input type='text' name='pippo'/><input type='file' name='ufile'/><input type='submit' value='upload'/></form>"
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
return str(len(request.form.get('pippo', 'boh'))) + request.form.get('pippo', 'boh')
return request.files['ufile'].read()
+12 -1
View File
@@ -60,6 +60,11 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
uwsgi_error("prctl()");
}
#endif
if (!uwsgi.sockets) {
// wait for child end
//waitpid(-1, &i, 0);
}
loop();
// never here !!! (i hope)
exit(1);
@@ -117,6 +122,12 @@ void gateway_respawn(int id) {
}
ug->pid = gw_pid;
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
ug->respawns++;
if (ug->respawns == 1) {
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
else {
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
}
+6
View File
@@ -0,0 +1,6 @@
import uwsgi
#uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
yield str(env['wsgi.input'].fileno())
yield "<h1>Hello World</h1>"
+14 -2
View File
@@ -67,6 +67,11 @@ char *ini_get_line(char *ini, off_t size) {
}
}
// check if it is a stupid file without \n at the end
if (ptr > ini) {
return ptr;
}
return NULL;
}
@@ -87,7 +92,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
char *section_asked = "uwsgi";
char *colon;
if (!uwsgi_startswith(file, "http://", 7)) {
if (!uwsgi_startswith(file, "http://", 7) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6) ) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
@@ -102,7 +107,9 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
}
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
if (file[0] != 0) {
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
}
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
@@ -143,6 +150,11 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
if (colon) {
colon[0] = ':';
}
}
#endif
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>it.unbit.uwsgi.emperor</string>
<key>ProgramArguments</key>
<array>
<string>/Users/roberta/uwsgi/uwsgi</string>
<string>--emperor</string>
<string>/Users/*/Library/uwsgi/*.{xml,ini,yml,yaml,js}</string>
</array>
</dict>
</plist>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>it.unbit.uwsgi</string>
<key>ProgramArguments</key>
<array>
<string>/Users/roberta/uwsgi/uwsgi</string>
<string>--socket</string>
<string>:3032</string>
<string>--module</string>
<string>welcome</string>
<string>--master</string>
<string>--die-on-term</string>
</array>
</dict>
</plist>
+5 -1
View File
@@ -30,7 +30,7 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
char *colon;
int i;
if (!uwsgi_startswith(file, "http://", 7)) {
if (!uwsgi_startswith(file, "http://", 7) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
@@ -49,7 +49,11 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
#ifdef JANSSON_MAJOR_VERSION
root = json_loads(json_data, 0, &error);
#else
root = json_loads(json_data, &error);
#endif
if (!root) {
uwsgi_log("error parsing JSON data: line %d %s\n", error.line, error.text);
+25
View File
@@ -25,6 +25,16 @@
#include "../uwsgi.h"
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
struct rb_node *right = node->rb_right;
@@ -282,3 +292,18 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
#ifdef __clang__
void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#else
inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#endif
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
+7 -19
View File
@@ -37,7 +37,6 @@ struct rb_root
struct rb_node *rb_node;
};
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(r) (!rb_color(r))
@@ -45,24 +44,13 @@ struct rb_root
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
void rb_insert_color(struct rb_node *, struct rb_root *);
void rb_erase(struct rb_node *, struct rb_root *);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
#ifdef __clang__
void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
#else
inline void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
#endif
+3 -1
View File
@@ -50,7 +50,7 @@ void log_request(struct wsgi_request *wsgi_req) {
if (wsgi_req->do_not_log) return ;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi.apps[wsgi_req->app_id];
wi = &uwsgi_apps[wsgi_req->app_id];
if (wi->requests > 0) {
app_req = wi->requests;
}
@@ -173,6 +173,8 @@ void get_memusage() {
#if defined(__FreeBSD__)
kv = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, NULL);
#elif defined(__NetBSD__) || defined(__OpenBSD__)
kv = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
#else
kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
#endif
+45 -6
View File
@@ -66,19 +66,20 @@ void *simple_loop(void *arg1) {
#endif
// initialize the main event queue to monitor sockets
uwsgi.main_queue = event_queue_init();
int main_queue = event_queue_init();
uwsgi_add_sockets_to_queue(uwsgi.main_queue);
uwsgi_add_sockets_to_queue(main_queue);
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.main_queue, uwsgi.signal_socket);
event_queue_add_fd_read(main_queue, uwsgi.signal_socket);
event_queue_add_fd_read(main_queue, uwsgi.my_signal_socket);
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
wsgi_req_setup(wsgi_req, core_id, NULL);
if (wsgi_req_accept(wsgi_req)) {
if (wsgi_req_accept(main_queue, wsgi_req)) {
continue;
}
@@ -91,6 +92,18 @@ void *simple_loop(void *arg1) {
}
// end of the loop
if (uwsgi.workers[uwsgi.mywid].destroy && uwsgi.workers[0].pid > 0) {
#ifdef __APPLE__
kill(uwsgi.workers[0].pid, SIGTERM);
#else
if (uwsgi.propagate_touch) {
kill(uwsgi.workers[0].pid, SIGHUP);
}
else {
gracefully_kill(0);
}
#endif
}
return NULL;
}
@@ -103,7 +116,7 @@ void *zeromq_loop(void *arg1) {
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
uwsgi.zeromq_recv_flag = 0;
zmq_pollitem_t zmq_poll_items[2];
zmq_pollitem_t zmq_poll_items[3];
char uwsgi_signal;
if (uwsgi.threads > 1) {
@@ -147,6 +160,10 @@ void *zeromq_loop(void *arg1) {
zmq_poll_items[1].socket = NULL;
zmq_poll_items[1].fd = uwsgi.signal_socket;
zmq_poll_items[1].events = ZMQ_POLLIN;
zmq_poll_items[2].socket = NULL;
zmq_poll_items[2].fd = uwsgi.my_signal_socket;
zmq_poll_items[2].events = ZMQ_POLLIN;
}
@@ -159,7 +176,7 @@ void *zeromq_loop(void *arg1) {
if (uwsgi.signal_socket > -1) {
if (zmq_poll(zmq_poll_items, 2, -1) < 0) {
if (zmq_poll(zmq_poll_items, 3, -1) < 0) {
uwsgi_error("zmq_poll()");
continue;
}
@@ -172,7 +189,9 @@ void *zeromq_loop(void *arg1) {
}
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
}
@@ -180,6 +199,26 @@ void *zeromq_loop(void *arg1) {
continue;
}
if (zmq_poll_items[2].revents & ZMQ_POLLIN) {
if (read(uwsgi.my_signal_socket, &uwsgi_signal, 1) <= 0) {
if (uwsgi.no_orphans) {
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
end_me(0);
}
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
}
}
continue;
}
if (zmq_poll_items[0].revents & ZMQ_POLLIN) {
wsgi_req->poll.fd = wsgi_req->socket->proto_accept(wsgi_req, uwsgi.zmq_socket->fd);
}
+223 -84
View File
@@ -42,32 +42,24 @@ void expire_rb_timeouts(struct rb_root *root) {
}
}
void uwsgi_subscribe(char *subscription) {
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, char *modifier1, size_t modifier1_len) {
char *ssb;
char subscrbuf[4096];
uint16_t ustrlen;
char *udp_address = strchr(subscription,':');
if (!udp_address) return;
ssb = subscrbuf;
char *subscription_key = strchr(udp_address+1, ':');
if (!subscription_key) return;
udp_address = uwsgi_concat2n(subscription, subscription_key-subscription, "", 0);
ssb = subscrbuf;
ustrlen = 3;
ustrlen = 3;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "key", ustrlen);
ssb+=ustrlen;
ustrlen = strlen(subscription_key+1);
ustrlen = keysize;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, subscription_key+1, ustrlen);
memcpy(ssb, key, ustrlen);
ssb+=ustrlen;
ustrlen = 7;
@@ -82,8 +74,106 @@ void uwsgi_subscribe(char *subscription) {
memcpy(ssb, uwsgi.sockets->name, ustrlen);
ssb+=ustrlen;
if (modifier1) {
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "modifier1", ustrlen);
ssb+=ustrlen;
ustrlen = modifier1_len;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, modifier1, ustrlen);
ssb+=ustrlen;
}
send_udp_message(224, udp_address, subscrbuf, ssb-subscrbuf);
free(udp_address);
}
void uwsgi_subscribe(char *subscription) {
int subfile_size;
int i;
char *key = NULL;
int keysize = 0;
char *modifier1 = NULL;
int modifier1_len = 0;
char *udp_address = strchr(subscription,':');
if (!udp_address) return;
char *subscription_key = strchr(udp_address+1, ':');
if (!subscription_key) return;
udp_address = uwsgi_concat2n(subscription, subscription_key-subscription, "", 0);
if (subscription_key[1] == '@') {
if (!uwsgi_file_exists(subscription_key+2)) goto clear;
char *lines = uwsgi_open_and_read(subscription_key+2, &subfile_size, 1, NULL);
if (subfile_size > 0) {
key = lines;
for(i=0;i<subfile_size;i++) {
if (lines[i] == 0) {
if (keysize > 0) {
if (key[0] != '#' && key[0] != '\n') {
modifier1 = strchr(key, ',');
if (modifier1) {
modifier1[0] = 0;
modifier1++;
modifier1_len = strlen(modifier1);
keysize = strlen(key);
}
uwsgi_send_subscription(udp_address, key, keysize, modifier1, modifier1_len);
modifier1 = NULL;
modifier1_len = 0;
}
}
break;
}
else if (lines[i] == '\n') {
if (keysize > 0) {
if (key[0] != '#' && key[0] != '\n') {
lines[i] = 0;
modifier1 = strchr(key, ',');
if (modifier1) {
modifier1[0] = 0;
modifier1++;
modifier1_len = strlen(modifier1);
keysize = strlen(key);
}
uwsgi_send_subscription(udp_address, key, keysize, modifier1, modifier1_len);
modifier1 = NULL;
modifier1_len = 0;
lines[i] = '\n';
}
}
key = lines+i+1;
keysize = 0;
continue;
}
keysize++;
}
free(lines);
}
}
else {
modifier1 = strchr(subscription_key+1, ',');
if (modifier1) {
modifier1[0] = 0;
modifier1++;
modifier1_len = strlen(modifier1);
}
uwsgi_send_subscription(udp_address, subscription_key+1, strlen(subscription_key+1), modifier1, modifier1_len);
if (modifier1)
modifier1[-1] = ',';
}
clear:
free(udp_address);
}
@@ -98,6 +188,18 @@ void get_linux_tcp_info(int fd) {
}
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS] = uwsgi.shared->ti.tcpi_unacked;
if (uwsgi.vassal_sos_backlog > 0 && uwsgi.has_emperor) {
if ((int)uwsgi.shared->ti.tcpi_unacked >= uwsgi.vassal_sos_backlog) {
// ask emperor for help
char byte = 30;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("write()");
}
else {
uwsgi_log("asking emperor for reinforcements (backlog: %d)...\n", (int) uwsgi.shared->ti.tcpi_unacked);
}
}
}
if (uwsgi.shared->ti.tcpi_unacked >= uwsgi.shared->ti.tcpi_sacked) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%d/%d) ***\n", fd, uwsgi.shared->ti.tcpi_unacked, uwsgi.shared->ti.tcpi_sacked);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
@@ -110,7 +212,10 @@ void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t val
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
@@ -187,7 +292,6 @@ void master_loop(char **argv, char **environ) {
struct uwsgi_rb_timer *min_timeout;
struct rb_root *rb_timers = uwsgi_init_rb_timer();
struct tm *uwsgi_cron_delta;
uwsgi.current_time = time(NULL);
@@ -206,7 +310,6 @@ void master_loop(char **argv, char **environ) {
uwsgi_unix_signal(SIGURG, uwsgi_restore_auto_snapshot);
}
uwsgi.master_queue = event_queue_init();
/* route signals to workers... */
@@ -228,6 +331,12 @@ void master_loop(char **argv, char **environ) {
if (uwsgi.has_emperor) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
}
if (uwsgi.zerg_server) {
uwsgi.zerg_server_fd = bind_to_unix(uwsgi.zerg_server, uwsgi.listen_queue, 0, 0);
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.zerg_server_fd);
uwsgi_log("*** Zerg server enabled on %s ***\n", uwsgi.zerg_server);
}
#ifdef UWSGI_UDP
if (uwsgi.udp_socket) {
udp_fd = bind_to_udp(uwsgi.udp_socket, 0, 0);
@@ -387,10 +496,19 @@ void master_loop(char **argv, char **environ) {
for (;;) {
//uwsgi_log("ready_to_reload %d %d\n", ready_to_reload, uwsgi.numproc);
if (uwsgi.to_outworld) {
//uwsgi_log("%d/%d\n", uwsgi.lazy_respawned, uwsgi.numproc);
if (uwsgi.lazy_respawned >= uwsgi.numproc) {
uwsgi.to_outworld = 0;
uwsgi.master_mercy = 0;
uwsgi.lazy_respawned = 0;
}
}
if (uwsgi.master_mercy) {
if (uwsgi.master_mercy < time(NULL)) {
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0) {
if (uwsgi.lazy && uwsgi.workers[i].destroy == 0) continue;
uwsgi_log("worker %d (pid: %d) is taking too much time to die...NO MERCY !!!\n", i, uwsgi.workers[i].pid);
if (!kill(uwsgi.workers[i].pid, SIGKILL)) {
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
@@ -399,12 +517,17 @@ void master_loop(char **argv, char **environ) {
uwsgi.workers[i].pid = 0;
if (uwsgi.to_hell) { ready_to_die++;}
else if (uwsgi.to_heaven) { ready_to_reload++;}
else if (uwsgi.to_outworld) {
uwsgi.lazy_respawned++;
if (uwsgi_respawn_worker(i)) return;
}
}
else {
uwsgi_error("kill()");
}
}
}
uwsgi.master_mercy = 0;
}
}
if (uwsgi.respawn_workers) {
@@ -600,70 +723,11 @@ void master_loop(char **argv, char **environ) {
// check uwsgi-cron table
if (ushared->cron_cnt) {
uwsgi.current_time = time(NULL);
uwsgi_cron_delta = localtime( &uwsgi.current_time );
uwsgi_manage_signal_cron(time(NULL));
}
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for(i=0;i<ushared->cron_cnt;i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = ucron->minute;
uc_hour = ucron->hour;
uc_day = ucron->day;
uc_month = ucron->month;
uc_week = ucron->week;
if (ucron->minute == -1) uc_minute = uwsgi_cron_delta->tm_min;
if (ucron->hour == -1) uc_hour = uwsgi_cron_delta->tm_hour;
if (ucron->month == -1) uc_month = uwsgi_cron_delta->tm_mon;
// mday and wday are ORed
if (ucron->day == -1 && ucron->week == -1) {
if (ucron->day == -1) uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1) uc_week = uwsgi_cron_delta->tm_wday;
}
else if (ucron->day == -1) {
ucron->day = uwsgi_cron_delta->tm_mday;
}
else if (ucron->week == -1) {
ucron->week = uwsgi_cron_delta->tm_wday;
}
else {
if (ucron->day == uwsgi_cron_delta->tm_mday) {
ucron->week = uwsgi_cron_delta->tm_wday;
}
else if (ucron->week == uwsgi_cron_delta->tm_wday) {
ucron->day = uwsgi_cron_delta->tm_mday;
}
}
if (uwsgi_cron_delta->tm_min == uc_minute &&
uwsgi_cron_delta->tm_hour == uc_hour &&
uwsgi_cron_delta->tm_mon == uc_month &&
uwsgi_cron_delta->tm_mday == uc_day &&
uwsgi_cron_delta->tm_wday == uc_week) {
// date match, signal it ?
if (uwsgi.current_time - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = uwsgi.current_time;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
if (uwsgi.crons) {
uwsgi_manage_command_cron(time(NULL));
}
if (rlen > 0) {
@@ -688,17 +752,70 @@ void master_loop(char **argv, char **environ) {
else if (uwsgi.log_socket) {
sendto(uwsgi.log_socket_fd, log_buf, rlen, 0, &uwsgi.log_socket_addr->sa, uwsgi.log_socket_size);
}
else {
rlen = write(uwsgi.original_log_fd, log_buf, rlen);
}
// TODO allow uwsgi.logger = func
}
}
}
if (uwsgi.zerg_server) {
if (interesting_fd == uwsgi.zerg_server_fd) {
struct sockaddr_un zsun;
socklen_t zsun_len = sizeof(struct sockaddr_un);
int zerg_client = accept(uwsgi.zerg_server_fd, (struct sockaddr *) &zsun, &zsun_len);
if (zerg_client < 0) {
uwsgi_error("zerg: accept()");
continue;
}
struct msghdr zerg_msg;
void *zerg_msg_control = uwsgi_malloc(CMSG_SPACE (sizeof (int) * uwsgi_count_sockets(uwsgi.sockets)));
struct iovec zerg_iov;
struct cmsghdr *cmsg;
zerg_iov.iov_base = "uwsgi-zerg";
zerg_iov.iov_len = 10;
zerg_msg.msg_name = NULL;
zerg_msg.msg_namelen = 0;
zerg_msg.msg_iov = &zerg_iov;
zerg_msg.msg_iovlen = 1;
zerg_msg.msg_flags = 0;
zerg_msg.msg_control = zerg_msg_control;
zerg_msg.msg_controllen = CMSG_SPACE (sizeof (int) * uwsgi_count_sockets(uwsgi.sockets));
cmsg = CMSG_FIRSTHDR (&zerg_msg);
cmsg->cmsg_len = CMSG_LEN (sizeof (int) * uwsgi_count_sockets(uwsgi.sockets));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
unsigned char *zerg_fd_ptr = CMSG_DATA(cmsg);
while(uwsgi_sock) {
memcpy(zerg_fd_ptr, &uwsgi_sock->fd, sizeof(int));
zerg_fd_ptr += sizeof(int);
uwsgi_sock = uwsgi_sock->next;
}
if (sendmsg(zerg_client, &zerg_msg, 0) < 0) {
uwsgi_error("sendmsg()");
}
close(zerg_client);
free(zerg_msg_control);
}
}
if (uwsgi.has_emperor) {
if (interesting_fd == uwsgi.emperor_fd) {
char byte;
rlen = read(uwsgi.emperor_fd, &byte, 1);
if (rlen > 0) {
uwsgi_log("received message %d from emperor\n", byte);
uwsgi_log_verbose("received message %d from emperor\n", byte);
// remove me
if (byte == 0) {
close(uwsgi.emperor_fd);
@@ -888,7 +1005,9 @@ void master_loop(char **argv, char **environ) {
uwsgi_error("read()");
}
else if (rlen > 0) {
uwsgi_log("received uwsgi signal %d from workers\n", uwsgi_signal);
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("received uwsgi signal %d from a worker\n", uwsgi_signal);
#endif
uwsgi_route_signal(uwsgi_signal);
}
else {
@@ -938,6 +1057,21 @@ void master_loop(char **argv, char **environ) {
}
else if (uwsgi.current_time - last_request_timecheck > uwsgi.idle) {
uwsgi_log("workers have been inactive for more than %d seconds\n", uwsgi.idle);
uwsgi.cheap = 1;
master_has_children = 0;
if (uwsgi.die_on_idle) {
if (uwsgi.has_emperor) {
char byte = 22;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("write()");
kill_them_all(0);
}
}
else {
kill_them_all(0);
}
continue;
}
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid == 0) continue;
kill(uwsgi.workers[i].pid, SIGKILL);
@@ -945,8 +1079,6 @@ void master_loop(char **argv, char **environ) {
uwsgi_error("waitpid()");
}
}
master_has_children = 0;
uwsgi.cheap = 1;
uwsgi_add_sockets_to_queue(uwsgi.master_queue);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
last_request_timecheck = 0;
@@ -1171,6 +1303,13 @@ void master_loop(char **argv, char **environ) {
uwsgi.workers[uwsgi.mywid].harakiri = 0;
continue;
}
else if (uwsgi.to_outworld) {
uwsgi.lazy_respawned++;
uwsgi.workers[uwsgi.mywid].destroy = 0;
uwsgi.workers[uwsgi.mywid].pid = 0;
// only to be safe :P
uwsgi.workers[uwsgi.mywid].harakiri = 0;
}
if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
+235 -45
View File
@@ -7,63 +7,253 @@ void master_check_cluster_nodes() {
int i;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_STATIC && ucn->status == UWSGI_NODE_FAILED) {
// should i retry ?
if (uwsgi.master_cycles % ucn->errors == 0) {
if (!uwsgi_ping_node(i, uwsgi.wsgi_req)) {
ucn->status = UWSGI_NODE_OK;
uwsgi_log( "re-enabled cluster node %d/%s\n", i, ucn->name);
}
else {
ucn->errors++;
}
}
}
else if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_DYNAMIC) {
// if the last_seen attr is higher than 30 secs ago, mark the node as dead
if ( (uwsgi.current_time - ucn->last_seen) > 30) {
uwsgi_log_verbose("no presence announce in the last 30 seconds by node %s, i assume it is dead.\n", ucn->name);
ucn->name[0] = 0 ;
}
}
}
if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_STATIC && ucn->status == UWSGI_NODE_FAILED) {
// should i retry ?
if (uwsgi.master_cycles % ucn->errors == 0) {
if (!uwsgi_ping_node(i, uwsgi.wsgi_req)) {
ucn->status = UWSGI_NODE_OK;
uwsgi_log("re-enabled cluster node %d/%s\n", i, ucn->name);
}
else {
ucn->errors++;
}
}
}
else if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_DYNAMIC) {
// if the last_seen attr is higher than 30 secs ago, mark the node as dead
if ((uwsgi.current_time - ucn->last_seen) > 30) {
uwsgi_log_verbose("no presence announce in the last 30 seconds by node %s, i assume it is dead.\n", ucn->name);
ucn->name[0] = 0;
}
}
}
}
int uwsgi_respawn_worker(int wid) {
int respawns = uwsgi.workers[wid].respawn_count;
int i;
if (uwsgi.master_process) {
if (uwsgi.signal_pipe[wid][0] != -1) close(uwsgi.signal_pipe[wid][0]);
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.signal_pipe[wid])) {
uwsgi_error("socketpair()\n");
}
}
pid_t pid = fork();
if (pid == 0) {
uwsgi.mywid = wid;
// fix the communication pipe
close(uwsgi.shared->worker_signal_pipe[0]);
uwsgi.mypid = getpid();
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].requests = 0;
uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
return 1;
}
else if (pid < 1) {
uwsgi_error("fork()");
}
else {
if (respawns > 0) {
uwsgi_log( "Respawned uWSGI worker %d (new pid: %d)\n", uwsgi.mywid, (int) pid);
if (pid == 0) {
uwsgi.mywid = wid;
uwsgi.mypid = getpid();
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].requests = 0;
uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
// close the cache server
if (uwsgi.cache_server_fd != -1) {
close(uwsgi.cache_server_fd);
}
if (uwsgi.master_process) {
// fix the communication pipe
close(uwsgi.shared->worker_signal_pipe[0]);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.signal_pipe[i][0] != -1) {
close(uwsgi.signal_pipe[i][0]);
}
}
else {
uwsgi_log("spawned uWSGI worker %d (pid: %d, cores: %d)\n", wid, pid, uwsgi.cores);
uwsgi.my_signal_socket = uwsgi.signal_pipe[wid][1];
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
}
}
#endif
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
}
}
return 1;
}
else if (pid < 1) {
uwsgi_error("fork()");
}
else {
if (uwsgi.master_process) {
close(uwsgi.signal_pipe[wid][1]);
}
if (respawns > 0) {
uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
}
else {
uwsgi_log("spawned uWSGI worker %d (pid: %d, cores: %d)\n", wid, pid, uwsgi.cores);
}
}
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi.current_time = now;
uwsgi_cron_delta = localtime(&uwsgi.current_time);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = ucron->minute;
uc_hour = ucron->hour;
uc_day = ucron->day;
uc_month = ucron->month;
uc_week = ucron->week;
if (ucron->minute == -1)
uc_minute = uwsgi_cron_delta->tm_min;
if (ucron->hour == -1)
uc_hour = uwsgi_cron_delta->tm_hour;
if (ucron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
// mday and wday are ORed
if (ucron->day == -1 && ucron->week == -1) {
if (ucron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
}
else if (ucron->day == -1) {
ucron->day = uwsgi_cron_delta->tm_mday;
}
else if (ucron->week == -1) {
ucron->week = uwsgi_cron_delta->tm_wday;
}
else {
if (ucron->day == uwsgi_cron_delta->tm_mday) {
ucron->week = uwsgi_cron_delta->tm_wday;
}
else if (ucron->week == uwsgi_cron_delta->tm_wday) {
ucron->day = uwsgi_cron_delta->tm_mday;
}
}
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
// date match, signal it ?
if (uwsgi.current_time - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = uwsgi.current_time;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uwsgi.current_time = now;
uwsgi_cron_delta = localtime(&uwsgi.current_time);
if (!uwsgi_cron_delta) {
uwsgi_error("localtime()");
return;
}
while (current_cron) {
uc_minute = current_cron->minute;
uc_hour = current_cron->hour;
uc_day = current_cron->day;
uc_month = current_cron->month;
uc_week = current_cron->week;
if (current_cron->minute == -1)
uc_minute = uwsgi_cron_delta->tm_min;
if (current_cron->hour == -1)
uc_hour = uwsgi_cron_delta->tm_hour;
if (current_cron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
// mday and wday are ORed
if (current_cron->day == -1 && current_cron->week == -1) {
if (current_cron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (current_cron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
}
else if (current_cron->day == -1) {
current_cron->day = uwsgi_cron_delta->tm_mday;
}
else if (current_cron->week == -1) {
current_cron->week = uwsgi_cron_delta->tm_wday;
}
else {
if (current_cron->day == uwsgi_cron_delta->tm_mday) {
current_cron->week = uwsgi_cron_delta->tm_wday;
}
else if (current_cron->week == uwsgi_cron_delta->tm_wday) {
current_cron->day = uwsgi_cron_delta->tm_mday;
}
}
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
// date match, run command ?
if (uwsgi.current_time - current_cron->last_job > 60) {
//call command
if (current_cron->command) {
if (uwsgi_run_command(current_cron->command) >=0) {
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
}
}
current_cron->last_job = uwsgi.current_time;
}
}
current_cron = current_cron->next;
}
}
+3 -8
View File
@@ -1,14 +1,9 @@
import werkzeug
def web3_app(environ):
status = b'200 OK'
headers = [(b'Content-type', b'text/plain')]
body = [b'I am a Web3 app\n']
return body, status, headers
import uwsgi
def zero_app(e,s):
s('200 OK', [ ('Content-Type', 'text/plain') ])
return ""
return "0"
def not_found(e,s):
s('404 Not Found', [ ('Content-Type', 'text/plain') ])
@@ -24,4 +19,4 @@ def internal_server_error(e, s):
s('500 Internal Server Error', [ ('Content-Type', 'text/plain') ])
return ""
applications = {'':web3_app, '/wsgi':wsgi_app, '/test':werkzeug.test_app, '/zero':zero_app, '/notfound':not_found, '/ise':internal_server_error}
uwsgi.applications = {'/wsgi':wsgi_app, '/test':werkzeug.test_app, '/zero':zero_app, '/notfound':not_found, '/ise':internal_server_error}
+3
View File
@@ -9,6 +9,9 @@ void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && tmp_vallen > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("cache value size: %llu\n", tmp_vallen);
#endif
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
}
+63
View File
@@ -0,0 +1,63 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
class FakeClass {
public:
char *foobar;
uint16_t foobar_len;
void hello_world(struct wsgi_request *);
};
void FakeClass::hello_world(struct wsgi_request *wsgi_req) {
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n", 44);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, foobar, foobar_len);
}
extern "C" int uwsgi_cplusplus_init(){
uwsgi_log("Initializing example c++ plugin\n");
return 0;
}
extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
FakeClass *fc;
// empty request ?
if (!wsgi_req->uh.pktsize) {
uwsgi_log( "Invalid request. skip.\n");
goto clear;
}
// get uwsgi variables
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid request. skip.\n");
goto clear;
}
fc = new FakeClass();
// get PATH_INFO
fc->foobar = uwsgi_get_var(wsgi_req, (char *) "PATH_INFO", &fc->foobar_len);
if (fc->foobar) {
// send output
fc->hello_world(wsgi_req);
}
delete fc;
clear:
return UWSGI_OK;
}
extern "C" void uwsgi_cplusplus_after_request(struct wsgi_request *wsgi_req) {
uwsgi_log("logging c++ request\n");
}
+17
View File
@@ -0,0 +1,17 @@
#include "../../uwsgi.h"
int uwsgi_cplusplus_init(void);
int uwsgi_cplusplus_request(struct wsgi_request *);
void uwsgi_cplusplus_after_request(struct wsgi_request *);
struct uwsgi_plugin cplusplus_plugin = {
.name = "cplusplus",
.modifier1 = 250,
.init = uwsgi_cplusplus_init,
.request = uwsgi_cplusplus_request,
.after_request = uwsgi_cplusplus_after_request,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='cplusplus'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lstdc++']
GCC_LIST = ['base.cc', 'plugin']
+1 -1
View File
@@ -5,7 +5,7 @@ extern struct uwsgi_server uwsgi;
int uwsgi_echo_request(struct wsgi_request *wsgi_req) {
wsgi_req->response_size = wsgi_req->socket_proto_write(wsgi_req, wsgi_req->buffer, wsgi_req->uh.pktsize);
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, wsgi_req->buffer, wsgi_req->uh.pktsize);
return 0;
}
+17 -5
View File
@@ -2,21 +2,33 @@
extern struct uwsgi_server uwsgi;
int uwsgi_init(char *args){
uwsgi_log("i am the example plugin initialization function with arg: %s\n", args);
int uwsgi_example_init(){
uwsgi_log("i am the example plugin initialization function\n");
return 0;
}
int uwsgi_request(struct wsgi_request *wsgi_req) {
int uwsgi_example_request(struct wsgi_request *wsgi_req) {
char *http = "HTTP/1.1 200 Ok\r\nContent-type: text/html\r\n\r\n<h1>Hello World</h1>";
wsgi_req->response_size += wsgi_req->socket_proto_write(wsgi_req, http, strlen(http));
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, http, strlen(http));
return 0;
}
void uwsgi_after_request(struct wsgi_request *wsgi_req) {
void uwsgi_example_after_request(struct wsgi_request *wsgi_req) {
uwsgi_log("i am the example plugin after request function\n");
}
struct uwsgi_plugin example_plugin = {
.name = "example",
.modifier1 = 250,
.init = uwsgi_example_init,
.request = uwsgi_example_request,
.after_request = uwsgi_example_after_request,
};
+5 -2
View File
@@ -1,3 +1,6 @@
NAME='example'
CFLAGS = ''
LDFLAGS = ''
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['example_plugin']
+91 -6
View File
@@ -19,6 +19,7 @@
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER 150005
#define LONG_ARGS_FASTROUTER_TIMEOUT 150006
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT 150007
#define LONG_ARGS_FASTROUTER_USE_CODE_STRING 150008
#define FASTROUTER_STATUS_FREE 0
#define FASTROUTER_STATUS_CONNECTING 1
@@ -55,6 +56,10 @@ struct uwsgi_fastrouter {
int socket_timeout;
uint8_t code_string_modifier1;
char *code_string_code;
char *code_string_function;
struct rb_root *timeouts;
} ufr;
@@ -90,6 +95,7 @@ struct option fastrouter_options[] = {
{"fastrouter-use-cache", no_argument, &ufr.use_cache, 1},
{"fastrouter-use-pattern", required_argument, 0, LONG_ARGS_FASTROUTER_USE_PATTERN},
{"fastrouter-use-base", required_argument, 0, LONG_ARGS_FASTROUTER_USE_BASE},
{"fastrouter-use-code-string", required_argument, 0, LONG_ARGS_FASTROUTER_USE_CODE_STRING},
{"fastrouter-events", required_argument, 0, LONG_ARGS_FASTROUTER_EVENTS},
{"fastrouter-subscription-server", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER},
{"fastrouter-subscription-slot", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT},
@@ -111,6 +117,10 @@ void fastrouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
usr->address = val;
usr->address_len = vallen;
}
else if (!uwsgi_strncmp("modifier1", 9, key, keylen)) {
usr->modifier1 = uwsgi_str_num(val, vallen);
}
}
struct fastrouter_session {
@@ -126,6 +136,8 @@ struct fastrouter_session {
char *hostname;
uint16_t hostname_len;
int has_key;
char *instance_address;
uint64_t instance_address_len;
@@ -134,6 +146,8 @@ struct fastrouter_session {
struct uwsgi_rb_timer *timeout;
int instance_failed;
uint8_t modifier1;
};
static void close_session(struct fastrouter_session **fr_table, struct fastrouter_session *fr_session) {
@@ -187,7 +201,14 @@ void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, voi
return;
}
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen)) {
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !fr_session->has_key) {
fr_session->hostname = val;
fr_session->hostname_len = vallen;
return;
}
if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) {
fr_session->has_key = 1;
fr_session->hostname = val;
fr_session->hostname_len = vallen;
return;
@@ -272,6 +293,8 @@ void fastrouter_loop() {
}
}
uwsgi_log("uwsgi fastrouter/proxy bound on %s\n", ufr_sock->name);
event_queue_add_fd_read(fr_queue, ufr_sock->fd);
ufr_sock = ufr_sock->next;
}
@@ -335,6 +358,7 @@ void fastrouter_loop() {
fr_table[new_connection]->status = FASTROUTER_STATUS_RECV_HDR;
fr_table[new_connection]->h_pos = 0;
fr_table[new_connection]->pos = 0;
fr_table[new_connection]->un = NULL;
fr_table[new_connection]->instance_failed = 0;
fr_table[new_connection]->instance_address_len = 0;
@@ -360,7 +384,7 @@ void fastrouter_loop() {
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf+4, len-4, fastrouter_manage_subscription, &usr);
uwsgi_add_subscriber(ufr.subscription_dict, usr.key, usr.keylen, usr.address, usr.address_len);
uwsgi_add_subscriber(ufr.subscription_dict, &usr);
}
}
else {
@@ -414,9 +438,16 @@ void fastrouter_loop() {
break;
}
//uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
#ifdef UWSGI_DEBUG
uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
#endif
if (ufr.use_cache) {
fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
if (cs_mod) {
fr_session->modifier1 = uwsgi_str_num(cs_mod+1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address))-1);
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
}
}
else if (ufr.pattern) {
magic_table['s'] = uwsgi_concat2n(fr_session->hostname, fr_session->hostname_len, "", 0);
@@ -430,6 +461,7 @@ void fastrouter_loop() {
if (fr_session->un && fr_session->un->len) {
fr_session->instance_address = fr_session->un->name;
fr_session->instance_address_len = fr_session->un->len;
fr_session->modifier1 = fr_session->un->modifier1;
}
}
else if (ufr.base) {
@@ -437,6 +469,19 @@ void fastrouter_loop() {
fr_session->instance_address_len = tmp_socket_name_len;
fr_session->instance_address = tmp_socket_name;
}
else if (ufr.code_string_code && ufr.code_string_function) {
if (uwsgi.p[ufr.code_string_modifier1]->code_string) {
fr_session->instance_address = uwsgi.p[ufr.code_string_modifier1]->code_string("uwsgi_fastrouter", ufr.code_string_code, ufr.code_string_function, fr_session->hostname, fr_session->hostname_len);
if (fr_session->instance_address) {
fr_session->instance_address_len = strlen(fr_session->instance_address);
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
if (cs_mod) {
fr_session->modifier1 = uwsgi_str_num(cs_mod+1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address))-1);
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
}
}
}
}
// no address found
if (!fr_session->instance_address_len) {
@@ -487,11 +532,17 @@ void fastrouter_loop() {
break;
}
fr_session->uh.modifier1 = fr_session->modifier1;
iov[0].iov_base = &fr_session->uh;
iov[0].iov_len = 4;
iov[1].iov_base = fr_session->buffer;
iov[1].iov_len = fr_session->uh.pktsize;
// increment node requests counter
if (fr_session->un)
fr_session->un->requests++;
// fd passing: PERFORMANCE EXTREME BOOST !!!
if (fr_session->pass_fd && !uwsgi.no_fd_passing) {
msg.msg_name = NULL;
@@ -547,6 +598,10 @@ void fastrouter_loop() {
close_session(fr_table, fr_session);
break;
}
// update transfer statistics
if (fr_session->un)
fr_session->un->transferred += len;
}
// body from client
else if (interesting_fd == fr_session->fd) {
@@ -597,9 +652,17 @@ int fastrouter_init() {
if (!ufr.nevents) ufr.nevents = 64;
if (register_gateway("fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
if (ufr.code_string_code && ufr.code_string_function) {
if (register_fat_gateway("fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
}
}
else {
if (register_gateway("fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
}
}
}
@@ -608,6 +671,10 @@ int fastrouter_init() {
int fastrouter_opt(int i, char *optarg) {
char *cs;
char *cs_code;
char *cs_func;
switch(i) {
case LONG_ARGS_FASTROUTER:
uwsgi_fastrouter_new_socket(generate_socket_name(optarg));
@@ -628,6 +695,24 @@ int fastrouter_opt(int i, char *optarg) {
// optimization
ufr.base_len = strlen(ufr.base);
return 1;
case LONG_ARGS_FASTROUTER_USE_CODE_STRING:
cs = uwsgi_str(optarg);
cs_code = strchr(cs, ':');
if (!cs_code) {
uwsgi_log("invalid code_string option\n");
exit(1);
}
cs_code[0] = 0;
cs_func = strchr(cs_code+1, ':');
if (!cs_func) {
uwsgi_log("invalid code_string option\n");
exit(1);
}
cs_func[0] = 0;
ufr.code_string_modifier1 = atoi(cs);
ufr.code_string_code = cs_code+1;
ufr.code_string_function = cs_func+1;
return 1;
case LONG_ARGS_FASTROUTER_TIMEOUT:
ufr.socket_timeout = atoi(optarg);
return -1;
+10 -4
View File
@@ -403,6 +403,14 @@ int http_parse(struct http_session *h_session) {
ptr++;
}
int i;
for(i=0;i<uhttp.http_vars_cnt;i++) {
char *equal = strchr(uhttp.http_vars[i],'=');
if (equal) {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, uhttp.http_vars[i], equal-uhttp.http_vars[i], equal+1, strlen(equal+1), &c);
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("vec size: %d pkt size: %d load %d\n", c, h_session->uh.pktsize, uhttp.load);
#endif
@@ -542,7 +550,7 @@ void http_loop() {
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf+4, len-4, http_manage_subscription, &usr);
uwsgi_add_subscriber(uhttp.subscription_dict, usr.key, usr.keylen, usr.address, usr.address_len);
uwsgi_add_subscriber(uhttp.subscription_dict, &usr);
}
}
else {
@@ -869,9 +877,7 @@ int http_init() {
if (!uhttp.nevents) uhttp.nevents = 64;
if (!uhttp.base && !uhttp.use_cache && !uhttp.to && !uwsgi.sockets && !uhttp.subscription_server && !uhttp.use_cluster) {
char *rand_name = uwsgi_malloc(64);
snprintf(rand_name, 64, "%d_%d.sock", (int) time(NULL), (int) getpid());
uwsgi.sockets = uwsgi_new_socket(rand_name);
uwsgi_new_socket(uwsgi_concat2("127.0.0.1:0", ""));
}
uhttp.server = bind_to_tcp(uhttp.socket_name, uwsgi.listen_queue, strchr(uhttp.socket_name,':'));
+10
View File
@@ -16,6 +16,16 @@ NAME='jvm'
JVM_INCPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.15/include/linux"
JVM_LIBPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/i386/server/"
try:
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
except:
pass
try:
JVM_LIBPATH = os.environ['UWSGICONFIG_JVM_LIBPATH']
except:
pass
try:
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
except:
+95 -25
View File
@@ -374,7 +374,7 @@ void uwsgi_lua_app() {
luaL_openlibs(ulua.L[i]);
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
uwsgi_log("unable to load file %s\n", ulua.filename);
uwsgi_log("unable to load file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
exit(1);
}
// use a pcall
@@ -403,8 +403,7 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
if ((i = lua_pcall(L, 0, 1, 0)) == 0) {
if (lua_type(L, -1) == LUA_TSTRING) {
http = lua_tolstring(L, -1, &slen);
if ( (rlen = write(wsgi_req->poll.fd, http, slen)) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
return UWSGI_OK;
}
wsgi_req->response_size += rlen;
@@ -420,12 +419,12 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
/* Standard WSAPI request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log( "Invalid WSAPI request. skip.\n");
goto clear;
goto clear2;
}
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid WSAPI request. skip.\n");
goto clear;
goto clear2;
}
// put function in the stack
@@ -453,12 +452,16 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
lua_setfield(L, -2, "read");
lua_setfield(L, -2, "input");
#ifdef UWSGI_DEBUG
uwsgi_log("stack pos %d\n", lua_gettop(L));
#endif
// call function
i = lua_pcall(L, 1, 3, 0);
if (i != 0) {
uwsgi_log("%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
lua_pushvalue(L, -1);
goto clear;
}
@@ -468,26 +471,30 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
// send status
if (lua_type(L, -3) == LUA_TSTRING || lua_type(L, -3) == LUA_TNUMBER) {
http = lua_tolstring(L, -3, &slen);
if (write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len) != wsgi_req->protocol_len) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len)) != wsgi_req->protocol_len) {
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, " ", 1) != 1) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, " ", 1)) != 1) {
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
// a performance hack
ptrbuf = (char *) http;
ptrbuf[3] = 0;
wsgi_req->status = atoi(ptrbuf);
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
}
else {
raw = 1;
@@ -499,31 +506,41 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
lua_pushnil(L);
while(lua_next(L, -3) != 0) {
http = lua_tolstring(L, -2, &slen);
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, ": ", 2) != 2) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, ": ", 2)) != 2) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
http = lua_tolstring(L, -1, &slen);
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
lua_pop(L, 1);
wsgi_req->header_cnt++;
}
if (!raw) {
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
}
// send body with coroutine
@@ -532,8 +549,9 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
while ( (i = lua_pcall(L, 0, 1, 0)) == 0) {
if (lua_type(L, -1) == LUA_TSTRING) {
http = lua_tolstring(L, -1, &slen);
if ( (rlen = write(wsgi_req->poll.fd, http, slen)) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pop(L, 1);
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->response_size += rlen;
@@ -550,6 +568,7 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
clear:
lua_pop(L, 4);
clear2:
// set frequency
lua_gc(L, LUA_GCCOLLECT, 0);
@@ -590,6 +609,55 @@ int uwsgi_lua_magic(char *mountpoint, char *lazy) {
return 0;
}
char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, uint16_t keylen) {
static struct lua_State *L = NULL;
if (!L) {
L = luaL_newstate();
luaL_openlibs(L);
if (luaL_loadfile(L, code) || lua_pcall(L, 0, 0, 0)) {
uwsgi_log("unable to load file %s: %s\n", code, lua_tostring(L, -1));
lua_close(L);
L = NULL;
return NULL;
}
lua_getglobal(L, func);
if (!lua_isfunction(L,-1)) {
uwsgi_log("unable to find %s function in lua file %s\n", func, code);
lua_close(L);
L = NULL;
return NULL;
}
lua_pushnil(L);
}
lua_pop(L, 1);
lua_pushvalue(L, -1);
lua_pushlstring(L, key, keylen);
#ifdef UWSGI_DEBUG
uwsgi_log("stack pos %d %.*s\n", lua_gettop(L), keylen, key);
#endif
if (lua_pcall(L, 1, 1, 0) != 0) {
uwsgi_log("CAZZO\n");
uwsgi_log("error running function `f': %s",
lua_tostring(L, -1));
return NULL;
}
if (lua_isstring(L, -1)) {
const char *ret = lua_tolstring(L, -1, NULL);
return (char *)ret;
}
return NULL;
}
int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -664,6 +732,8 @@ struct uwsgi_plugin lua_plugin = {
.init_apps = uwsgi_lua_app,
.magic = uwsgi_lua_magic,
.signal_handler = uwsgi_lua_signal_handler,
.code_string = uwsgi_lua_code_string,
.rpc = uwsgi_lua_rpc,
};
+14 -11
View File
@@ -16,7 +16,7 @@ struct option nagios_options[] = {
int nagios() {
char *tcp_port;
struct pollfd nagios_poll;
struct wsgi_request nagios_req;
// connect and send
if (!use_nagios) {
@@ -34,27 +34,30 @@ int nagios() {
tcp_port[0] = 0;
nagios_poll.fd = connect_to_tcp(uwsgi.sockets->name, atoi(tcp_port + 1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (nagios_poll.fd < 0) {
int fd = connect_to_tcp(uwsgi.sockets->name, atoi(tcp_port + 1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) {
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
exit(2);
}
uwsgi.wsgi_req->uh.modifier1 = UWSGI_MODIFIER_PING;
uwsgi.wsgi_req->uh.pktsize = 0;
uwsgi.wsgi_req->uh.modifier2 = 0;
if (write(nagios_poll.fd, uwsgi.wsgi_req, 4) != 4) {
nagios_req.uh.modifier1 = UWSGI_MODIFIER_PING;
nagios_req.uh.pktsize = 0;
nagios_req.uh.modifier2 = 0;
if (write(fd, &nagios_req.uh, 4) != 4) {
uwsgi_error("write()");
fprintf(stdout, "UWSGI CRITICAL: could not send ping packet to workers\n");
exit(2);
}
nagios_poll.events = POLLIN;
if (!uwsgi_parse_response(&nagios_poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) uwsgi.wsgi_req, uwsgi.wsgi_req->buffer, uwsgi_proto_uwsgi_parser)) {
nagios_req.poll.fd = fd;
nagios_req.poll.events = POLLIN;
if (!uwsgi_parse_packet(&nagios_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
fprintf(stdout, "UWSGI CRITICAL: timed out waiting for response\n");
exit(2);
}
else {
if (uwsgi.wsgi_req->uh.pktsize > 0) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", uwsgi.wsgi_req->uh.pktsize, uwsgi.wsgi_req->buffer);
if (nagios_req.uh.pktsize > 0) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", nagios_req.uh.pktsize, nagios_req.buffer);
exit(1);
}
else {
+18 -11
View File
@@ -15,32 +15,38 @@ struct option uwsgi_ping_options[] = {
static void ping() {
struct uwsgi_header uh;
struct pollfd uwsgi_poll;
struct wsgi_request ping_req;
char *buf = uwsgi_malloc(uwsgi.buffer_size);
// use a 3 secs timeout by default
if (!uping.ping_timeout) uping.ping_timeout = 3;
uwsgi_log("PING uwsgi host %s (timeout: %d)\n", uping.ping, uping.ping_timeout);
uwsgi_poll.fd = uwsgi_connect(uping.ping, uping.ping_timeout, 0);
if (uwsgi_poll.fd < 0) {
int fd = uwsgi_connect(uping.ping, uping.ping_timeout, 0);
if (fd < 0) {
exit(1);
}
uh.modifier1 = UWSGI_MODIFIER_PING;
uh.pktsize = 0;
uh.modifier2 = 0;
if (write(uwsgi_poll.fd, &uh, 4) != 4) {
memset(&ping_req, 0, sizeof(struct wsgi_request));
ping_req.uh.modifier1 = UWSGI_MODIFIER_PING;
ping_req.uh.pktsize = 0;
ping_req.uh.modifier2 = 0;
if (write(fd, &ping_req.uh, 4) != 4) {
uwsgi_error("write()");
exit(2);
}
uwsgi_poll.events = POLLIN;
if (!uwsgi_parse_response(&uwsgi_poll, uping.ping_timeout, &uh, NULL, uwsgi_proto_uwsgi_parser)) {
ping_req.poll.fd = fd;
ping_req.poll.events = POLLIN;
ping_req.buffer = buf;
if (!uwsgi_parse_packet(&ping_req, uping.ping_timeout)) {
exit(1);
}
else {
if (uh.pktsize > 0) {
if (ping_req.uh.pktsize > 0) {
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, ping_req.uh.pktsize, buf);
exit(2);
}
else {
@@ -92,6 +98,7 @@ int uwsgi_ping_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PING:
uwsgi.no_server = 1;
uping.ping = optarg;
return 1;
case LONG_ARGS_PING_TIMEOUT:
-490
View File
@@ -1,490 +0,0 @@
/*
uWSGI proxy
it needs one of this tecnology to work:
- epoll (linux 2.6)
- kqueue (various BSD and Darwin)
- /dev/poll (Solaris)
*/
#include "../../uwsgi.h"
#define LONG_ARGS_PROXY_WORKERS 50000
struct uwsgi_proxy {
char *socket_name;
int add_me;
int workers;
int fd;
} uproxy;
struct option proxy_options[] = {
{"proxy", required_argument, 0, LONG_ARGS_PROXY},
{"proxy-node", required_argument, 0, LONG_ARGS_PROXY_NODE},
{"proxy-max-connections", required_argument, 0, LONG_ARGS_PROXY_MAX_CONNECTIONS},
{"proxy-workers", required_argument, 0, LONG_ARGS_PROXY_WORKERS},
{0, 0, 0, 0},
};
#define UWSGI_PROXY_CONNECTING 1
#define UWSGI_PROXY_WAITING 2
extern struct uwsgi_server uwsgi;
struct uwsgi_proxy_connection {
int dest_fd;
int status;
int retry;
int node;
};
static void end_proxy(void) {
exit(UWSGI_END_CODE);
}
static void reload_proxy(void) {
exit(UWSGI_RELOAD_CODE);
}
static void uwsgi_proxy_close(struct uwsgi_proxy_connection *upcs, int fd) {
if (upcs[fd].dest_fd >= 0) {
close(upcs[fd].dest_fd);
upcs[upcs[fd].dest_fd].dest_fd = -1;
upcs[upcs[fd].dest_fd].status = 0;
upcs[upcs[fd].dest_fd].retry = 0;
if (upcs[upcs[fd].dest_fd].node > -1) {
if (uwsgi.shared->nodes[upcs[upcs[fd].dest_fd].node].connections > 0)
uwsgi.shared->nodes[upcs[upcs[fd].dest_fd].node].connections--;
}
}
if (fd >= 0) {
close(fd);
upcs[fd].dest_fd = -1;
upcs[fd].status = 0;
upcs[fd].retry = 0;
if (upcs[fd].node > -1) {
if (uwsgi.shared->nodes[upcs[fd].node].connections > 0)
uwsgi.shared->nodes[upcs[fd].node].connections--;
}
}
}
static int uwsgi_proxy_find_next_node(int current_node) {
int i;
current_node++;
if (current_node >= MAX_CLUSTER_NODES) {
current_node = 0;
}
// is it a good node ?
if (uwsgi.shared->nodes[current_node].name[0] != 0 && uwsgi.shared->nodes[current_node].status == UWSGI_NODE_OK) {
if (uwsgi.shared->nodes[current_node].connections < uwsgi.shared->nodes[current_node].workers)
return current_node;
}
// try to find a better one
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
if (uwsgi.shared->nodes[i].name[0] != 0 && uwsgi.shared->nodes[i].status == UWSGI_NODE_OK) {
if (uwsgi.shared->nodes[i].connections < uwsgi.shared->nodes[i].workers)
return i;
}
}
// ok, it is a very loaded system, fallback to round robin
if (uwsgi.shared->nodes[current_node].name[0] != 0 && uwsgi.shared->nodes[current_node].status == UWSGI_NODE_OK) {
return current_node;
}
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
if (uwsgi.shared->nodes[i].name[0] != 0 && uwsgi.shared->nodes[i].status == UWSGI_NODE_OK) {
return i;
}
}
return -1;
}
void proxy_loop() {
int efd;
#ifdef __linux__
struct epoll_event *eevents;
struct epoll_event ev;
#elif defined(__sun__)
struct pollfd *eevents;
struct pollfd ev;
#else
struct kevent *eevents;
struct kevent ev;
#endif
int max_events = 64;
int nevents, i;
const int nonblocking = 1;
const int blocking = 0;
char buffer[4096];
ssize_t rlen;
ssize_t wlen;
int max_connections = sysconf(_SC_OPEN_MAX);
int soopt;
socklen_t solen = sizeof(int);
int rc;
struct uwsgi_proxy_connection *upcs;
struct sockaddr_in upc_addr;
socklen_t upc_len = sizeof(struct sockaddr_in);
int next_node = -1;
#ifdef UWSGI_DEBUG
uwsgi_log( "allocating space for %d concurrent proxy connections\n", max_connections);
#endif
// allocate memory for connections
upcs = malloc(sizeof(struct uwsgi_proxy_connection) * max_connections);
if (!upcs) {
uwsgi_error("malloc()");
exit(1);
}
memset(upcs, 0, sizeof(struct uwsgi_proxy_connection) * max_connections);
if (uproxy.add_me) {
uwsgi_cluster_simple_add_node(uwsgi.sockets[0].name, 1, CLUSTER_NODE_STATIC);
}
efd = async_queue_init(uproxy.fd);
if (efd < 0) {
exit(1);
}
#ifdef __linux__
eevents = malloc(sizeof(struct epoll_event) * max_events);
memset(&ev, 0, sizeof(struct epoll_event));
#elif defined(__sun)
eevents = malloc(sizeof(struct pollfd) * max_events);
memset(&ev, 0, sizeof(struct pollfd));
#else
eevents = malloc(sizeof(struct kevent) * max_events);
memset(&ev, 0, sizeof(struct kevent));
#endif
if (!eevents) {
uwsgi_error("malloc()");
exit(1);
}
signal(SIGINT, (void *) &end_proxy);
signal(SIGTERM, (void *) &reload_proxy);
signal(SIGHUP, (void *) &reload_proxy);
// and welcome to the loop...
for (;;) {
nevents = async_wait(efd, eevents, max_events, -1, 0);
if (nevents < 0) {
uwsgi_error("epoll_wait()");
continue;
}
for (i = 0; i < nevents; i++) {
if ( (int)eevents[i].ASYNC_FD == uproxy.fd) {
if (eevents[i].ASYNC_IS_IN) {
// new connection, accept it
ev.ASYNC_FD = accept(uproxy.fd, (struct sockaddr *) &upc_addr, &upc_len);
if ( (int) ev.ASYNC_FD < 0) {
uwsgi_error("accept()");
continue;
}
upcs[ev.ASYNC_FD].node = -1;
// now connect to the first worker available
upcs[ev.ASYNC_FD].dest_fd = socket(AF_INET, SOCK_STREAM, 0);
if (upcs[ev.ASYNC_FD].dest_fd < 0) {
uwsgi_error("socket()");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[upcs[ev.ASYNC_FD].dest_fd].node = -1;
// set nonblocking
if (ioctl(upcs[ev.ASYNC_FD].dest_fd, FIONBIO, &nonblocking)) {
uwsgi_error("ioctl()");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[ev.ASYNC_FD].status = 0;
upcs[ev.ASYNC_FD].retry = 0;
next_node = uwsgi_proxy_find_next_node(next_node);
if (next_node == -1) {
uwsgi_log( "unable to find an available worker in the cluster !\n");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[upcs[ev.ASYNC_FD].dest_fd].node = next_node;
rc = connect(upcs[ev.ASYNC_FD].dest_fd, (struct sockaddr *) &uwsgi.shared->nodes[next_node].ucn_addr, sizeof(struct sockaddr_in));
uwsgi.shared->nodes[next_node].connections++;
if (!rc) {
// connected to worker, put it in the epoll_list
if (async_add(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[upcs[ev.ASYNC_FD].dest_fd].dest_fd = ev.ASYNC_FD;
upcs[upcs[ev.ASYNC_FD].dest_fd].status = 0;
upcs[upcs[ev.ASYNC_FD].dest_fd].retry = 0;
ev.ASYNC_FD = upcs[ev.ASYNC_FD].dest_fd;
if (async_add(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
// re-set blocking
if (ioctl(upcs[upcs[ev.ASYNC_FD].dest_fd].dest_fd, FIONBIO, &blocking)) {
uwsgi_error("ioctl()");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
else if (errno == EINPROGRESS) {
// the socket is waiting, set status to CONNECTING
upcs[ev.ASYNC_FD].status = UWSGI_PROXY_WAITING;
upcs[upcs[ev.ASYNC_FD].dest_fd].dest_fd = ev.ASYNC_FD;
upcs[upcs[ev.ASYNC_FD].dest_fd].status = UWSGI_PROXY_CONNECTING;
upcs[upcs[ev.ASYNC_FD].dest_fd].retry = 0;
ev.ASYNC_FD = upcs[ev.ASYNC_FD].dest_fd;
if (async_add(efd, ev.ASYNC_FD, ASYNC_OUT)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
else {
// connection failed, retry with the next node ?
uwsgi_error("connect()");
// close only when all node are tried
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
else {
uwsgi_log( "!!! something horrible happened to the uWSGI proxy, reloading it !!!\n");
exit(1);
}
}
else {
// this is for clients/workers
if (eevents[i].ASYNC_IS_IN) {
// is this a connected client/worker ?
//uwsgi_log("ready %d\n", upcs[eevents[i].data.fd].status);
if (!upcs[eevents[i].ASYNC_FD].status) {
if (upcs[eevents[i].ASYNC_FD].dest_fd >= 0) {
rlen = read(eevents[i].ASYNC_FD, buffer, 4096);
if (rlen < 0) {
uwsgi_error("read()");
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
else if (rlen == 0) {
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
else {
wlen = write(upcs[eevents[i].ASYNC_FD].dest_fd, buffer, rlen);
if (wlen != rlen) {
uwsgi_error("write()");
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
}
}
else {
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
}
else if (upcs[eevents[i].ASYNC_FD].status == UWSGI_PROXY_WAITING) {
// disconnected node
continue;
}
else {
uwsgi_log( "UNKNOWN STATUS %d\n", upcs[eevents[i].ASYNC_FD].status);
continue;
}
}
else if (eevents[i].ASYNC_IS_OUT) {
if (upcs[eevents[i].ASYNC_FD].status == UWSGI_PROXY_CONNECTING) {
#ifdef UWSGI_PROXY_USE_KQUEUE
if (getsockopt(eevents[i].ASYNC_FD, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
/* is something bad ? */
if (soopt) {
uwsgi_log( "connect() %s\n", strerror(soopt));
// increase errors on node
uwsgi_log( "*** marking cluster node %d/%s as failed ***\n", upcs[eevents[i].ASYNC_FD].node, uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name);
if (uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].type == CLUSTER_NODE_DYNAMIC) {
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name[0] = 0 ;
}
else {
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].errors++;
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].status = UWSGI_NODE_FAILED;
}
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
// increase errors on node
#endif
ev.ASYNC_FD = upcs[eevents[i].ASYNC_FD].dest_fd;
upcs[ev.ASYNC_FD].status = 0;
if (async_add(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
ev.ASYNC_FD = upcs[ev.ASYNC_FD].dest_fd;
upcs[ev.ASYNC_FD].status = 0;
if (async_mod(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
// re-set blocking
if (ioctl(ev.ASYNC_FD, FIONBIO, &blocking)) {
uwsgi_error("ioctl()");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
else {
uwsgi_log( "strange event for %d\n", (int) eevents[i].ASYNC_FD);
}
}
else {
if (upcs[eevents[i].ASYNC_FD].status == UWSGI_PROXY_CONNECTING) {
if (getsockopt(eevents[i].ASYNC_FD, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
}
/* is something bad ? */
if (soopt) {
uwsgi_log( "connect() %s\n", strerror(soopt));
}
// increase errors on node
uwsgi_log( "*** marking cluster node %d/%s as failed ***\n", upcs[eevents[i].ASYNC_FD].node, uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name);
if (uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].type == CLUSTER_NODE_DYNAMIC) {
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name[0] = 0;
}
else {
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].errors++;
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].status = UWSGI_NODE_FAILED;
}
}
else {
uwsgi_log( "STRANGE EVENT !!! %d %d %d\n", (int) eevents[i].ASYNC_FD, (int) eevents[i].ASYNC_EV, upcs[eevents[i].ASYNC_FD].status);
}
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
}
}
}
}
int proxy_init() {
int i;
char *tcp_port;
if (!uproxy.workers) uproxy.workers = 1 ;
if (uproxy.socket_name) {
tcp_port = strchr(uproxy.socket_name, ':');
if (tcp_port == NULL) {
uproxy.fd = bind_to_unix(uproxy.socket_name, UWSGI_LISTEN_QUEUE, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
else {
uproxy.fd = bind_to_tcp(uproxy.socket_name, UWSGI_LISTEN_QUEUE, tcp_port);
tcp_port[0] = ':';
}
if (uproxy.fd < 0) {
uwsgi_log( "unable to create the proxy server socket.\n");
exit(1);
}
for(i=0;i<uproxy.workers;i++) {
if (register_gateway("proxy", proxy_loop) == NULL) {
uwsgi_log("unable to register the proxy gateway\n");
}
}
}
return 0;
}
int proxy_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PROXY_NODE:
if (uwsgi.cluster_fd >= 0 && !strcmp(optarg, "@self")) {
uproxy.add_me = 1;
}
else {
uwsgi_cluster_simple_add_node(optarg, 1, CLUSTER_NODE_STATIC);
}
return 1;
case LONG_ARGS_PROXY:
uproxy.socket_name = optarg;
return 1;
case LONG_ARGS_PROXY_WORKERS:
uproxy.workers = atoi(optarg);
return 1;
}
return 0;
}
struct uwsgi_plugin proxy_plugin = {
.options = proxy_options,
.manage_opt = proxy_opt,
.init = proxy_init,
};
-7
View File
@@ -1,7 +0,0 @@
NAME='proxy'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['proxy']
+25
View File
@@ -3,7 +3,11 @@
extern char **environ;
extern struct uwsgi_server uwsgi;
#ifdef __APPLE__
extern struct uwsgi_perl uperl;
#else
struct uwsgi_perl uperl;
#endif
struct option uwsgi_perl_options[] = {
@@ -257,6 +261,10 @@ SV *build_psgi_env(struct wsgi_request *wsgi_req) {
if (!hv_store(env, "psgix.input.buffered", 20, newSViv(wsgi_req->body_as_file), 0)) goto clear;
if (uwsgi.master_process) {
if (!hv_store(env, "psgix.harakiri", 14, newSViv(1), 0)) goto clear;
}
SV *pe = uwsgi_perl_obj_new("uwsgi::error", 12);
if (!hv_store(env, "psgi.errors", 11, pe, 0)) goto clear;
@@ -281,6 +289,10 @@ int uwsgi_perl_init(){
uwsgi_error("setenv()");
}
if (setenv("PLACK_SERVER", "uwsgi", 0)) {
uwsgi_error("setenv()");
}
#ifdef PERL_VERSION_STRING
uwsgi_log("initializing Perl %s environment\n", PERL_VERSION_STRING);
#else
@@ -364,6 +376,7 @@ void uwsgi_perl_enable_threads() {
int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
SV **harakiri;
SV *psgi_func = uperl.psgi_main;
// ugly hack
register PerlInterpreter *my_perl = uperl.main;
@@ -426,6 +439,12 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
}
clear2:
// check for psgix.harakiri
harakiri = hv_fetch((HV*)SvRV( (SV*)wsgi_req->async_environ), "psgix.harakiri.commit", 21, 0);
if (harakiri) {
if (SvTRUE(*harakiri)) wsgi_req->async_plagued = 1;
}
SvREFCNT_dec(wsgi_req->async_environ);
SvREFCNT_dec(wsgi_req->async_result);
clear:
@@ -441,6 +460,12 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
if (wsgi_req->async_plagued) {
uwsgi_log("*** psgix.harakiri.commit requested ***\n");
goodbye_cruel_world();
}
}
void uwsgi_perl_init_thread(int core_id) {
+8 -46
View File
@@ -2,52 +2,7 @@
extern struct uwsgi_server uwsgi;
/* statistically ordered */
struct http_status_codes hsc[] = {
{"200", "OK"},
{"302", "Found"},
{"404", "Not Found"},
{"500", "Internal Server Error"},
{"301", "Moved Permanently"},
{"304", "Not Modified"},
{"303", "See Other"},
{"403", "Forbidden"},
{"307", "Temporary Redirect"},
{"401", "Unauthorized"},
{"400", "Bad Request"},
{"405", "Method Not Allowed"},
{"408", "Request Timeout"},
{"100", "Continue"},
{"101", "Switching Protocols"},
{"201", "Created"},
{"202", "Accepted"},
{"203", "Non-Authoritative Information"},
{"204", "No Content"},
{"205", "Reset Content"},
{"206", "Partial Content"},
{"300", "Multiple Choices"},
{"305", "Use Proxy"},
{"402", "Payment Required"},
{"406", "Not Acceptable"},
{"407", "Proxy Authentication Required"},
{"409", "Conflict"},
{"410", "Gone"},
{"411", "Length Required"},
{"412", "Precondition Failed"},
{"413", "Request Entity Too Large"},
{"414", "Request-URI Too Long"},
{"415", "Unsupported Media Type"},
{"416", "Requested Range Not Satisfiable"},
{"417", "Expectation Failed"},
{"501", "Not Implemented"},
{"502", "Bad Gateway"},
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{ "", NULL },
};
extern struct http_status_codes hsc[];
int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *response) {
@@ -57,6 +12,7 @@ int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *r
struct http_status_codes *http_sc;
int i,vi, base;
char *chitem;
SV **harakiri;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
@@ -84,6 +40,12 @@ int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *r
SvREFCNT_dec(closed);
}
// check for psgix.harakiri
harakiri = hv_fetch((HV*)SvRV( (SV*)wsgi_req->async_environ), "psgix.harakiri.commit", 21, 0);
if (harakiri) {
if (SvTRUE(*harakiri)) wsgi_req->async_plagued = 1;
}
SvREFCNT_dec(wsgi_req->async_environ);
SvREFCNT_dec(wsgi_req->async_result);
+1 -1
View File
@@ -66,7 +66,7 @@ XS(XS_wait_fd_write) {
}
if (fd >= 0) {
async_add_fd_read(wsgi_req, fd, timeout);
async_add_fd_write(wsgi_req, fd, timeout);
}
wsgi_req->async_force_again = 1;
+4
View File
@@ -4,15 +4,19 @@ extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
void gil_real_get() {
//uwsgi_log("LOCK %d\n", uwsgi.mywid);
#ifndef PYTHREE
PyEval_AcquireLock();
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_gil_key));
#else
PyEval_RestoreThread((PyThreadState *) pthread_getspecific(up.upt_gil_key));
#endif
//uwsgi_log("LOCKED !!! %d\n", uwsgi.mywid);
}
void gil_real_release() {
//uwsgi_log("UNLOCK %d\n", uwsgi.mywid);
#ifndef PYTHREE
pthread_setspecific(up.upt_gil_key, (void *) PyThreadState_Swap(NULL));
PyEval_ReleaseLock();
+388
View File
@@ -0,0 +1,388 @@
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern PyTypeObject uwsgi_InputType;
extern struct http_status_codes hsc[];
void *uwsgi_request_subhandler_pump(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
PyObject *zero;
int i;
PyObject *pydictkey, *pydictvalue;
char *port = memchr(wsgi_req->host, ':', wsgi_req->host_len);
if (port) {
zero = PyString_FromStringAndSize(wsgi_req->host, (port-wsgi_req->host));
PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
Py_DECREF(zero);
zero = PyString_FromStringAndSize(port, wsgi_req->host_len-((port+1)-wsgi_req->host));
PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
Py_DECREF(zero);
}
else {
zero = PyString_FromStringAndSize(wsgi_req->host, wsgi_req->host_len);
PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
Py_DECREF(zero);
zero = PyString_FromStringAndSize("80", 2);
PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
Py_DECREF(zero);
}
zero = PyString_FromStringAndSize(wsgi_req->remote_addr, wsgi_req->remote_addr_len);
PyDict_SetItemString(wsgi_req->async_environ, "remote_addr", zero);
Py_DECREF(zero);
zero = PyString_FromStringAndSize(wsgi_req->path_info, wsgi_req->path_info_len);
PyDict_SetItemString(wsgi_req->async_environ, "uri", zero);
Py_DECREF(zero);
if (wsgi_req->query_string_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->query_string, wsgi_req->query_string_len);
PyDict_SetItemString(wsgi_req->async_environ, "query_string", zero);
Py_DECREF(zero);
}
zero = PyString_FromStringAndSize(uwsgi_lower(wsgi_req->method, wsgi_req->method_len), wsgi_req->method_len);
PyDict_SetItemString(wsgi_req->async_environ, "method", zero);
Py_DECREF(zero);
if (wsgi_req->post_cl > 0) {
PyDict_SetItemString(wsgi_req->async_environ, "content_length", PyInt_FromLong(wsgi_req->post_cl));
if (wsgi_req->content_type_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->content_type, wsgi_req->content_type_len);
PyDict_SetItemString(wsgi_req->async_environ, "content_type", zero);
Py_DECREF(zero);
}
}
PyObject *headers = PyDict_New();
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
if (wsgi_req->hvec[i].iov_len < 6) continue;
if (!uwsgi_startswith(wsgi_req->hvec[i].iov_base, "HTTP_", 5)) {
(void) uwsgi_lower(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5);
#ifdef PYTHREE
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5, NULL);
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
PyObject *old_value = PyDict_GetItem(headers, pydictkey);
if (old_value) {
if (PyString_Check(old_value)) {
PyObject *new_value = PyList_New(0);
PyList_Append(new_value, old_value);
old_value = new_value;
PyDict_SetItem(headers, pydictkey, old_value);
Py_DECREF(old_value);
}
PyList_Append(old_value, pydictvalue);
}
else {
PyDict_SetItem(headers, pydictkey, pydictvalue);
}
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
}
PyDict_SetItemString(wsgi_req->async_environ, "headers", headers);
Py_DECREF(headers);
// if async_post is mapped as a file, directly use it as wsgi.input
if (wsgi_req->async_post) {
#ifdef PYTHREE
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "pump_body", "rb", 0, NULL, NULL, NULL, 0);
#else
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "pump_body", "r", NULL);
#endif
}
else {
// create wsgi.input custom object
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
}
PyDict_SetItemString(wsgi_req->async_environ, "body", wsgi_req->async_input);
if (wsgi_req->scheme_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
zero = PyString_FromString("https");
}
else {
zero = PyString_FromString("http");
}
}
else {
zero = PyString_FromString("http");
}
PyDict_SetItemString(wsgi_req->async_environ, "scheme", zero);
Py_DECREF(zero);
wsgi_req->async_app = wi->callable;
// export .env only in non-threaded mode
if (uwsgi.threads < 2) {
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
}
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
if (uwsgi.cores > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
}
// cache this ?
if (uwsgi.cluster_fd >= 0) {
zero = PyString_FromString(uwsgi.cluster);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
Py_DECREF(zero);
zero = PyString_FromString(uwsgi.hostname);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero);
Py_DECREF(zero);
}
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
// call
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
}
int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
PyObject *pychunk;
ssize_t wsize;
int i;
struct http_status_codes *http_sc;
char sc[4];
UWSGI_GET_GIL
// ok its a yield
if (!wsgi_req->async_placeholder) {
if (PyDict_Check((PyObject *)wsgi_req->async_result)) {
PyObject *status = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "status");
if (!status) {
uwsgi_log("invalid Pump response (status code).\n");
goto clear;
}
PyObject *headers = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "headers");
if (!headers) {
uwsgi_log("invalid Pump response (headers).\n");
goto clear;
}
wsgi_req->async_placeholder = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "body");
if (!wsgi_req->async_placeholder) {
uwsgi_log("invalid Pump response (body).\n");
goto clear;
}
// get the status code
if (!PyInt_Check(status)) {
uwsgi_log("invalid Pump response (status code).\n");
goto clear;
}
if (uwsgi_num2str2n(PyInt_AsLong(status), sc, 4) != 3) {
uwsgi_log("invalid Pump response (status code).\n");
goto clear;
}
int found = 0;
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
if (http_sc->key[0] == sc[0] && http_sc->key[1] == sc[1] && http_sc->key[2] == sc[2]) {
wsgi_req->hvec[4].iov_base = (char *) http_sc->message;
wsgi_req->hvec[4].iov_len = http_sc->message_size;
found = 1;
break;
}
}
if (!found) {
uwsgi_log("invalid Pump response (status code).\n");
goto clear;
}
wsgi_req->hvec[0].iov_base = wsgi_req->protocol;
wsgi_req->hvec[0].iov_len = wsgi_req->protocol_len;
wsgi_req->hvec[1].iov_base = " ";
wsgi_req->hvec[1].iov_len = 1;
wsgi_req->hvec[2].iov_base = sc;
wsgi_req->hvec[2].iov_len = 3;
wsgi_req->hvec[3].iov_base = " ";
wsgi_req->hvec[3].iov_len = 1;
wsgi_req->hvec[5].iov_base = "\r\n";
wsgi_req->hvec[5].iov_len = 2;
UWSGI_RELEASE_GIL
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6);
UWSGI_GET_GIL
if (wsize < 0) {
uwsgi_error("writev()");
}
wsgi_req->headers_size += wsize;
PyObject *hhkey, *hhvalue;
Py_ssize_t hhpos = 0;
while (PyDict_Next(headers, &hhpos, &hhkey, &hhvalue)) {
if (!PyString_Check(hhkey)) continue;
wsgi_req->hvec[0].iov_base = PyString_AsString(hhkey);
wsgi_req->hvec[0].iov_len = PyString_Size(hhkey);
((char*)wsgi_req->hvec[0].iov_base)[0] = toupper((int) ((char*)wsgi_req->hvec[0].iov_base)[0]);
wsgi_req->hvec[1].iov_base = ": ";
wsgi_req->hvec[1].iov_len = 2;
wsgi_req->hvec[3].iov_base = "\r\n";
wsgi_req->hvec[3].iov_len = 2;
if (PyList_Check(hhvalue)) {
for(i=0;i<PyList_Size(hhvalue);i++) {
PyObject *item = PyList_GetItem(hhvalue, i);
if (PyString_Check(item)) {
wsgi_req->hvec[2].iov_base = PyString_AsString(item);
wsgi_req->hvec[2].iov_len = PyString_Size(item);
UWSGI_RELEASE_GIL
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4);
UWSGI_GET_GIL
if (wsize < 0) {
uwsgi_error("writev()");
}
wsgi_req->headers_size += wsize;
}
}
}
else if (PyString_Check(hhvalue)) {
wsgi_req->hvec[2].iov_base = PyString_AsString(hhvalue);
wsgi_req->hvec[2].iov_len = PyString_Size(hhvalue);
UWSGI_RELEASE_GIL
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4);
UWSGI_GET_GIL
if (wsize < 0) {
uwsgi_error("writev()");
}
wsgi_req->headers_size += wsize;
}
}
wsgi_req->socket->proto_write(wsgi_req, "\r\n", 2);
Py_INCREF((PyObject *)wsgi_req->async_placeholder);
if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) {
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(wsgi_req->async_placeholder), PyString_Size(wsgi_req->async_placeholder))) < 0) {
uwsgi_error("write()");
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
#ifdef PYTHREE
else if ((wsgi_req->sendfile_fd = PyObject_AsFileDescriptor((PyObject *)wsgi_req->async_placeholder)) > -1) {
#else
else if (PyFile_Check((PyObject *)wsgi_req->async_placeholder)) {
wsgi_req->sendfile_fd = fileno(PyFile_AsFile((PyObject *)wsgi_req->async_placeholder));
#endif
wsize = uwsgi_sendfile(wsgi_req);
if (wsize < 0) {
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
PyObject *tmp = (PyObject *)wsgi_req->async_placeholder;
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_placeholder );
Py_DECREF(tmp);
if (!wsgi_req->async_placeholder) {
goto clear;
}
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
}
else {
uwsgi_log("invalid Pump response.\n");
goto clear;
}
#endif
}
pychunk = PyIter_Next(wsgi_req->async_placeholder);
if (!pychunk) {
if (PyErr_Occurred()) PyErr_Print();
goto clear;
}
if (PyString_Check(pychunk)) {
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
uwsgi_error("write()");
Py_DECREF(pychunk);
goto clear;
}
wsgi_req->response_size += wsize;
}
Py_DECREF(pychunk);
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
clear:
if (wsgi_req->async_input) {
Py_DECREF((PyObject *)wsgi_req->async_input);
}
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
UWSGI_RELEASE_GIL
return UWSGI_OK;
}
+65 -69
View File
@@ -22,12 +22,11 @@ PyMethodDef uwsgi_eventfd_read_method[] = { {"uwsgi_eventfd_read", py_eventfd_re
PyMethodDef uwsgi_eventfd_write_method[] = { {"uwsgi_eventfd_write", py_eventfd_write, METH_VARARGS, ""}};
#endif
int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThreadState *interpreter) {
int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThreadState *interpreter, int app_type) {
PyObject *zero;
PyObject *app_list = NULL, *applications = NULL;
int id = uwsgi.apps_cnt;
int id = uwsgi_apps_cnt;
int multiapp = 0;
#ifdef UWSGI_ASYNC
@@ -39,23 +38,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
struct uwsgi_app *wi;
if (wsgi_req->script_name_len == 0) {
wsgi_req->script_name = "";
}
else if (wsgi_req->script_name_len == 1) {
if (wsgi_req->script_name[0] == '/') {
wsgi_req->script_name = "";
wsgi_req->script_name_len = 0;
}
}
if (uwsgi.vhost && wsgi_req->host_len > 0) {
mountpoint = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|", 1, wsgi_req->script_name, wsgi_req->script_name_len);
}
else {
mountpoint = uwsgi_strncopy(wsgi_req->script_name, wsgi_req->script_name_len);
}
mountpoint = uwsgi_strncopy(wsgi_req->appid, wsgi_req->appid_len);
if (uwsgi_get_app_id(mountpoint, strlen(mountpoint), -1) != -1) {
uwsgi_log( "mountpoint %.*s already configured. skip.\n", strlen(mountpoint), mountpoint);
@@ -64,7 +47,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
wi = &uwsgi.apps[id];
wi = &uwsgi_apps[id];
memset(wi, 0, sizeof(struct uwsgi_app));
wi->mountpoint = mountpoint;
@@ -161,7 +144,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
wi->callable = up.loaders[loader](arg1);
if (!wi->callable) {
uwsgi_log("unable to load app SCRIPT_NAME=%s\n", mountpoint);
uwsgi_log("unable to load app mountpoint=%s\n", mountpoint);
goto doh;
}
@@ -185,12 +168,14 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
wi->mountpoint = PyString_AsString(app_mnt);
wi->mountpoint_len = strlen(wi->mountpoint);
wsgi_req->script_name = wi->mountpoint;
wsgi_req->script_name_len = wi->mountpoint_len;
wsgi_req->appid = wi->mountpoint;
wsgi_req->appid_len = wi->mountpoint_len;
uwsgi_log("main mountpoint = %s\n", wi->mountpoint);
wi->callable = PyDict_GetItem(applications, app_mnt);
}
Py_INCREF((PyObject *)wi->callable);
#ifdef UWSGI_ASYNC
wi->environ = malloc(sizeof(PyObject*)*uwsgi.cores);
if (!wi->environ) {
@@ -213,47 +198,29 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
#endif
// check function args
// by defaut it is a WSGI app
wi->argc = 2;
zero = PyObject_GetAttrString(wi->callable, "__code__");
if (!zero) {
zero = PyObject_GetAttrString(wi->callable, "__call__");
if (zero) {
zero = PyObject_GetAttrString(wi->callable, "__code__");
}
else {
uwsgi_log("WARNING: unable to get the number of callable args. Fallback to WSGI\n");
}
}
wi->argc = 1;
// avoid __code__ attr error propagation
PyErr_Clear();
if (zero) {
zero = PyObject_GetAttrString(zero, "co_argcount");
wi->argc = (int) PyInt_AsLong(zero);
}
if (wi->argc == 2) {
if (app_type == PYTHON_APP_TYPE_WSGI) {
#ifdef UWSGI_DEBUG
uwsgi_log("-- WSGI callable detected --\n");
uwsgi_log("-- WSGI callable selected --\n");
#endif
wi->request_subhandler = uwsgi_request_subhandler_wsgi;
wi->response_subhandler = uwsgi_response_subhandler_wsgi;
wi->argc = 2;
}
#ifdef UWSGI_WEB3
else if (wi->argc == 1) {
else if (app_type == PYTHON_APP_TYPE_WEB3) {
#ifdef UWSGI_DEBUG
uwsgi_log("-- Web3 callable detected --\n");
uwsgi_log("-- Web3 callable selected --\n");
#endif
wi->request_subhandler = uwsgi_request_subhandler_web3;
wi->response_subhandler = uwsgi_response_subhandler_web3;
}
else if (app_type == PYTHON_APP_TYPE_PUMP) {
#ifdef UWSGI_DEBUG
uwsgi_log("-- Pump callable selected --\n");
#endif
else {
uwsgi_log("-- INVALID callable detected --\n");
goto doh;
wi->request_subhandler = uwsgi_request_subhandler_pump;
wi->response_subhandler = uwsgi_response_subhandler_pump;
}
#ifdef UWSGI_ASYNC
@@ -271,7 +238,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
// add start_response on WSGI app
if (wi->argc == 2) {
Py_INCREF((PyObject *)up.wsgi_spitout);
if (app_type == PYTHON_APP_TYPE_WSGI) {
if (PyTuple_SetItem(wi->args[i], 1, up.wsgi_spitout)) {
uwsgi_log("unable to set start_response in args tuple\n");
exit(1);
@@ -281,7 +249,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
#else
wi->wsgi_args = PyTuple_New(wi->argc);
if (wi->argc == 2) {
if (app_type == PYTHON_APP_TYPE_WSGI) {
if (PyTuple_SetItem(wi->wsgi_args, 1, up.wsgi_spitout)) {
uwsgi_log("unable to set start_response in args tuple\n");
exit(1);
@@ -289,7 +257,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
#endif
if (wi->argc == 2) {
if (app_type == PYTHON_APP_TYPE_WSGI) {
#ifdef UWSGI_SENDFILE
// prepare sendfile() for WSGI app
wi->sendfile = PyCFunction_New(uwsgi_sendfile_method, NULL);
@@ -301,9 +269,23 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
#endif
}
// cache most used values
wi->gateway_version = PyTuple_New(2);
PyTuple_SetItem(wi->gateway_version, 0, PyInt_FromLong(1));
PyTuple_SetItem(wi->gateway_version, 1, PyInt_FromLong(0));
Py_INCREF((PyObject *)wi->gateway_version);
wi->uwsgi_version = PyString_FromString(UWSGI_VERSION);
Py_INCREF((PyObject *)wi->uwsgi_version);
wi->uwsgi_node = PyString_FromString(uwsgi.hostname);
Py_INCREF((PyObject *)wi->uwsgi_node);
if (uwsgi.threads > 1 && id) {
// if we have multiple threads we need to initialize a PyThreadState for each one
for(i=0;i<uwsgi.threads;i++) {
//uwsgi_log("%p\n", uwsgi.core[i]->ts[id]);
uwsgi.core[i]->ts[id] = PyThreadState_New( ((PyThreadState *)wi->interpreter)->interp);
if (!uwsgi.core[i]->ts[id]) {
uwsgi_log("unable to allocate new PyThreadState structure for app %s", mountpoint);
@@ -316,19 +298,22 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
PyThreadState_Swap(up.main_thread);
}
if (wi->argc == 1) {
uwsgi_log( "Web3 application %d (SCRIPT_NAME=%.*s) ready on interpreter %p", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter);
if (app_type == PYTHON_APP_TYPE_WSGI) {
uwsgi_log( "WSGI application %d (mountpoint=%.*s) ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
else {
uwsgi_log( "WSGI application %d (SCRIPT_NAME=%.*s) ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
else if (app_type == PYTHON_APP_TYPE_WEB3) {
uwsgi_log( "Web3 application %d (mountpoint=%.*s) ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
else if (app_type == PYTHON_APP_TYPE_PUMP) {
uwsgi_log( "Pump application %d (mountpoint=%.*s) ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
if (!wsgi_req->script_name_len) {
if (!wsgi_req->appid_len) {
uwsgi_rawlog(" (default app)");
uwsgi.default_app = id;
}
uwsgi.apps_cnt++;
uwsgi_apps_cnt++;
uwsgi_rawlog("\n");
@@ -340,9 +325,17 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
continue;
}
wsgi_req->script_name = PyString_AsString(app_mnt);
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
init_uwsgi_app(LOADER_CALLABLE, PyDict_GetItem(applications, app_mnt), wsgi_req, wi->interpreter);
wsgi_req->appid = PyString_AsString(app_mnt);
wsgi_req->appid_len = strlen(wsgi_req->appid);
init_uwsgi_app(LOADER_CALLABLE, PyDict_GetItem(applications, app_mnt), wsgi_req, wi->interpreter, app_type);
}
}
// check if we need to emulate fork() COW
if (uwsgi.mywid == 0) {
for(i=1;i<=uwsgi.numproc;i++) {
memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
}
}
@@ -439,9 +432,9 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
if (quick_callable[strlen(quick_callable) -2 ] == '(' && quick_callable[strlen(quick_callable) -1] ==')') {
quick_callable[strlen(quick_callable) -2 ] = 0;
tmp_callable = PyDict_GetItemString(wsgi_dict, quick_callable);
quick_callable[strlen(quick_callable) -2 ] = '(';
quick_callable[strlen(quick_callable)] = '(';
if (tmp_callable) {
return python_call(tmp_callable, PyTuple_New(0), 0);
return python_call(tmp_callable, PyTuple_New(0), 0, NULL);
}
}
@@ -523,8 +516,11 @@ PyObject *uwsgi_file_loader(void *arg1) {
char *callable = up.callable;
if (!callable) callable = "application";
wsgi_file_module = uwsgi_pyimport_by_filename("uwsgi_wsgi_file", filename);
// no need to check here for module import as it is already done by uwsgi_pyimport_by_file
wsgi_file_module = uwsgi_pyimport_by_filename(uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename)), filename);
if (!wsgi_file_module) {
PyErr_Print();
exit(1);
}
wsgi_file_dict = PyModule_GetDict(wsgi_file_module);
if (!wsgi_file_dict) {
+371 -85
View File
@@ -3,6 +3,8 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_python up;
extern struct http_status_codes hsc[];
#include <glob.h>
extern PyTypeObject uwsgi_InputType;
@@ -12,6 +14,7 @@ struct option uwsgi_python_options[] = {
{"file", required_argument, 0, LONG_ARGS_FILE_CONFIG},
{"eval", required_argument, 0, LONG_ARGS_EVAL_CONFIG},
{"module", required_argument, 0, 'w'},
{"wsgi", required_argument, 0, 'w'},
{"callable", required_argument, 0, LONG_ARGS_CALLABLE},
{"test", required_argument, 0, 'j'},
{"home", required_argument, 0, 'H'},
@@ -21,10 +24,22 @@ struct option uwsgi_python_options[] = {
{"pythonpath", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"python-path", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"pymodule-alias", required_argument, 0, LONG_ARGS_PYMODULE_ALIAS},
{"post-pymodule-alias", required_argument, 0, LONG_ARGS_POST_PYMODULE_ALIAS},
{"import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"pyimport", required_argument, 0, LONG_ARGS_PYIMPORT},
{"py-import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"python-import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"spooler-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-pyimport", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-py-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-python-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"pp", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"pyargv", required_argument, 0, LONG_ARGS_PYARGV},
{"optimize", required_argument, 0, 'O'},
{"paste", required_argument, 0, LONG_ARGS_PASTE},
{"web3", required_argument, 0, LONG_ARGS_WEB3},
{"pump", required_argument, 0, LONG_ARGS_PUMP},
{"wsgi-lite", required_argument, 0, LONG_ARGS_WSGI_LITE},
#ifdef UWSGI_INI
{"ini-paste", required_argument, 0, LONG_ARGS_INI_PASTE},
#endif
@@ -33,6 +48,7 @@ struct option uwsgi_python_options[] = {
{"pep3333-input", no_argument, &up.pep3333_input, 1},
{"reload-os-env", no_argument, &up.reload_os_env, 1},
{"no-site", no_argument, &Py_NoSiteFlag, 1},
{"pyshell", no_argument, 0, LONG_ARGS_PYSHELL},
{0, 0, 0, 0},
};
@@ -89,14 +105,15 @@ int uwsgi_python_init() {
if (up.home != NULL) {
#ifdef PYTHREE
wchar_t *wpyhome;
wpyhome = malloc((sizeof(wchar_t) * strlen(up.home)) + 2);
wpyhome = malloc((sizeof(wchar_t) * strlen(up.home)) + sizeof(wchar_t) );
if (!wpyhome) {
uwsgi_error("malloc()");
exit(1);
}
mbstowcs(wpyhome, up.home, strlen(up.home));
Py_SetPythonHome(wpyhome);
free(wpyhome);
// do not free this memory !!!
//free(wpyhome);
#else
Py_SetPythonHome(up.home);
#endif
@@ -136,27 +153,40 @@ int uwsgi_python_init() {
}
void uwsgi_python_post_fork() {
void uwsgi_python_reset_random_seed() {
PyObject *random_module, *random_dict, *random_seed;
// reinitialize the random seed (thanks Jonas Borgström)
random_module = PyImport_ImportModule("random");
if (random_module) {
random_dict = PyModule_GetDict(random_module);
if (random_dict) {
random_seed = PyDict_GetItemString(random_dict, "seed");
if (random_seed) {
PyObject *random_args = PyTuple_New(1);
// pass no args
PyTuple_SetItem(random_args, 0, Py_None);
PyEval_CallObject(random_seed, random_args);
if (PyErr_Occurred()) {
PyErr_Print();
}
}
// reinitialize the random seed (thanks Jonas Borgström)
random_module = PyImport_ImportModule("random");
if (random_module) {
random_dict = PyModule_GetDict(random_module);
if (random_dict) {
random_seed = PyDict_GetItemString(random_dict, "seed");
if (random_seed) {
PyObject *random_args = PyTuple_New(1);
// pass no args
PyTuple_SetItem(random_args, 0, Py_None);
PyEval_CallObject(random_seed, random_args);
if (PyErr_Occurred()) {
PyErr_Print();
}
}
}
}
}
void uwsgi_python_post_fork() {
#ifdef UWSGI_SPOOLER
if (uwsgi.shared->spooler_pid > 0) {
if (uwsgi.shared->spooler_pid == getpid()) {
UWSGI_GET_GIL
}
}
}
#endif
uwsgi_python_reset_random_seed();
#ifdef UWSGI_EMBEDDED
// call the post_fork_hook
@@ -164,7 +194,7 @@ void uwsgi_python_post_fork() {
if (uwsgi_dict) {
PyObject *pfh = PyDict_GetItemString(uwsgi_dict, "post_fork_hook");
if (pfh) {
python_call(pfh, PyTuple_New(0), 0);
python_call(pfh, PyTuple_New(0), 0, NULL);
}
}
PyErr_Clear();
@@ -184,17 +214,17 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
char *real_filename = filename;
if (strncmp(filename, "http://", 7)) {
if (strncmp(filename, "http://", 7) && strncmp(filename, "sym://", 6) && strncmp(filename, "data://", 7)) {
pyfile = fopen(filename, "r");
if (!pyfile) {
uwsgi_log("failed to open python file %s\n", filename);
exit(1);
return NULL;
}
if (fstat(fileno(pyfile), &pystat)) {
uwsgi_error("fstat()");
exit(1);
return NULL;
}
if (S_ISDIR(pystat.st_mode)) {
@@ -204,7 +234,9 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
pyfile = fopen(real_filename, "r");
if (!pyfile) {
uwsgi_error_open(real_filename);
exit(1);
free(real_filename);
fclose(pyfile);
return NULL;
}
}
@@ -212,7 +244,10 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
if (!py_file_node) {
PyErr_Print();
uwsgi_log("failed to parse file %s\n", real_filename);
exit(1);
if (is_a_package)
free(real_filename);
fclose(pyfile);
return NULL;
}
fclose(pyfile);
@@ -226,7 +261,7 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
if (!py_file_node) {
PyErr_Print();
uwsgi_log("failed to parse url %s\n", real_filename);
exit(1);
return NULL;
}
}
}
@@ -236,13 +271,13 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
if (!py_compiled_node) {
PyErr_Print();
uwsgi_log("failed to compile python file %s\n", real_filename);
exit(1);
return NULL;
}
py_file_module = PyImport_ExecCodeModule(name, py_compiled_node);
if (!py_file_module) {
PyErr_Print();
exit(1);
return NULL;
}
Py_DECREF(py_compiled_node);
@@ -365,6 +400,10 @@ void init_uwsgi_vars() {
else {
// this is a filepath that need to be mapped
tmp_module = uwsgi_pyimport_by_filename(up.pymodule_alias[i], value + 1);
if (!tmp_module) {
PyErr_Print();
exit(1);
}
}
uwsgi_log("mapped virtual pymodule \"%s\" to real pymodule \"%s\"\n", up.pymodule_alias[i], value + 1);
// reset original value
@@ -423,6 +462,9 @@ void init_uwsgi_embedded_module() {
exit(1);
}
// just for safety
Py_INCREF(up.embedded_dict);
if (PyDict_SetItemString(up.embedded_dict, "version", PyString_FromString(UWSGI_VERSION))) {
PyErr_Print();
exit(1);
@@ -482,6 +524,11 @@ void init_uwsgi_embedded_module() {
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "has_threads", PyInt_FromLong(uwsgi.has_threads))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "cores", PyInt_FromLong(uwsgi.cores))) {
PyErr_Print();
exit(1);
@@ -494,39 +541,6 @@ void init_uwsgi_embedded_module() {
}
}
if (PyDict_SetItemString(up.embedded_dict, "KIND_NULL", PyInt_FromLong(KIND_NULL))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "KIND_WORKER", PyInt_FromLong(KIND_WORKER))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "KIND_EVENT", PyInt_FromLong(KIND_EVENT))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "KIND_SPOOLER", PyInt_FromLong(KIND_SPOOLER))) {
PyErr_Print();
exit(1);
}
/*
if (PyDict_SetItemString(up.embedded_dict, "KIND_ERLANG", PyInt_FromLong(KIND_ERLANG))) {
PyErr_Print();
exit(1);
}
*/
if (PyDict_SetItemString(up.embedded_dict, "KIND_PROXY", PyInt_FromLong(KIND_PROXY))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "KIND_MASTER", PyInt_FromLong(KIND_MASTER))) {
PyErr_Print();
exit(1);
}
PyObject *py_opt_dict = PyDict_New();
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (PyDict_Contains(py_opt_dict, PyString_FromString(uwsgi.exported_opts[i]->key))) {
@@ -706,6 +720,20 @@ int uwsgi_python_manage_options(int i, char *optarg) {
uwsgi_log("you can specify at most %d --pymodule-alias options\n", MAX_PYMODULE_ALIAS);
}
return 1;
case LONG_ARGS_PYSHELL:
uwsgi.honour_stdin = 1;
up.pyshell = 1;
uwsgi.to_hell = 1;
return 1;
case LONG_ARGS_PYIMPORT:
uwsgi_string_new_list(&up.import_list, optarg);
return 1;
case LONG_ARGS_SPOOLER_PYIMPORT:
uwsgi_string_new_list(&up.spooler_import_list, optarg);
return 1;
case LONG_ARGS_POST_PYMODULE_ALIAS:
uwsgi_string_new_list(&up.post_pymodule_alias, optarg);
return 1;
case LONG_ARGS_PYTHONPATH:
if (glob(optarg, GLOB_MARK, NULL, &g)) {
uwsgi_string_new_list(&up.python_path, optarg);
@@ -744,6 +772,15 @@ int uwsgi_python_manage_options(int i, char *optarg) {
}
return 1;
#endif
case LONG_ARGS_WEB3:
up.web3 = optarg;
return 1;
case LONG_ARGS_PUMP:
up.pump = optarg;
return 1;
case LONG_ARGS_WSGI_LITE:
up.wsgi_lite = optarg;
return 1;
case LONG_ARGS_PASTE:
up.paste = optarg;
return 1;
@@ -757,27 +794,96 @@ int uwsgi_python_manage_options(int i, char *optarg) {
int uwsgi_python_mount_app(char *mountpoint, char *app) {
uwsgi.wsgi_req->script_name = mountpoint;
uwsgi.wsgi_req->script_name_len = strlen(mountpoint);
uwsgi.wsgi_req->appid = mountpoint;
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
if (uwsgi.single_interpreter) {
return init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread);
return init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
return init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL);
return init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
}
char *uwsgi_pythonize(char *orig) {
char *name = uwsgi_concat2(orig, "");
size_t i;
size_t len = 0;
if (!strncmp(name, "sym://", 6)) {
name+=6;
}
else if (!strncmp(name, "http://", 7)) {
name+=7;
}
else if (!strncmp(name, "data://", 7)) {
name+=7;
}
len = strlen(name);
for(i=0;i<len;i++) {
if (name[i] == '.') {
name[i] = '_';
}
else if (name[i] == '/') {
name[i] = '.';
}
}
if ((name[len-3] == '.' || name[len-3] == '_') && name[len-2] == 'p' && name[len-1] == 'y') {
name[len-3] = 0;
}
return name;
}
void uwsgi_python_spooler_init(void) {
struct uwsgi_string_list *upli = up.spooler_import_list;
UWSGI_GET_GIL
while(upli) {
if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) {
uwsgi_pyimport_by_filename(uwsgi_pythonize(upli->value), upli->value);
}
else {
if (PyImport_ImportModule(upli->value) == NULL) {
PyErr_Print();
}
}
upli = upli->next;
}
UWSGI_RELEASE_GIL
}
void uwsgi_python_init_apps() {
struct http_status_codes *http_sc;
if (uwsgi.async > 1) {
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
}
init_pyargv();
#ifdef UWSGI_MINTERPRETERS
init_uwsgi_embedded_module();
#endif
#ifdef __linux__
#ifndef PYTHREE
uwsgi_init_symbol_import();
#endif
#endif
if (up.test_module != NULL) {
if (PyImport_ImportModule(up.test_module)) {
exit(0);
@@ -800,18 +906,81 @@ void uwsgi_python_init_apps() {
up.loaders[LOADER_STRING_CALLABLE] = uwsgi_string_callable_loader;
struct uwsgi_string_list *upli = up.import_list;
while(upli) {
if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) {
uwsgi_pyimport_by_filename(uwsgi_pythonize(upli->value), upli->value);
}
else {
if (PyImport_ImportModule(upli->value) == NULL) {
PyErr_Print();
}
}
upli = upli->next;
}
struct uwsgi_string_list *uppa = up.post_pymodule_alias;
PyObject *modules = PyImport_GetModuleDict();
PyObject *tmp_module;
while(uppa) {
// split key=value
char *value = strchr(uppa->value, '=');
if (!value) {
uwsgi_log("invalid pymodule-alias syntax\n");
continue;
}
value[0] = 0;
if (!strchr(value + 1, '/')) {
// this is a standard pymodule
tmp_module = PyImport_ImportModule(value + 1);
if (!tmp_module) {
PyErr_Print();
exit(1);
}
PyDict_SetItemString(modules, uppa->value, tmp_module);
}
else {
// this is a filepath that need to be mapped
tmp_module = uwsgi_pyimport_by_filename(uppa->value, value + 1);
if (!tmp_module) {
PyErr_Print();
exit(1);
}
}
uwsgi_log("mapped virtual pymodule \"%s\" to real pymodule \"%s\"\n", uppa->value, value + 1);
// reset original value
value[0] = '=';
uppa = uppa->next;
}
if (up.wsgi_config != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread);
init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.file_config != NULL) {
init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, up.main_thread);
init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.paste != NULL) {
init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, up.main_thread);
init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.eval != NULL) {
init_uwsgi_app(LOADER_EVAL, up.eval, uwsgi.wsgi_req, up.main_thread);
init_uwsgi_app(LOADER_EVAL, up.eval, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.web3 != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.web3, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WEB3);
}
if (up.pump != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.pump, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_PUMP);
// filling http status codes
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = (int) strlen(http_sc->message);
}
}
if (up.wsgi_lite != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.wsgi_lite, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI_LITE);
}
if (uwsgi.profiler) {
@@ -822,6 +991,29 @@ void uwsgi_python_init_apps() {
}
void uwsgi_python_master_fixup(int step) {
static int master_fixed = 0;
static int worker_fixed = 0;
if (!uwsgi.master_process) return;
if (uwsgi.has_threads) {
if (step == 0) {
if (!master_fixed) {
UWSGI_RELEASE_GIL;
master_fixed = 1;
}
}
else {
if (!worker_fixed) {
UWSGI_GET_GIL;
worker_fixed = 1;
}
}
}
}
void uwsgi_python_enable_threads() {
PyEval_InitThreads();
@@ -841,9 +1033,12 @@ void uwsgi_python_enable_threads() {
up.gil_get = gil_real_get;
up.gil_release = gil_real_release;
up.swap_ts = threaded_swap_ts;
up.reset_ts = threaded_reset_ts;
if (uwsgi.threads > 1) {
up.swap_ts = threaded_swap_ts;
up.reset_ts = threaded_reset_ts;
}
uwsgi_log("threads support enabled\n");
}
void uwsgi_python_init_thread(int core_id) {
@@ -865,16 +1060,16 @@ int uwsgi_python_xml(char *node, char *content) {
}
if (!strcmp("script", node)) {
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("file", node)) {
return init_uwsgi_app(LOADER_FILE, content, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_FILE, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("eval", node)) {
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("wsgi", node)) {
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("module", node)) {
uwsgi.wsgi_req->module = content;
@@ -885,10 +1080,10 @@ int uwsgi_python_xml(char *node, char *content) {
uwsgi.wsgi_req->callable++;
uwsgi.wsgi_req->callable_len = strlen(uwsgi.wsgi_req->callable);
uwsgi.wsgi_req->module_len = strlen(uwsgi.wsgi_req->module);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else {
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
return 1;
}
@@ -900,7 +1095,7 @@ int uwsgi_python_xml(char *node, char *content) {
else if (!strcmp("callable", node)) {
uwsgi.wsgi_req->callable = content;
uwsgi.wsgi_req->callable_len = strlen(content);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
return 0;
@@ -921,6 +1116,56 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
}
char *uwsgi_python_code_string(char *id, char *code, char *function, char *key, uint16_t keylen) {
PyObject *cs_module = NULL;
PyObject *cs_dict = NULL;
UWSGI_GET_GIL;
cs_module = PyImport_ImportModule(id);
if (!cs_module) {
PyErr_Clear();
cs_module = uwsgi_pyimport_by_filename(id, code);
}
if (!cs_module) {
UWSGI_RELEASE_GIL;
return NULL;
}
cs_dict = PyModule_GetDict(cs_module);
if (!cs_dict) {
PyErr_Print();
UWSGI_RELEASE_GIL;
return NULL;
}
PyObject *func = PyDict_GetItemString(cs_dict, function);
if (!func) {
uwsgi_log("function %s not available in %s\n", function, code);
PyErr_Print();
UWSGI_RELEASE_GIL;
return NULL;
}
PyObject *args = PyTuple_New(1);
PyTuple_SetItem(args, 0, PyString_FromStringAndSize(key, keylen));
PyObject *ret = python_call(func, args, 0, NULL);
Py_DECREF(args);
if (ret && PyString_Check(ret)) {
char *val = PyString_AsString(ret);
UWSGI_RELEASE_GIL;
return val;
}
UWSGI_RELEASE_GIL;
return NULL;
}
int uwsgi_python_signal_handler(uint8_t sig, void *handler) {
UWSGI_GET_GIL;
@@ -936,8 +1181,8 @@ int uwsgi_python_signal_handler(uint8_t sig, void *handler) {
PyTuple_SetItem(args, 0, PyInt_FromLong(sig));
ret = python_call(handler, args, 0);
ret = python_call(handler, args, 0, NULL);
Py_DECREF(args);
if (ret) {
UWSGI_RELEASE_GIL;
return 0;
@@ -963,7 +1208,7 @@ uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
PyTuple_SetItem(pyargs, i, PyString_FromString(argv[i]));
}
ret = python_call((PyObject *) func, pyargs, 0);
ret = python_call((PyObject *) func, pyargs, 0, NULL);
if (ret) {
if (PyString_Check(ret)) {
@@ -992,44 +1237,68 @@ void uwsgi_python_add_item(char *key, uint16_t keylen, char *val, uint16_t valle
PyDict_SetItem(pydict, PyString_FromStringAndSize(key, keylen), PyString_FromStringAndSize(val, vallen));
}
int uwsgi_python_spooler(char *buf, uint16_t len) {
int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, size_t body_len) {
static int random_seed_reset = 0;
UWSGI_GET_GIL;
PyObject *spool_dict = PyDict_New();
PyObject *spool_func, *pyargs, *ret;
if (!random_seed_reset) {
uwsgi_python_reset_random_seed();
random_seed_reset = 1;
}
if (!up.embedded_dict) {
// ignore
UWSGI_RELEASE_GIL;
return 0;
}
spool_func = PyDict_GetItemString(up.embedded_dict, "spooler");
if (!spool_func) {
// ignore
UWSGI_RELEASE_GIL;
return 0;
}
if (uwsgi_hooked_parse(buf, len, uwsgi_python_add_item, spool_dict)) {
// malformed packet, destroy it
UWSGI_RELEASE_GIL;
return -2;
}
pyargs = PyTuple_New(1);
PyDict_SetItemString(spool_dict, "spooler_task_name", PyString_FromString(filename));
if (body && body_len > 0) {
PyDict_SetItemString(spool_dict, "body", PyString_FromStringAndSize(body, body_len));
}
PyTuple_SetItem(pyargs, 0, spool_dict);
ret = python_call(spool_func, pyargs, 0);
ret = python_call(spool_func, pyargs, 0, NULL);
if (ret) {
if (!PyInt_Check(ret)) {
// error, retry
UWSGI_RELEASE_GIL;
return -1;
}
return PyInt_AsLong(ret);
int retval = (int) PyInt_AsLong(ret);
UWSGI_RELEASE_GIL;
return retval;
}
if (PyErr_Occurred())
PyErr_Print();
// error, retry
UWSGI_RELEASE_GIL;
return -1;
}
@@ -1053,6 +1322,17 @@ void uwsgi_python_fixup() {
uwsgi.p[30] = uwsgi.p[0];
}
void uwsgi_python_hijack(void) {
// the pyshell will be execute only in the first worker
if (up.pyshell && uwsgi.mywid == 1) {
UWSGI_GET_GIL;
PyImport_ImportModule("readline");
PyRun_InteractiveLoop(stdin, "uwsgi");
exit(0);
}
}
struct uwsgi_plugin python_plugin = {
.name = "python",
@@ -1068,6 +1348,7 @@ struct uwsgi_plugin python_plugin = {
.init_apps = uwsgi_python_init_apps,
.fixup = uwsgi_python_fixup,
.master_fixup = uwsgi_python_master_fixup,
.mount_app = uwsgi_python_mount_app,
@@ -1080,11 +1361,16 @@ struct uwsgi_plugin python_plugin = {
.suspend = uwsgi_python_suspend,
.resume = uwsgi_python_resume,
.hijack_worker = uwsgi_python_hijack,
.spooler_init = uwsgi_python_spooler_init,
.signal_handler = uwsgi_python_signal_handler,
.rpc = uwsgi_python_rpc,
.spooler = uwsgi_python_spooler,
.code_string = uwsgi_python_code_string,
.help = uwsgi_python_help,
};
+13 -3
View File
@@ -8,17 +8,27 @@ int manage_python_response(struct wsgi_request *wsgi_req) {
return uwsgi_response_subhandler_wsgi(wsgi_req);
}
PyObject *python_call(PyObject *callable, PyObject *args, int catch) {
PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi_request *wsgi_req) {
PyObject *pyret;
//uwsgi_log("ready to call %p %p\n", callable, args);
pyret = PyEval_CallObject(callable, args);
//uwsgi_log("called\n");
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
uwsgi_log("Memory Error detected !!!\n");
}
uwsgi.workers[uwsgi.mywid].exceptions++;
// this can be in a spooler or in the master
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].exceptions++;
if (wsgi_req) {
uwsgi_apps[wsgi_req->app_id].exceptions++;
}
}
if (!catch) {
PyErr_Print();
}
@@ -35,7 +45,7 @@ PyObject *python_call(PyObject *callable, PyObject *args, int catch) {
int uwsgi_python_call(struct wsgi_request *wsgi_req, PyObject *callable, PyObject *args) {
wsgi_req->async_result = python_call(callable, args, 0);
wsgi_req->async_result = python_call(callable, args, 0, wsgi_req);
if (wsgi_req->async_result) {
while ( manage_python_response(wsgi_req) != UWSGI_OK) {
+746
View File
@@ -0,0 +1,746 @@
#include "uwsgi_python.h"
#ifndef PYTHREE
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
struct _symimporter {
PyObject_HEAD;
} uwsgi_symbol_importer_object;
struct _symzipimporter {
PyObject_HEAD;
char *prefix;
PyObject *zip;
PyObject *items;
} uwsgi_symbol_zip_importer_object;
static char *symbolize(char *name) {
char *base = uwsgi_concat2(name, "");
char *ptr = base;
while(*ptr != 0) {
if (*ptr == '.') {
*ptr = '_';
}
ptr++;
}
return base;
}
static char *name_to_py(char *prefix, char *name) {
char *base;
char *ptr;
if (prefix) {
if (prefix[strlen(prefix)-1] == '/') {
base = uwsgi_concat3(prefix, name, ".py");
ptr = base + strlen(prefix);
}
else {
base = uwsgi_concat4(prefix, "/", name, ".py");
ptr = base + strlen(prefix) + 1;
}
}
else {
base = uwsgi_concat2(name, ".py");
ptr = base;
}
while(*ptr != 0) {
if (*ptr == '.') {
*ptr = '/';
}
ptr++;
}
// fix .py
ptr-=3;
*ptr = '.';
return base;
}
static char *name_to_init_py(char *prefix, char *name) {
char *base;
char *ptr;
if (prefix) {
if (prefix[strlen(prefix)-1] == '/') {
base = uwsgi_concat3(prefix, name, "/__init__.py");
ptr = base + strlen(prefix);
}
else {
base = uwsgi_concat4(prefix, "/", name, "/__init__.py");
ptr = base + strlen(prefix) + 1;
}
}
else {
base = uwsgi_concat2(name, "/__init__.py");
ptr = base;
}
while(*ptr != 0) {
if (*ptr == '.') {
*ptr = '/';
}
ptr++;
}
// fix .py
ptr-=3;
*ptr = '.';
return base;
}
static char *name_to_symbol(char *name, char *what) {
char *symbol = uwsgi_concat4("_binary_", name, "_", what);
char *sym_ptr_start = dlsym(RTLD_DEFAULT, symbol);
free(symbol);
return sym_ptr_start;
}
static char *name_to_symbol_module(char *name, char *what) {
char *symbol = uwsgi_concat4("_binary_", name, "_py_", what);
char *sym_ptr_start = dlsym(RTLD_DEFAULT, symbol);
free(symbol);
return sym_ptr_start;
}
static char *name_to_symbol_pkg(char *name, char *what) {
char *symbol = uwsgi_concat4("_binary_", name, "___init___py_", what);
char *sym_ptr_start = dlsym(RTLD_DEFAULT, symbol);
free(symbol);
return sym_ptr_start;
}
int py_list_has_string(PyObject *obj, char *name) {
Py_ssize_t i, len = PyList_Size(obj);
int found = 0;
for(i=0;i<len;i++) {
PyObject *current = PyList_GetItem(obj, i);
char *filename = PyString_AsString(current);
if (!strcmp(filename, name)) {
found = 1;
break;
}
}
return found;
}
static PyObject* symzipimporter_find_module(PyObject *self, PyObject *args) {
char *fullname;
PyObject *path = NULL;
struct _symzipimporter *this = (struct _symzipimporter *) self;
if (!PyArg_ParseTuple(args, "s|O:find_module", &fullname, &path)) {
return NULL;
}
char *filename = name_to_py(this->prefix, fullname);
if (py_list_has_string(this->items, filename)) {
free(filename);
return self;
}
PyErr_Clear();
free(filename);
filename = name_to_init_py(this->prefix, fullname);
if (py_list_has_string(this->items, filename)) {
free(filename);
return self;
}
PyErr_Clear();
free(filename);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* symzipimporter_load_module(PyObject *self, PyObject *args) {
char *fullname;
char *modname;
struct _symzipimporter *this = (struct _symzipimporter *) self;
if (!PyArg_ParseTuple(args, "s:load_module", &fullname)) {
return NULL;
}
char *filename = name_to_py(this->prefix, fullname);
if (py_list_has_string(this->items, filename)) {
PyObject *mod = PyImport_AddModule(fullname);
if (!mod) goto clear;
PyObject *dict = PyModule_GetDict(mod);
if (!dict) goto clear;
PyDict_SetItemString(dict, "__loader__", self);
modname = uwsgi_concat2("symzip://", fullname);
PyObject *source = PyObject_CallMethod(this->zip, "read", "(s)", filename);
free(filename);
PyObject *code = Py_CompileString(PyString_AsString(source), modname, Py_file_input);
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
Py_DECREF(code);
Py_DECREF(source);
free(modname);
return mod;
}
PyErr_Clear();
free(filename);
filename = name_to_init_py(this->prefix, fullname);
if (py_list_has_string(this->items, filename)) {
PyObject *mod = PyImport_AddModule(fullname);
if (!mod) goto clear;
PyObject *dict = PyModule_GetDict(mod);
if (!dict) goto clear;
modname = uwsgi_concat2("symzip://", fullname);
PyObject *pkgpath = Py_BuildValue("[O]", PyString_FromString(modname));
PyDict_SetItemString(dict, "__path__", pkgpath);
PyDict_SetItemString(dict, "__loader__", self);
PyObject *source = PyObject_CallMethod(this->zip, "read", "(s)", filename);
free(filename);
PyObject *code = Py_CompileString(PyString_AsString(source), modname, Py_file_input);
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
Py_DECREF(code);
Py_DECREF(source);
free(modname);
return mod;
}
clear:
PyErr_Clear();
free(filename);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* symimporter_find_module(PyObject *self, PyObject *args) {
char *fullname;
PyObject *path = NULL;
if (!PyArg_ParseTuple(args, "s|O:find_module", &fullname, &path)) {
return NULL;
}
char *fullname2 = symbolize(fullname);
char *code_start = name_to_symbol_module(fullname2, "start");
if (code_start) {
free(fullname2);
Py_INCREF(self);
return self;
}
code_start = name_to_symbol_pkg(fullname2, "start");
if (code_start) {
free(fullname2);
Py_INCREF(self);
return self;
}
free(fullname2);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* symimporter_load_module(PyObject *self, PyObject *args) {
char *code_start;
char *code_end;
char *fullname;
char *source;
char *modname;
PyObject *code;
if (!PyArg_ParseTuple(args, "s:load_module", &fullname)) {
return NULL;
}
char *fullname2 = symbolize(fullname);
code_start = name_to_symbol_module(fullname2, "start");
if (code_start) {
code_end = name_to_symbol_module(fullname2, "end");
if (code_end) {
PyObject *mod = PyImport_AddModule(fullname);
if (!mod) goto clear;
PyObject *dict = PyModule_GetDict(mod);
if (!dict) goto clear;
PyDict_SetItemString(dict, "__loader__", self);
source = uwsgi_concat2n(code_start, code_end-code_start, "", 0);
modname = uwsgi_concat3("sym://", fullname2, "_py");
code = Py_CompileString(source, modname, Py_file_input);
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
Py_DECREF(code);
free(source);
free(modname);
free(fullname2);
return mod;
}
}
code_start = name_to_symbol_pkg(fullname2, "start");
if (code_start) {
code_end = name_to_symbol_pkg(fullname2, "end");
if (code_end) {
PyObject *mod = PyImport_AddModule(fullname);
if (!mod) goto clear;
PyObject *dict = PyModule_GetDict(mod);
if (!dict) goto clear;
source = uwsgi_concat2n(code_start, code_end-code_start, "", 0);
modname = uwsgi_concat3("sym://", symbolize(fullname), "___init___py");
PyObject *pkgpath = Py_BuildValue("[O]", PyString_FromString(modname));
PyDict_SetItemString(dict, "__path__", pkgpath);
PyDict_SetItemString(dict, "__loader__", self);
code = Py_CompileString(source, modname, Py_file_input);
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
Py_DECREF(code);
free(source);
free(modname);
free(fullname2);
return mod;
}
}
clear:
free(fullname2);
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef symimporter_methods[] = {
{"find_module", symimporter_find_module, METH_VARARGS},
{"load_module", symimporter_load_module, METH_VARARGS},
};
static PyMethodDef symzipimporter_methods[] = {
{"find_module", symzipimporter_find_module, METH_VARARGS},
{"load_module", symzipimporter_load_module, METH_VARARGS},
};
static void uwsgi_symimporter_free(struct _symimporter *self) {
PyObject_Del(self);
}
static PyTypeObject SymImporter_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"uwsgi.SymbolsImporter",
sizeof(struct _symimporter),
0, /* tp_itemsize */
(destructor) uwsgi_symimporter_free, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT,
"uwsgi symbols importer", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
symimporter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
PyObject_GC_Del, /* tp_free */
};
static int
zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
{
char *name;
char *prefix = NULL;
int len = 0;
if (!PyArg_ParseTuple(args, "s", &name))
return -1;
// avoid GC !!!
name = uwsgi_concat2(name, "");
if (!uwsgi_startswith(name, "http://", 7) || !uwsgi_startswith(name, "data://", 7) || !uwsgi_startswith(name, "sym://", 6) ) {
prefix = uwsgi_get_last_char(name, '/');
prefix = uwsgi_get_last_char(prefix, ':');
}
else {
prefix = uwsgi_get_last_char(name, ':');
}
if (prefix) {
prefix[0] = 0;
}
char *body = uwsgi_open_and_read(name, &len, 0, NULL);
if (!body) {
return -1;
}
PyObject *stringio = PyImport_ImportModule("StringIO");
if (!stringio) {
return -1;
}
PyObject *stringio_dict = PyModule_GetDict(stringio);
if (!stringio_dict) {
return -1;
}
PyObject *stringio_stringio = PyDict_GetItemString(stringio_dict, "StringIO");
if (!stringio_stringio) {
return -1;
}
PyObject *stringio_args = PyTuple_New(1);
PyTuple_SetItem(stringio_args, 0, PyString_FromStringAndSize(body, len));
PyObject *source_code = PyInstance_New(stringio_stringio, stringio_args, NULL);
if (!source_code) {
return -1;
}
PyObject *zipfile = PyImport_ImportModule("zipfile");
if (!zipfile) {
return -1;
}
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
if (!zipfile_dict) {
return -1;
}
PyObject *zipfile_zipfile = PyDict_GetItemString(zipfile_dict, "ZipFile");
if (!zipfile_zipfile) {
return -1;
}
PyObject *zipfile_args = PyTuple_New(1);
PyTuple_SetItem(zipfile_args, 0, source_code);
self->zip = PyInstance_New(zipfile_zipfile, zipfile_args, NULL);
if (!self->zip) {
return -1;
}
Py_INCREF(self->zip);
self->items = PyObject_CallMethod(self->zip, "namelist", NULL);
if (!self->items) {
return -1;
}
Py_INCREF(self->items);
self->prefix = NULL;
if (prefix) {
self->prefix = prefix+1;
prefix[0] = ':';
}
return 0;
}
static int
symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
{
char *name;
char *prefix = NULL;
if (!PyArg_ParseTuple(args, "s", &name))
return -1;
// avoid GC !!!
name = uwsgi_concat2(name, "");
prefix = strchr(name, ':');
if (prefix) {
prefix[0] = 0;
}
char *code_start = name_to_symbol(name, "start");
if (!code_start) {
PyErr_Format(PyExc_ValueError, "unable to find symbol");
return -1;
}
char *code_end = name_to_symbol(name, "end");
if (!code_end) {
PyErr_Format(PyExc_ValueError, "unable to find symbol");
return -1;
}
PyObject *stringio = PyImport_ImportModule("StringIO");
if (!stringio) {
return -1;
}
PyObject *stringio_dict = PyModule_GetDict(stringio);
if (!stringio_dict) {
return -1;
}
PyObject *stringio_stringio = PyDict_GetItemString(stringio_dict, "StringIO");
if (!stringio_stringio) {
return -1;
}
PyObject *stringio_args = PyTuple_New(1);
PyTuple_SetItem(stringio_args, 0, PyString_FromStringAndSize(code_start, code_end-code_start));
PyObject *source_code = PyInstance_New(stringio_stringio, stringio_args, NULL);
if (!source_code) {
return -1;
}
PyObject *zipfile = PyImport_ImportModule("zipfile");
if (!zipfile) {
return -1;
}
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
if (!zipfile_dict) {
return -1;
}
PyObject *zipfile_zipfile = PyDict_GetItemString(zipfile_dict, "ZipFile");
if (!zipfile_zipfile) {
return -1;
}
PyObject *zipfile_args = PyTuple_New(1);
PyTuple_SetItem(zipfile_args, 0, source_code);
self->zip = PyInstance_New(zipfile_zipfile, zipfile_args, NULL);
if (!self->zip) {
return -1;
}
Py_INCREF(self->zip);
self->items = PyObject_CallMethod(self->zip, "namelist", NULL);
if (!self->items) {
return -1;
}
Py_INCREF(self->items);
self->prefix = NULL;
if (prefix) {
self->prefix = prefix+1;
prefix[0] = ':';
}
return 0;
}
static PyTypeObject SymZipImporter_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"uwsgi.SymbolsZipImporter",
sizeof(struct _symzipimporter),
0, /* tp_itemsize */
(destructor) uwsgi_symimporter_free, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT,
"uwsgi symbols zip importer", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
symzipimporter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc) symzipimporter_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
PyObject_GC_Del, /* tp_free */
};
static PyTypeObject ZipImporter_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"uwsgi.ZipImporter",
sizeof(struct _symzipimporter),
0, /* tp_itemsize */
(destructor) uwsgi_symimporter_free, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT,
"uwsgi zip importer", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
symzipimporter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc) zipimporter_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
PyObject_GC_Del, /* tp_free */
};
int uwsgi_init_symbol_import() {
if (PyType_Ready(&SymImporter_Type) < 0) {
PyErr_Print();
uwsgi_log("unable to initialize symbols importer module\n");
exit(1);
}
if (PyType_Ready(&ZipImporter_Type) < 0) {
PyErr_Print();
uwsgi_log("unable to initialize zip importer module\n");
exit(1);
}
if (PyType_Ready(&SymZipImporter_Type) < 0) {
PyErr_Print();
uwsgi_log("unable to initialize symbols zip importer module\n");
exit(1);
}
PyObject *uwsgi_em = PyImport_ImportModule("uwsgi");
if (!uwsgi_em) {
PyErr_Print();
uwsgi_log("unable to get uwsgi module\n");
exit(1);
}
if (PyModule_AddObject(uwsgi_em, "SymbolsImporter",
(PyObject *)&SymImporter_Type) < 0) {
PyErr_Print();
uwsgi_log("unable to initialize symbols importer object\n");
exit(1);
}
if (PyModule_AddObject(uwsgi_em, "ZipImporter",
(PyObject *)&ZipImporter_Type) < 0) {
PyErr_Print();
uwsgi_log("unable to initialize zip importer object\n");
exit(1);
}
if (PyModule_AddObject(uwsgi_em, "SymbolsZipImporter",
(PyObject *)&SymZipImporter_Type) < 0) {
PyErr_Print();
uwsgi_log("unable to initialize symbols zip importer object\n");
exit(1);
}
return 0;
}
#endif
+326 -63
View File
@@ -2,16 +2,74 @@
#include "uwsgi_python.h"
char *spool_buffer = NULL;
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req();
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
uint8_t received_signal;
int ret;
struct pollfd pfd[2];
wsgi_req->signal_received = -1;
if (PyTuple_Size(args) > 0) {
if (!PyArg_ParseTuple(args, "|B:", &uwsgi_signal)) {
return NULL;
}
wait_for_specific_signal = 1;
}
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
wsgi_req->sigwait = 1;
}
else {
#endif
pfd[0].fd = uwsgi.signal_socket;
pfd[0].events = POLLIN;
pfd[1].fd = uwsgi.my_signal_socket;
pfd[1].events = POLLIN;
cycle:
ret = poll(pfd, 2, -1);
if (ret > 0) {
if (pfd[0].revents == POLLIN) {
if (read(uwsgi.signal_socket, &received_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
if (uwsgi_signal_handler(received_signal)) {
uwsgi_log_verbose("error managing signal %d on worker %d\n", received_signal, uwsgi.mywid);
}
wsgi_req->signal_received = received_signal;
if (wait_for_specific_signal) {
if (received_signal != uwsgi_signal) goto cycle;
}
}
}
if (pfd[1].revents == POLLIN) {
if (read(uwsgi.my_signal_socket, &received_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
if (uwsgi_signal_handler(received_signal)) {
uwsgi_log_verbose("error managing signal %d on worker %d\n", received_signal, uwsgi.mywid);
}
wsgi_req->signal_received = received_signal;
if (wait_for_specific_signal) {
if (received_signal != uwsgi_signal) goto cycle;
}
}
}
}
#ifdef UWSGI_ASYNC
}
#endif
wsgi_req->sigwait = 1;
return PyString_FromString("");
}
@@ -115,6 +173,7 @@ char *uwsgi_encode_pydict(PyObject * pydict, uint16_t * size) {
if (!key || !val) {
PyErr_Print();
continue;
}
if (!PyString_Check(key) || !PyString_Check(val)) {
@@ -309,15 +368,15 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
char *node, *func;
uint16_t size = 0;
PyObject *py_node, *py_func;
struct uwsgi_header uh;
struct wsgi_request rpc_req;
int argc = PyTuple_Size(args);
char *argv[0xff];
int i, fd;
uint16_t pktsize = 0, ulen;
char *bufptr;
int rlen;
int rpc_args = 0;
struct pollfd upoll;
// TODO better error reporting
if (argc < 2)
@@ -341,10 +400,16 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
for (i = 0; i < (argc - 2); i++) {
argv[i] = PyString_AsString(PyTuple_GetItem(args, i + 2));
rpc_args++;
}
if (node == (char *) "") {
size = uwsgi_rpc(func, 0, NULL, buffer);
if (!strcmp(node, "")) {
if (!rpc_args) {
size = uwsgi_rpc(func, 0, NULL, buffer);
}
else {
size = uwsgi_rpc(func, rpc_args, argv, buffer);
}
}
else {
@@ -361,9 +426,11 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
pktsize += 2 + strlen(argv[i]);
}
uh.modifier1 = 173;
uh.pktsize = pktsize;
uh.modifier2 = 0;
memset(&rpc_req, 0, sizeof(struct wsgi_request));
rpc_req.uh.modifier1 = 173;
rpc_req.uh.pktsize = pktsize;
rpc_req.uh.modifier2 = 0;
bufptr = buffer;
@@ -381,7 +448,7 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
bufptr += ulen;
}
if (write(fd, &uh, 4) != 4) {
if (write(fd, &rpc_req.uh, 4) != 4) {
uwsgi_error("write()");
close(fd);
goto clear;
@@ -395,10 +462,11 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
rlen = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (rlen > 0) {
upoll.fd = fd;
upoll.events = POLLIN;
if (uwsgi_parse_response(&upoll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &uh, buffer, uwsgi_proto_uwsgi_parser)) {
size = uh.pktsize;
rpc_req.poll.fd = fd;
rpc_req.poll.events = POLLIN;
rpc_req.buffer = buffer;
if (uwsgi_parse_packet(&rpc_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
size = rpc_req.uh.pktsize;
}
}
@@ -426,8 +494,7 @@ PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
if (uwsgi_register_rpc(name, 0, argc, func)) {
Py_INCREF(Py_None);
return Py_None;
return PyErr_Format(PyExc_ValueError, "unable to register rpc function");
}
Py_INCREF(Py_True);
@@ -451,6 +518,22 @@ PyObject *py_uwsgi_attach_daemon(PyObject * self, PyObject * args) {
return Py_True;
}
PyObject *py_uwsgi_signal_registered(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
if (!PyArg_ParseTuple(args, "B:signal_registered", &uwsgi_signal)) {
return NULL;
}
if (uwsgi_signal_registered(uwsgi_signal)) {
Py_INCREF(Py_True);
return Py_True;
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
@@ -478,9 +561,11 @@ PyObject *py_uwsgi_signal(PyObject * self, PyObject * args) {
return NULL;
}
#ifdef UWSGI_DEBUG
uwsgi_log("sending %d to master\n", uwsgi_signal);
#endif
rlen = write(uwsgi.shared->worker_signal_pipe[1], &uwsgi_signal, 1);
rlen = write(uwsgi.signal_socket, &uwsgi_signal, 1);
if (rlen != 1) {
uwsgi_error("write()");
}
@@ -745,7 +830,7 @@ PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
size_t chunk;
off_t pos = 0;
size_t filesize = 0;
struct stat stat_buf;
struct wsgi_request *wsgi_req = current_wsgi_req();
int fd = -1;
@@ -770,36 +855,35 @@ PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
goto clear;
// check for mixing file_wrapper and sendfile
if (fd == uwsgi.wsgi_req->sendfile_fd) {
if (fd == wsgi_req->sendfile_fd) {
Py_INCREF(what);
}
}
if (!filesize) {
if (fstat(fd, &stat_buf)) {
uwsgi_error("fstat()");
goto clear2;
}
else {
filesize = stat_buf.st_size;
}
int tmp_fd = wsgi_req->sendfile_fd;
size_t tmp_filesize = wsgi_req->sendfile_fd_size;
size_t tmp_chunk = wsgi_req->sendfile_fd_chunk;
off_t tmp_pos = wsgi_req->sendfile_fd_pos;
}
wsgi_req->sendfile_fd = fd;
wsgi_req->sendfile_fd_size = filesize;
wsgi_req->sendfile_fd_chunk = chunk;
wsgi_req->sendfile_fd_pos = pos;
if (!filesize)
goto clear2;
// do sendfile
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
if (!chunk)
chunk = 4096;
uwsgi.wsgi_req->response_size += uwsgi_do_sendfile(uwsgi.wsgi_req->poll.fd, fd, filesize, chunk, &pos, 0);
// revert to old values
wsgi_req->sendfile_fd = tmp_fd;
wsgi_req->sendfile_fd_size = tmp_filesize;
wsgi_req->sendfile_fd_chunk = tmp_chunk;
wsgi_req->sendfile_fd_pos = tmp_pos;
close(fd);
Py_INCREF(Py_True);
return Py_True;
clear2:
close(fd);
clear:
Py_INCREF(Py_None);
return Py_None;
@@ -867,14 +951,13 @@ PyObject *py_uwsgi_log(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_lock(PyObject * self, PyObject * args) {
// the spooler, the master process or single process environment cannot lock resources
// the spooler cannot lock resources
#ifdef UWSGI_SPOOLER
if (uwsgi.numproc > 1 && uwsgi.mypid != uwsgi.workers[0].pid && uwsgi.mypid != uwsgi.shared->spooler_pid) {
#else
if (uwsgi.numproc > 1 && uwsgi.mypid != uwsgi.workers[0].pid) {
#endif
uwsgi_lock(uwsgi.user_lock);
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
}
#endif
uwsgi_lock(uwsgi.user_lock);
Py_INCREF(Py_None);
return Py_None;
@@ -882,12 +965,47 @@ PyObject *py_uwsgi_lock(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_unlock(PyObject * self, PyObject * args) {
#ifdef UWSGI_SPOOLER
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
}
#endif
uwsgi_unlock(uwsgi.user_lock);
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_embedded_data(PyObject * self, PyObject * args) {
char *name;
char *symbol;
void *sym_ptr_start = NULL;
void *sym_ptr_end = NULL;
if (!PyArg_ParseTuple(args, "s:embedded_data", &name)) {
return NULL;
}
symbol = uwsgi_concat3("_binary_", name, "_start");
sym_ptr_start = dlsym(RTLD_DEFAULT, symbol);
free(symbol);
if (!sym_ptr_start)
return PyErr_Format(PyExc_ValueError, "unable to find symbol %s", name);
symbol = uwsgi_concat3("_binary_", name, "_end");
sym_ptr_end = dlsym(RTLD_DEFAULT, symbol);
free(symbol);
if (!sym_ptr_end)
return PyErr_Format(PyExc_ValueError, "unable to find symbol %s", name);
return PyString_FromStringAndSize(sym_ptr_start, sym_ptr_end - sym_ptr_start);
}
PyObject *py_uwsgi_sharedarea_inclong(PyObject * self, PyObject * args) {
int pos = 0;
long value = 0;
@@ -1127,6 +1245,11 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
int i;
char spool_filename[1024];
struct wsgi_request *wsgi_req = current_wsgi_req();
char *priority = NULL;
long numprio = 0;
time_t at = 0;
char *body = NULL;
size_t body_len= 0;
spool_dict = PyTuple_GetItem(args, 0);
@@ -1147,12 +1270,47 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
return PyErr_Format(PyExc_ValueError, "The argument of spooler callable must be a dictionary");
}
PyObject *pyprio = uwsgi_py_dict_get(spool_dict, "priority");
if (pyprio) {
if (PyInt_Check(pyprio)) {
numprio = PyInt_AsLong(pyprio);
uwsgi_py_dict_del(spool_dict, "priority");
}
}
PyObject *pyat = uwsgi_py_dict_get(spool_dict, "at");
if (pyat) {
if (PyInt_Check(pyat)) {
at = (time_t) PyInt_AsLong(pyat);
uwsgi_py_dict_del(spool_dict, "at");
}
else if (PyLong_Check(pyat)) {
at = (time_t) PyLong_AsLong(pyat);
uwsgi_py_dict_del(spool_dict, "at");
}
else if (PyFloat_Check(pyat)) {
at = (time_t) PyFloat_AsDouble(pyat);
uwsgi_py_dict_del(spool_dict, "at");
}
}
PyObject *pybody = uwsgi_py_dict_get(spool_dict, "body");
if (pybody) {
if (PyString_Check(pybody)) {
body = PyString_AsString(pybody);
body_len = PyString_Size(pybody);
uwsgi_py_dict_del(spool_dict, "body");
}
}
spool_vars = PyDict_Items(spool_dict);
if (!spool_vars) {
Py_INCREF(Py_None);
return Py_None;
}
char *spool_buffer = uwsgi_malloc(UMAX16);
cur_buf = spool_buffer;
for (i = 0; i < PyList_Size(spool_vars); i++) {
@@ -1162,12 +1320,16 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
key = PyTuple_GetItem(zero, 0);
val = PyTuple_GetItem(zero, 1);
#ifdef UWSGI_DEBUG
uwsgi_log("ob_type %s %s\n", key->ob_type->tp_name, val->ob_type->tp_name);
#endif
if (PyString_Check(key) && PyString_Check(val)) {
keysize = PyString_Size(key);
valsize = PyString_Size(val);
if (cur_buf + keysize + 2 + valsize + 2 <= spool_buffer + uwsgi.buffer_size) {
if (cur_buf + keysize + 2 + valsize + 2 <= spool_buffer + UMAX16) {
#ifdef __BIG_ENDIAN__
keysize = uwsgi_swap16(keysize);
@@ -1192,36 +1354,54 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
}
else {
Py_DECREF(zero);
return PyErr_Format(PyExc_ValueError, "spooler packet cannot be more than %d bytes", uwsgi.buffer_size);
free(spool_buffer);
return PyErr_Format(PyExc_ValueError, "spooler packet cannot be more than %d bytes", UMAX16);
}
}
else {
Py_DECREF(zero);
free(spool_buffer);
return PyErr_Format(PyExc_ValueError, "spooler callable dictionary must contains only strings");
}
}
else {
free(spool_buffer);
Py_DECREF(zero);
Py_INCREF(Py_None);
return Py_None;
}
}
else {
free(spool_buffer);
Py_INCREF(Py_None);
return Py_None;
}
}
i = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, cur_buf - spool_buffer);
if (numprio) {
priority = uwsgi_num2str(numprio);
}
i = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, cur_buf - spool_buffer, priority, at, body, body_len);
if (priority) {
free(priority);
}
free(spool_buffer);
Py_DECREF(spool_vars);
if (i > 0) {
Py_INCREF(Py_True);
return Py_True;
char *slash = uwsgi_get_last_char(spool_filename, '/');
if (slash) {
return PyString_FromString(slash+1);
}
return PyString_FromString(spool_filename);
}
Py_INCREF(Py_None);
return Py_None;
return PyErr_Format(PyExc_ValueError, "unable to spool job");
}
PyObject *py_uwsgi_spooler_pid(PyObject * self, PyObject * args) {
return PyInt_FromLong(uwsgi.shared->spooler_pid ? uwsgi.shared->spooler_pid : 0);
}
#endif
@@ -1234,7 +1414,7 @@ PyObject *py_uwsgi_send_multi_message(PyObject * self, PyObject * args) {
int managed;
struct pollfd *multipoll;
char *buffer;
struct uwsgi_header uh;
PyObject *arg_cluster;
PyObject *cluster_node;
@@ -1348,9 +1528,11 @@ PyObject *py_uwsgi_send_multi_message(PyObject * self, PyObject * args) {
goto megamulticlear;
}
else {
// TODO fix
/*
for (i = 0; i < clen; i++) {
if (multipoll[i].revents & POLLIN) {
if (!uwsgi_parse_response(&multipoll[i], PyInt_AsLong(arg_timeout), &uh, &buffer[i], uwsgi_proto_uwsgi_parser)) {
if (!uwsgi_parse_packet(&multipoll[i], PyInt_AsLong(arg_timeout), &uh, &buffer[i], uwsgi_proto_uwsgi_parser)) {
goto megamulticlear;
}
else {
@@ -1363,6 +1545,7 @@ PyObject *py_uwsgi_send_multi_message(PyObject * self, PyObject * args) {
}
}
}
*/
}
}
@@ -1898,8 +2081,9 @@ PyObject *py_uwsgi_total_requests(PyObject * self, PyObject * args) {
/* uWSGI workers */
PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
PyObject *worker_dict, *zero;
int i;
PyObject *worker_dict, *apps_dict, *apps_tuple, *zero;
int i, j;
struct uwsgi_app *ua;
for (i = 0; i < uwsgi.numproc; i++) {
worker_dict = PyTuple_GetItem(up.workers_tuple, i);
@@ -1972,6 +2156,43 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
Py_DECREF(zero);
*/
apps_tuple = PyTuple_New(uwsgi.workers[i+1].apps_cnt);
for(j=0;j<uwsgi.workers[i+1].apps_cnt;j++) {
apps_dict = PyDict_New();
ua = &uwsgi.workers[i+1].apps[j];
PyDict_SetItemString(apps_dict, "id", PyInt_FromLong(j));
PyDict_SetItemString(apps_dict, "modifier1", PyInt_FromLong(ua->modifier1));
zero = PyString_FromStringAndSize(ua->mountpoint, ua->mountpoint_len);
PyDict_SetItemString(apps_dict, "mountpoint", zero);
Py_DECREF(zero);
PyDict_SetItemString(apps_dict, "interpreter", PyInt_FromLong((long)ua->interpreter));
PyDict_SetItemString(apps_dict, "callable", PyInt_FromLong((long)ua->interpreter));
PyDict_SetItemString(apps_dict, "requests", PyInt_FromLong(ua->requests));
PyDict_SetItemString(apps_dict, "exceptions", PyInt_FromLong(ua->exceptions));
if (ua->chdir) {
zero = PyString_FromString(ua->chdir);
}
else {
zero = PyString_FromString("");
}
PyDict_SetItemString(apps_dict, "chdir", zero);
Py_DECREF(zero);
PyTuple_SetItem(apps_tuple, j, apps_dict);
}
PyDict_SetItemString(worker_dict, "apps", apps_tuple);
Py_DECREF(apps_tuple);
}
@@ -1986,6 +2207,7 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
}
/* uWSGI reload */
PyObject *py_uwsgi_reload(PyObject * self, PyObject * args) {
@@ -2200,6 +2422,9 @@ PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
// this field will be overwrite after each call
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
// reset the random seed
uwsgi_python_reset_random_seed();
// TODO
// manage thread in grunt processes
Py_INCREF(Py_True);
@@ -2228,6 +2453,7 @@ static PyMethodDef uwsgi_spooler_methods[] = {
#endif
{"set_spooler_frequency", py_uwsgi_spooler_freq, METH_VARARGS, ""},
{"spooler_jobs", py_uwsgi_spooler_jobs, METH_VARARGS, ""},
{"spooler_pid", py_uwsgi_spooler_pid, METH_VARARGS, ""},
{NULL, NULL},
};
#endif
@@ -2272,7 +2498,9 @@ PyObject *py_uwsgi_cluster_node_name(PyObject * self, PyObject * args) {
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("node_name: %s %s\n", node, ucn->name);
#endif
if (!strcmp(ucn->name, node)) {
return PyString_FromString(ucn->nodename);
}
@@ -2352,6 +2580,7 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"register_signal", py_uwsgi_register_signal, METH_VARARGS, ""},
{"signal", py_uwsgi_signal, METH_VARARGS, ""},
{"signal_wait", py_uwsgi_signal_wait, METH_VARARGS, ""},
{"signal_registered", py_uwsgi_signal_registered, METH_VARARGS, ""},
{"signal_received", py_uwsgi_signal_received, METH_VARARGS, ""},
{"add_file_monitor", py_uwsgi_add_file_monitor, METH_VARARGS, ""},
{"add_timer", py_uwsgi_add_timer, METH_VARARGS, ""},
@@ -2398,6 +2627,7 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"fcgi", py_uwsgi_fcgi, METH_VARARGS, ""},
{"parsefile", py_uwsgi_parse_file, METH_VARARGS, ""},
{"embedded_data", py_uwsgi_embedded_data, METH_VARARGS, ""},
//{"call_hook", py_uwsgi_call_hook, METH_VARARGS, ""},
{NULL, NULL},
@@ -2480,6 +2710,43 @@ PyObject *py_uwsgi_cache_set(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_cache_update(PyObject * self, PyObject * args) {
char *key;
char *value;
Py_ssize_t vallen = 0;
Py_ssize_t keylen = 0;
char *remote = NULL;
uint64_t expires = 0;
if (!PyArg_ParseTuple(args, "s#s#|is:cache_update", &key, &keylen, &value, &vallen, &expires, &remote)) {
return NULL;
}
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
return PyErr_Format(PyExc_ValueError, "uWSGI cache items size must be < %llu, requested %d bytes", (unsigned long long)uwsgi.cache_blocksize, (int) vallen);
}
if (remote && strlen(remote) > 0) {
uwsgi_simple_send_string2(remote, 111, 1, key, keylen, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
}
else if (uwsgi.cache_max_items) {
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
uwsgi_rwunlock(uwsgi.cache_lock);
Py_INCREF(Py_None);
return Py_None;
}
uwsgi_rwunlock(uwsgi.cache_lock);
}
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_cache_exists(PyObject * self, PyObject * args) {
@@ -2495,6 +2762,7 @@ PyObject *py_uwsgi_cache_exists(PyObject * self, PyObject * args) {
}
if (remote && strlen(remote) > 0) {
// TODO FIX THIS !!!
uwsgi_simple_message_string(remote, 111, 0, key, keylen, buffer, &valsize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (valsize > 0) {
Py_INCREF(Py_True);
@@ -2657,6 +2925,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
char *key;
uint64_t valsize;
uint16_t valsize16;
Py_ssize_t keylen = 0;
char *value = NULL;
char *remote = NULL;
@@ -2672,8 +2941,8 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
}
if (remote && strlen(remote) > 0) {
//uwsgi_simple_message_string(remote, 111, 0, key, keylen, buffer, &valsize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (valsize > 0) {
uwsgi_simple_message_string(remote, 111, 0, key, keylen, buffer, &valsize16, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (valsize16 > 0) {
value = buffer;
}
}
@@ -2711,6 +2980,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
static PyMethodDef uwsgi_cache_methods[] = {
{"cache_get", py_uwsgi_cache_get, METH_VARARGS, ""},
{"cache_set", py_uwsgi_cache_set, METH_VARARGS, ""},
{"cache_update", py_uwsgi_cache_update, METH_VARARGS, ""},
{"cache_del", py_uwsgi_cache_del, METH_VARARGS, ""},
{"cache_exists", py_uwsgi_cache_exists, METH_VARARGS, ""},
{NULL, NULL},
@@ -2738,13 +3008,6 @@ void init_uwsgi_module_spooler(PyObject * current_uwsgi_module) {
exit(1);
}
spool_buffer = malloc(uwsgi.buffer_size);
if (!spool_buffer) {
uwsgi_error("malloc()");
exit(1);
}
for (uwsgi_function = uwsgi_spooler_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(uwsgi_module_dict, uwsgi_function->ml_name, func);
+51 -4
View File
@@ -13,6 +13,19 @@
#define LONG_ARGS_PYARGV LONG_ARGS_PYTHON_BASE + 3
#define LONG_ARGS_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 4
#define LONG_ARGS_RELOAD_OS_ENV LONG_ARGS_PYTHON_BASE + 5
#define LONG_ARGS_PYIMPORT LONG_ARGS_PYTHON_BASE + 6
#define LONG_ARGS_POST_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 7
#define LONG_ARGS_WEB3 LONG_ARGS_PYTHON_BASE + 8
#define LONG_ARGS_PUMP LONG_ARGS_PYTHON_BASE + 9
#define LONG_ARGS_WSGI_LITE LONG_ARGS_PYTHON_BASE + 10
#define LONG_ARGS_PYSHELL LONG_ARGS_PYTHON_BASE + 11
#define LONG_ARGS_SPOOLER_PYIMPORT LONG_ARGS_PYTHON_BASE + 12
#define PYTHON_APP_TYPE_WSGI 0
#define PYTHON_APP_TYPE_WEB3 1
#define PYTHON_APP_TYPE_WSGI2 2
#define PYTHON_APP_TYPE_PUMP 3
#define PYTHON_APP_TYPE_WSGI_LITE 4
#if PY_MINOR_VERSION == 4 && PY_MAJOR_VERSION == 2
#define Py_ssize_t ssize_t
@@ -60,10 +73,14 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define PyString_Concat PyBytes_Concat
#define PyString_AsString (char *) PyBytes_AsString
#define PyFile_FromFile(A,B,C,D) PyFile_FromFd(fileno((A)), (B), (C), -1, NULL, NULL, NULL, 0)
#define uwsgi_py_dict_get(a, b) PyDict_GetItem(a, PyBytes_FromString(b));
#define uwsgi_py_dict_del(a, b) PyDict_DelItem(a, PyBytes_FromString(b));
#else
#define UWSGI_PYFROMSTRING(x) PyString_FromString(x)
#define UWSGI_PYFROMSTRINGSIZE(x, y) PyString_FromStringAndSize(x, y)
#define uwsgi_py_dict_get(a, b) PyDict_GetItemString(a, b)
#define uwsgi_py_dict_del(a, b) PyDict_DelItemString(a, b)
#endif
#define LOADER_DYN 0
@@ -77,6 +94,16 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define LOADER_MAX 8
typedef struct uwsgi_Input {
PyObject_HEAD
char readline[1024];
size_t readline_size;
size_t readline_max_size;
size_t readline_pos;
size_t pos;
struct wsgi_request *wsgi_req;
} uwsgi_Input;
struct uwsgi_python {
char *home;
@@ -98,7 +125,12 @@ struct uwsgi_python {
char *test_module;
int pyshell;
struct uwsgi_string_list *python_path;
struct uwsgi_string_list *import_list;
struct uwsgi_string_list *spooler_import_list;
struct uwsgi_string_list *post_pymodule_alias;
PyObject *loader_dict;
PyObject* (*loaders[LOADER_MAX]) (void *);
@@ -108,6 +140,9 @@ struct uwsgi_python {
char *paste;
char *eval;
char *web3;
char *pump;
char *wsgi_lite;
char *callable;
@@ -144,6 +179,7 @@ struct uwsgi_python {
void (*extension)(void);
int reload_os_env;
};
@@ -157,7 +193,7 @@ void uwsgi_paste_config(char *);
void uwsgi_file_config(char *);
void uwsgi_eval_config(char *);
int init_uwsgi_app(int, void *, struct wsgi_request *wsgi_req, PyThreadState *);
int init_uwsgi_app(int, void *, struct wsgi_request *, PyThreadState *, int);
PyObject *py_eventfd_read(PyObject *, PyObject *);
@@ -166,7 +202,7 @@ PyObject *py_eventfd_write(PyObject *, PyObject *);
int manage_python_response(struct wsgi_request *);
int uwsgi_python_call(struct wsgi_request *, PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *, int);
PyObject *python_call(PyObject *, PyObject *, int, struct wsgi_request *);
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *);
@@ -179,10 +215,11 @@ PyObject *py_uwsgi_spit(PyObject *, PyObject *);
void init_pyargv(void);
#ifdef UWSGI_WEB3
void *uwsgi_request_subhandler_web3(struct wsgi_request *, struct uwsgi_app *);
int uwsgi_response_subhandler_web3(struct wsgi_request *);
#endif
void *uwsgi_request_subhandler_pump(struct wsgi_request *, struct uwsgi_app *);
int uwsgi_response_subhandler_pump(struct wsgi_request *);
PyObject *uwsgi_uwsgi_loader(void *);
PyObject *uwsgi_dyn_loader(void *);
@@ -221,3 +258,13 @@ void threaded_reset_ts(struct wsgi_request *, struct uwsgi_app *);
void simple_reset_ts(struct wsgi_request *, struct uwsgi_app *);
int uwsgi_python_profiler_call(PyObject *, PyFrameObject *, int, PyObject *);
void uwsgi_python_reset_random_seed(void);
char *uwsgi_pythonize(char *);
#ifdef __linux__
#ifndef PYTHREE
int uwsgi_init_symbol_import(void);
#endif
#endif
+1 -1
View File
@@ -3,7 +3,7 @@ import os,sys
from distutils import sysconfig
NAME='python'
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler']
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter']
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
LDFLAGS = []
+131 -53
View File
@@ -1,20 +1,70 @@
#include "uwsgi.h"
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern PyTypeObject uwsgi_InputType;
void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
PyObject *zero, *wsgi_socket;
PyObject *zero;
wsgi_socket = PyFile_FromFile(wsgi_req->async_post, "web3_input", "r", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "web3.input", wsgi_socket);
Py_DECREF(wsgi_socket);
int i;
PyObject *pydictkey, *pydictvalue;
char *path_info;
zero = PyTuple_New(2);
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
PyDict_SetItemString(wsgi_req->async_environ, "web3.version", zero);
Py_DECREF(zero);
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
#ifdef PYTHREE
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
wsgi_req->uh.modifier1 = 0;
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
if (pydictvalue) {
if (PyString_Check(pydictvalue)) {
path_info = PyString_AsString(pydictvalue);
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
}
}
}
}
}
// if async_post is mapped as a file, directly use it as wsgi.input
if (wsgi_req->async_post) {
#ifdef PYTHREE
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "web3_input", "rb", 0, NULL, NULL, NULL, 0);
#else
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "web3_input", "r", NULL);
#endif
}
else {
// create wsgi.input custom object
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
}
PyDict_SetItemString(wsgi_req->async_environ, "web3.input", wsgi_req->async_input);
PyDict_SetItemString(wsgi_req->async_environ, "web3.version", wi->gateway_version);
zero = PyFile_FromFile(stderr, "web3_input", "w", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "web3.errors", zero);
@@ -31,35 +81,53 @@ void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_
}
if (wsgi_req->scheme_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
zero = PyString_FromString("https");
zero = UWSGI_PYFROMSTRING("https");
}
else {
zero = PyString_FromString("http");
zero = UWSGI_PYFROMSTRING("http");
}
}
else {
zero = PyString_FromString("http");
zero = UWSGI_PYFROMSTRING("http");
}
PyDict_SetItemString(wsgi_req->async_environ, "web3.url_scheme", zero);
Py_DECREF(zero);
wsgi_req->async_app = wi->wsgi_callable;
wsgi_req->async_app = wi->callable;
PyDict_SetItemString(uwsgi.embedded_dict, "env", wsgi_req->async_environ);
// export .env only in non-threaded mode
if (uwsgi.threads < 2) {
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
}
// TODO: fix this
//PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", uwsgi_version);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
if (uwsgi.cores > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
}
// cache this ?
if (uwsgi.cluster_fd >= 0) {
zero = PyString_FromString(uwsgi.cluster);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
Py_DECREF(zero);
zero = PyString_FromString(uwsgi.hostname);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero);
Py_DECREF(zero);
}
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
// call
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions);
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
}
@@ -68,16 +136,7 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
PyObject *pychunk;
ssize_t wsize;
// return or yield ? (PyString on python2 PyBytes on python3)
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
uwsgi_error("write()");
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
UWSGI_GET_GIL
// ok its a yield
if (!wsgi_req->async_placeholder) {
@@ -86,19 +145,51 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
uwsgi_log("invalid Web3 response.\n");
goto clear;
}
if (py_uwsgi_spit(NULL, (PyObject *)wsgi_req->async_result) == Py_None) {
wsgi_req->async_placeholder = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 0);
Py_INCREF((PyObject *)wsgi_req->async_placeholder);
PyObject *spit_args = PyTuple_New(2);
PyObject *status = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 1);
Py_INCREF(status);
PyTuple_SetItem(spit_args, 0, status);
PyObject *headers = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 2);
Py_INCREF(headers);
PyTuple_SetItem(spit_args, 1, headers);
if (py_uwsgi_spit(NULL, spit_args) == Py_None) {
Py_DECREF(spit_args);
goto clear;
}
wsgi_req->async_result = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 0);
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_result );
Py_DECREF(spit_args);
if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) {
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(wsgi_req->async_placeholder), PyString_Size(wsgi_req->async_placeholder))) < 0) {
uwsgi_error("write()");
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
PyObject *tmp = (PyObject *)wsgi_req->async_placeholder;
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_placeholder );
Py_DECREF(tmp);
if (!wsgi_req->async_placeholder) {
goto clear2;
goto clear;
}
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
}
@@ -119,9 +210,8 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
}
if (PyString_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
uwsgi_error("write()");
Py_DECREF(pychunk);
goto clear;
@@ -131,34 +221,22 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
Py_DECREF(pychunk);
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
clear:
if (wsgi_req->async_input) {
Py_DECREF((PyObject *)wsgi_req->async_input);
}
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
if (wsgi_req->async_post && !wsgi_req->fd_closed) {
fclose(wsgi_req->async_post);
if (!uwsgi.post_buffering || wsgi_req->post_cl <= (size_t) uwsgi.post_buffering) {
wsgi_req->fd_closed = 1;
}
}
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
clear2:
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
#ifdef UWSGI_DEBUG
if (wsgi_req->async_placeholder) {
uwsgi_debug("wsgi_req->async_placeholder: %d\n", ((PyObject *)wsgi_req->async_placeholder)->ob_refcnt);
}
if (wsgi_req->async_result) {
uwsgi_debug("wsgi_req->async_result: %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
}
if (wsgi_req->async_app) {
uwsgi_debug("wsgi_req->async_app: %d\n", ((PyObject *)wsgi_req->async_app)->ob_refcnt);
}
#endif
UWSGI_RELEASE_GIL
return UWSGI_OK;
}
+50 -145
View File
@@ -4,16 +4,6 @@ extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
typedef struct uwsgi_Input {
PyObject_HEAD
char readline[1024];
size_t readline_size;
size_t readline_max_size;
size_t readline_pos;
size_t pos;
struct wsgi_request *wsgi_req;
} uwsgi_Input;
PyObject *uwsgi_Input_iter(PyObject *self) {
Py_INCREF(self);
return self;
@@ -44,8 +34,9 @@ PyObject *uwsgi_Input_getline(uwsgi_Input *self) {
return res;
}
}
res = PyString_FromStringAndSize(ptr + self->readline_pos, self->readline_size - self->readline_pos);
self->readline_pos = 0;
return PyString_FromStringAndSize(ptr + self->readline_pos, self->readline_size - self->readline_pos);
return res;
}
@@ -61,7 +52,7 @@ PyObject *uwsgi_Input_getline(uwsgi_Input *self) {
else {
rlen = read(wsgi_req->poll.fd, self->readline, 1024);
}
if (rlen < 0) {
if (rlen <= 0) {
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data");
}
@@ -74,7 +65,7 @@ PyObject *uwsgi_Input_getline(uwsgi_Input *self) {
for(i=0;i<(size_t)rlen;i++) {
if (self->readline[i] == '\n') {
res = PyString_FromStringAndSize(self->readline, i);
res = PyString_FromStringAndSize(self->readline, i+1);
self->readline_pos+= i+1;
if (self->readline_pos >= self->readline_size) self->readline_pos = 0;
return res;
@@ -165,7 +156,7 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
}
rlen = read(self->wsgi_req->poll.fd, tmp_buf+tmp_pos, remains);
if (rlen < 0) {
if (rlen <= 0) {
free(tmp_buf);
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data");
@@ -220,12 +211,18 @@ static PyObject *uwsgi_Input_close(uwsgi_Input *self, PyObject *args) {
return Py_None;
}
static PyObject *uwsgi_Input_fileno(uwsgi_Input *self, PyObject *args) {
return PyInt_FromLong(self->wsgi_req->poll.fd);
}
static PyMethodDef uwsgi_Input_methods[] = {
{ "read", (PyCFunction)uwsgi_Input_read, METH_VARARGS, 0 },
{ "readline", (PyCFunction)uwsgi_Input_readline, METH_VARARGS, 0 },
{ "readlines", (PyCFunction)uwsgi_Input_readlines, METH_VARARGS, 0 },
// add close to allow mod_wsgi compatibility
{ "close", (PyCFunction)uwsgi_Input_close, METH_VARARGS, 0 },
{ "fileno", (PyCFunction)uwsgi_Input_fileno, METH_VARARGS, 0 },
{ NULL, NULL}
};
@@ -326,16 +323,10 @@ PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
int i;
PyObject *pydictkey, *pydictvalue;
char *path_info;
struct uwsgi_app *wi;
int tmp_stderr;
char *what;
int what_len;
int free_appid = 0;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
@@ -362,7 +353,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
/* Standard WSGI request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log( "Invalid WSGI request. skip.\n");
uwsgi_log( "Empty python request. skip.\n");
return -1;
}
@@ -371,76 +362,59 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
if (!up.ignore_script_name) {
if (!wsgi_req->script_name)
wsgi_req->script_name = "";
if (wsgi_req->appid_len == 0) {
if (!up.ignore_script_name) {
wsgi_req->appid = wsgi_req->script_name;
wsgi_req->appid_len = wsgi_req->script_name_len;
}
if (uwsgi.vhost) {
what = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
what_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
wsgi_req->appid = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
wsgi_req->appid_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
#ifdef UWSGI_DEBUG
uwsgi_debug("VirtualHost SCRIPT_NAME=%s\n", what);
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
#endif
free_appid = 1;
}
else {
what = wsgi_req->script_name;
what_len = wsgi_req->script_name_len;
}
}
if ( (wsgi_req->app_id = uwsgi_get_app_id(what, what_len, 0)) == -1) {
if (wsgi_req->script_name_len > 1 || uwsgi.default_app < 0 || uwsgi.vhost) {
/* unavailable app for this SCRIPT_NAME */
wsgi_req->app_id = -1;
if (wsgi_req->script_len > 0
|| wsgi_req->module_len > 0
|| wsgi_req->file_len > 0
|| wsgi_req->paste_len > 0
) {
// this part must be heavy locked in threaded modes
if (uwsgi.threads > 1) {
pthread_mutex_lock(&up.lock_pyloaders);
}
UWSGI_GET_GIL
if (uwsgi.single_interpreter) {
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, up.main_thread);
}
else {
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, NULL);
}
UWSGI_RELEASE_GIL
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&up.lock_pyloaders);
}
}
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
wsgi_req->app_id = uwsgi.default_app;
if (uwsgi.no_default_app) {
wsgi_req->app_id = -1;
}
if (wsgi_req->dynamic) {
// this part must be heavy locked in threaded modes
if (uwsgi.threads > 1) {
pthread_mutex_lock(&up.lock_pyloaders);
}
UWSGI_GET_GIL
if (uwsgi.single_interpreter) {
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
else {
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
}
UWSGI_RELEASE_GIL
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&up.lock_pyloaders);
}
}
if (uwsgi.vhost) {
free(what);
}
}
else {
wsgi_req->app_id = 0;
}
if (free_appid) {
free(wsgi_req->appid);
}
if (wsgi_req->app_id == -1) {
// use default app ?
if (!uwsgi.no_default_app && uwsgi.default_app >= 0) {
wsgi_req->app_id = uwsgi.default_app;
}
else {
internal_server_error(wsgi_req, "wsgi application not found");
goto clear2;
}
internal_server_error(wsgi_req, "Python application not found");
goto clear2;
}
wi = &uwsgi.apps[wsgi_req->app_id];
wi = &uwsgi_apps[wsgi_req->app_id];
up.swap_ts(wsgi_req, wi);
@@ -454,21 +428,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
if (wsgi_req->protocol_len < 5) {
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req, "invalid HTTP protocol !!!");
goto clear;
}
if (strncmp(wsgi_req->protocol, "HTTP/", 5)) {
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req, "invalid HTTP protocol !!!");
goto clear;
}
#ifdef UWSGI_ASYNC
wsgi_req->async_environ = wi->environ[wsgi_req->async_id];
wsgi_req->async_args = wi->args[wsgi_req->async_id];
@@ -484,60 +443,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
Py_INCREF((PyObject *)wsgi_req->async_environ);
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
#ifdef PYTHREE
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
wsgi_req->uh.modifier1 = 0;
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
if (pydictvalue) {
if (PyString_Check(pydictvalue)) {
path_info = PyString_AsString(pydictvalue);
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
}
}
}
}
}
// if async_post is mapped as a file, directly use it as wsgi.input
if (wsgi_req->async_post) {
#ifdef PYTHREE
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "wsgi_input", "rb", 0, NULL, NULL, NULL, 0);
#else
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
#endif
}
else {
// create wsgi.input custom object
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
}
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input);
wsgi_req->async_result = wi->request_subhandler(wsgi_req, wi);
UWSGI_RELEASE_GIL
+2 -1
View File
@@ -38,7 +38,8 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
// in this way, error will be reported to the log
PyErr_Restore(exc_type, exc_val, exc_tb);
goto clear;
// the error is reported, let's continue...
//goto clear;
}
}
+65 -20
View File
@@ -2,19 +2,67 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern PyTypeObject uwsgi_InputType;
void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
PyObject *zero;
int i;
PyObject *pydictkey, *pydictvalue;
char *path_info;
//static PyObject *uwsgi_version = NULL;
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
#ifdef PYTHREE
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
/*
if (uwsgi_version == NULL) {
uwsgi_version = PyString_FromString(UWSGI_VERSION);
}
*/
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
wsgi_req->uh.modifier1 = 0;
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
if (pydictvalue) {
if (PyString_Check(pydictvalue)) {
path_info = PyString_AsString(pydictvalue);
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
}
}
}
}
}
// if async_post is mapped as a file, directly use it as wsgi.input
if (wsgi_req->async_post) {
#ifdef PYTHREE
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "wsgi_input", "rb", 0, NULL, NULL, NULL, 0);
#else
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
#endif
}
else {
// create wsgi.input custom object
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
}
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input);
#ifdef UWSGI_SENDFILE
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->sendfile);
@@ -28,12 +76,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
}
#endif
// cache this
zero = PyTuple_New(2);
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", zero);
Py_DECREF(zero);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", wi->gateway_version);
zero = PyFile_FromFile(stderr, "wsgi_input", "w", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.errors", zero);
@@ -55,18 +98,18 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
}
if (wsgi_req->scheme_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
zero = PyString_FromString("https");
zero = UWSGI_PYFROMSTRING("https");
}
else {
zero = PyString_FromString("http");
zero = UWSGI_PYFROMSTRING("http");
}
}
else {
zero = PyString_FromString("http");
zero = UWSGI_PYFROMSTRING("http");
}
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
Py_DECREF(zero);
@@ -79,14 +122,13 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
}
zero = PyString_FromString(UWSGI_VERSION);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", zero);
Py_DECREF(zero);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
if (uwsgi.cores > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
}
// cache this ?
if (uwsgi.cluster_fd >= 0) {
zero = PyString_FromString(uwsgi.cluster);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
@@ -96,6 +138,8 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
Py_DECREF(zero);
}
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
#ifdef UWSGI_ROUTING
uwsgi_log("routing %d routes %d\n", uwsgi.routing, uwsgi.nroutes);
@@ -109,7 +153,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions);
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions, wsgi_req);
}
int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
@@ -176,6 +220,7 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
uwsgi_log("Memory Error detected !!!\n");
}
uwsgi.workers[uwsgi.mywid].exceptions++;
uwsgi_apps[wsgi_req->app_id].exceptions++;
PyErr_Print();
}
goto clear;
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python24'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler'])
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.4-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python25'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler'])
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.5-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python26'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler'])
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.6-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python27'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler'])
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.7-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
+190 -53
View File
@@ -32,53 +32,7 @@ void uwsgi_ruby_exception(void) {
/* statistically ordered */
static struct http_status_codes hsc[] = {
{"200", "OK"},
{"302", "Found"},
{"404", "Not Found"},
{"500", "Internal Server Error"},
{"301", "Moved Permanently"},
{"304", "Not Modified"},
{"303", "See Other"},
{"403", "Forbidden"},
{"307", "Temporary Redirect"},
{"401", "Unauthorized"},
{"400", "Bad Request"},
{"405", "Method Not Allowed"},
{"408", "Request Timeout"},
{"100", "Continue"},
{"101", "Switching Protocols"},
{"201", "Created"},
{"202", "Accepted"},
{"203", "Non-Authoritative Information"},
{"204", "No Content"},
{"205", "Reset Content"},
{"206", "Partial Content"},
{"300", "Multiple Choices"},
{"305", "Use Proxy"},
{"402", "Payment Required"},
{"406", "Not Acceptable"},
{"407", "Proxy Authentication Required"},
{"409", "Conflict"},
{"410", "Gone"},
{"411", "Length Required"},
{"412", "Precondition Failed"},
{"413", "Request Entity Too Large"},
{"414", "Request-URI Too Long"},
{"415", "Unsupported Media Type"},
{"416", "Requested Range Not Satisfiable"},
{"417", "Expectation Failed"},
{"501", "Not Implemented"},
{"502", "Bad Gateway"},
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{ "", NULL },
};
extern struct http_status_codes hsc[];
VALUE rb_uwsgi_io_new(VALUE class, VALUE wr) {
@@ -134,6 +88,7 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
if (RARRAY_LEN(args) == 0) {
chunk = rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, wsgi_req->post_cl-wsgi_req->buf_pos);
wsgi_req->buf_pos += (wsgi_req->post_cl-wsgi_req->buf_pos);
return chunk;
}
else if (RARRAY_LEN(args) > 0) {
@@ -141,11 +96,12 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
if (wsgi_req->buf_pos+chunk_size > wsgi_req->post_cl) {
chunk_size = wsgi_req->post_cl-wsgi_req->buf_pos;
}
wsgi_req->buf_pos+=chunk_size;
if (RARRAY_LEN(args) > 1) {
rb_str_cat(RARRAY_PTR(args)[1], wsgi_req->post_buffering_buf+wsgi_req->buf_pos, chunk_size);
wsgi_req->buf_pos+=chunk_size;
return RARRAY_PTR(args)[1];
}
wsgi_req->buf_pos+=chunk_size;
return rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, chunk_size);
}
@@ -184,6 +140,142 @@ VALUE require_rails(VALUE arg) {
VALUE init_rack_app(VALUE);
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
uint8_t uwsgi_signal = NUM2INT(signum);
if (uwsgi_signal_registered(uwsgi_signal)) {
return Qtrue;
}
return Qfalse;
}
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
uint8_t uwsgi_signal = NUM2INT(signum);
char *signal_kind = RSTRING_PTR(sigkind);
if (uwsgi_register_signal(uwsgi_signal, signal_kind, (void *) rbhandler, 7)) {
rb_raise(rb_eRuntimeError, "unable to register signal %d", uwsgi_signal);
return Qnil;
}
rb_gc_register_address(&rbhandler);
return Qtrue;
}
VALUE uwsgi_ruby_signal(VALUE *class, VALUE signum) {
uint8_t uwsgi_signal = NUM2INT(signum);
ssize_t rlen;
rlen = write(uwsgi.signal_socket, &uwsgi_signal, 1);
if (rlen != 1) {
uwsgi_error("write()");
}
return Qtrue;
}
VALUE rack_call_signal_handler(VALUE args) {
return rb_funcall(rb_ary_entry(args, 0), rb_intern("call"), 1, rb_ary_entry(args, 1));
}
int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
int error = 0;
VALUE rbhandler = (VALUE) handler;
VALUE args = rb_ary_new2(2);
rb_ary_store(args, 0, rbhandler);
VALUE rbsig = INT2NUM(sig);
rb_ary_store(args, 1, rbsig);
VALUE ret = rb_protect(rack_call_signal_handler, args, &error);
if (error) {
uwsgi_ruby_exception();
// free resources (useless ?)
rb_gc_unregister_address(&args);
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&rbsig);
return -1;
}
// free resources (useless ?)
rb_gc_unregister_address(&args);
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&rbsig);
return 0;
}
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
uint8_t uwsgi_signal = NUM2INT(rbsignum);
int minute = NUM2INT(rbmin);
int hour = NUM2INT(rbhour);
int day = NUM2INT(rbday);
int month = NUM2INT(rbmon);
int week = NUM2INT(rbweek);
if (uwsgi_signal_add_cron(uwsgi_signal, minute, hour, day, month, week)) {
rb_raise(rb_eRuntimeError, "unable to add cron");
return Qnil;
}
return Qtrue;
}
VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
uint8_t uwsgi_signal = NUM2INT(rbsignum);
int seconds = NUM2INT(secs);
if (uwsgi_add_timer(uwsgi_signal, seconds)) {
rb_raise(rb_eRuntimeError, "unable to add timer");
return Qnil;
}
return Qtrue;
}
VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
uint8_t uwsgi_signal = NUM2INT(rbsignum);
int seconds = NUM2INT(secs);
if (uwsgi_signal_add_rb_timer(uwsgi_signal, seconds, 0)) {
rb_raise(rb_eRuntimeError, "unable to add rb_timer");
return Qnil;
}
return Qtrue;
}
VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
uint8_t uwsgi_signal = NUM2INT(rbsignum);
char *filename = RSTRING_PTR(rbfilename);
if (uwsgi_add_file_monitor(uwsgi_signal, filename)) {
rb_raise(rb_eRuntimeError, "unable to add file monitor");
return Qnil;
}
return Qtrue;
}
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -251,13 +343,13 @@ int uwsgi_rack_init(){
char **argv = sargv;
#endif
int error;
// filling http status codes
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = (int) strlen(http_sc->message);
}
ur.unprotected = 0;
#ifdef RUBY19
ruby_sysinit(&argc, &argv);
@@ -279,6 +371,20 @@ int uwsgi_rack_init(){
rb_define_module_function(rb_uwsgi_embedded, "wait_fd_read", uwsgi_ruby_wait_fd_read, 2);
rb_define_module_function(rb_uwsgi_embedded, "wait_fd_write", uwsgi_ruby_wait_fd_write, 2);
rb_define_module_function(rb_uwsgi_embedded, "async_connect", uwsgi_ruby_async_connect, 1);
rb_define_module_function(rb_uwsgi_embedded, "signal", uwsgi_ruby_signal, 1);
rb_define_module_function(rb_uwsgi_embedded, "register_signal", uwsgi_ruby_register_signal, 3);
rb_define_module_function(rb_uwsgi_embedded, "signal_registered", uwsgi_ruby_signal_registered, 1);
rb_define_module_function(rb_uwsgi_embedded, "add_cron", rack_uwsgi_add_cron, 6);
rb_define_module_function(rb_uwsgi_embedded, "add_timer", rack_uwsgi_add_timer, 2);
rb_define_module_function(rb_uwsgi_embedded, "add_rb_timer", rack_uwsgi_add_rb_timer, 2);
rb_define_module_function(rb_uwsgi_embedded, "add_file_monitor", rack_uwsgi_add_file_monitor, 2);
return 0;
}
void uwsgi_rack_init_apps(void) {
int error;
if (ur.rack) {
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error);
@@ -287,9 +393,12 @@ int uwsgi_rack_init(){
exit(1);
}
if (ur.dispatcher == Qnil) {
uwsgi_log("unable to find RACK entry point\n");
exit(1);
}
rb_gc_register_address(&ur.dispatcher);
goto ready;
}
else if (ur.rails) {
if (chdir(ur.rails)) {
@@ -312,10 +421,18 @@ int uwsgi_rack_init(){
uwsgi_log("unable to load rails dispatcher\n");
exit(1);
}
goto ready;
}
return;
ready:
ur.call = rb_intern("call");
if (!ur.call) {
uwsgi_log("unable to find RACK entry point\n");
return;
}
rb_gc_register_address(&ur.call);
@@ -330,8 +447,6 @@ int uwsgi_rack_init(){
rb_define_method(ur.rb_uwsgi_io_class, "read", rb_uwsgi_io_read, -2);
rb_define_method(ur.rb_uwsgi_io_class, "rewind", rb_uwsgi_io_rewind, 0);
return 0;
}
VALUE call_dispatch(VALUE env) {
@@ -519,7 +634,21 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
rb_ary_store(rbv, 1, INT2NUM(1));
rb_hash_aset(env, rb_str_new2("rack.version"), rbv);
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
if (wsgi_req->scheme_len > 0) {
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new(wsgi_req->scheme, wsgi_req->scheme_len));
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("https"));
}
else {
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
}
}
else {
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
}
rb_hash_aset(env, rb_str_new2("rack.multithread"), Qfalse);
rb_hash_aset(env, rb_str_new2("rack.multiprocess"), Qtrue);
@@ -623,7 +752,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
wsgi_req->response_size = uwsgi_sendfile(wsgi_req);
if (wsgi_req->response_size > 0) {
while(wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
uwsgi_log("sendfile_fd_size = %d\n", wsgi_req->sendfile_fd_size);
//uwsgi_log("sendfile_fd_size = %d\n", wsgi_req->sendfile_fd_size);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
}
}
@@ -690,11 +819,16 @@ void uwsgi_rack_after_request(struct wsgi_request *wsgi_req) {
int uwsgi_rack_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_RAILS:
// HACK: can be overridden with --post-buffering
if (!uwsgi.post_buffering) uwsgi.post_buffering = 4096;
ur.rails = optarg;
return 1;
case LONG_ARGS_RACK:
// HACK: can be overridden with --post-buffering
if (!uwsgi.post_buffering) uwsgi.post_buffering = 4096;
ur.rack = optarg;
return 1;
case LONG_ARGS_RUBY_GC_FREQ:
@@ -796,6 +930,9 @@ struct uwsgi_plugin rack_plugin = {
.request = uwsgi_rack_request,
.after_request = uwsgi_rack_after_request,
.signal_handler = uwsgi_rack_signal_handler,
.init_apps = uwsgi_rack_init_apps,
//.mount_app = uwsgi_rack_mount_app,
.manage_xml = uwsgi_rack_xml,
+16 -9
View File
@@ -5,9 +5,8 @@ extern struct uwsgi_server uwsgi;
int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
char *argv[0xff];
uint8_t argc;
int i;
char *argv[256];
uint8_t argc = 0xff;
/* Standard RPC request */
if (!wsgi_req->uh.pktsize) {
@@ -15,17 +14,25 @@ int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
return -1;
}
uwsgi_log("parsing array\n");
/*
for(argc=0;argc<wsgi_req->uh.pktsize;argc++) {
uwsgi_log("rpc: %c\n", wsgi_req->buffer[argc]);
}
*/
#ifdef UWSGI_DEBUG
uwsgi_log("RPC pktsize %d\n", wsgi_req->uh.pktsize);
#endif
if (uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
uwsgi_log("Invalid RPC request. skip.\n");
return -1;
}
uwsgi_log("done\n");
for(i=0;i<argc;i++) {
uwsgi_log("arg %d %s\n", i, argv[i]);
}
#ifdef UWSGI_DEBUG
uwsgi_log("RPC args %d\n", argc-1);
#endif
wsgi_req->uh.pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, wsgi_req->buffer);
if (wsgi_req->uh.modifier2 == 0) {
+33
View File
@@ -0,0 +1,33 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
int (*symcall_function)(struct wsgi_request *);
int uwsgi_symcall_init(){
symcall_function = dlsym(RTLD_DEFAULT, "pypy_uwsgi_request");
uwsgi_log("symcall function ptr: %p\n", symcall_function);
return 0;
}
int uwsgi_symcall_request(struct wsgi_request *wsgi_req) {
return symcall_function(wsgi_req);
}
void uwsgi_symcall_after_request(struct wsgi_request *wsgi_req) {
// TODO
}
struct uwsgi_plugin symcall_plugin = {
.name = "symcall",
.modifier1 = 18,
.init = uwsgi_symcall_init,
.request = uwsgi_symcall_request,
.after_request = uwsgi_symcall_after_request,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='symcall'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['symcall_plugin']
+2 -2
View File
@@ -254,7 +254,7 @@ ssize_t uwsgi_proto_fastcgi_sendfile(struct wsgi_request *wsgi_req) {
return -1;
}
len = read(wsgi_req->sendfile_fd, buf, ntohs(fr.cl));
if (len != ntohs(fr.cl)) {
if (len != (ssize_t) ntohs(fr.cl)) {
uwsgi_error("read()");
return -1;
}
@@ -270,7 +270,7 @@ ssize_t uwsgi_proto_fastcgi_sendfile(struct wsgi_request *wsgi_req) {
return -1;
}
len = read(wsgi_req->sendfile_fd, buf, ntohs(fr.cl));
if (len != ntohs(fr.cl)) {
if (len != (ssize_t) ntohs(fr.cl)) {
uwsgi_error("read()");
return -1;
}
+33 -2
View File
@@ -42,6 +42,14 @@ static uint16_t http_add_uwsgi_header(struct wsgi_request *wsgi_req, char *hh, i
if (uwsgi_strncmp("CONTENT_TYPE", 12, hh, keylen) && uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
keylen += 5;
prefix = 1;
if (!uwsgi_strncmp("IF_MODIFIED_SINCE", 17, hh, keylen)) {
wsgi_req->if_modified_since = val;
wsgi_req->if_modified_since_len = vallen;
}
else if (uwsgi.vhost_host && !uwsgi_strncmp("HOST", 4, hh, keylen)) {
wsgi_req->host = val;
wsgi_req->host_len = vallen;
}
}
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
wsgi_req->post_cl = uwsgi_str_num(val, vallen);
@@ -96,6 +104,8 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
while (ptr < watermark) {
if (*ptr == ' ') {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_METHOD", 14, base, ptr - base);
wsgi_req->method = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->method_len = ptr - base;
ptr++;
break;
}
@@ -107,16 +117,25 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
while (ptr < watermark) {
if (*ptr == '?' && !query_string) {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->path_info_len = ptr - base;
query_string = ptr + 1;
}
else if (*ptr == ' ') {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, base, ptr - base);
wsgi_req->uri = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->uri_len = ptr - base;
if (!query_string) {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->path_info_len = ptr - base;
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
}
else {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, query_string, ptr - query_string);
wsgi_req->query_string = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - query_string);
wsgi_req->query_string_len = ptr - query_string;
}
ptr++;
break;
@@ -133,6 +152,8 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
if (*(ptr + 1) != '\n')
return 0;
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PROTOCOL", 15, base, ptr - base);
wsgi_req->protocol = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->protocol_len = ptr - base;
ptr += 2;
break;
}
@@ -144,14 +165,24 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
// SERVER_NAME
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len);
wsgi_req->host = uwsgi.hostname;
wsgi_req->host_len = uwsgi.hostname_len;
// SERVER_PORT
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "3031", 4);
char *server_port = strchr(wsgi_req->socket->name, ':');
if (server_port) {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, server_port+1, strlen(server_port+1));
}
else {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
}
// REMOTE_ADDR
memset(ip, 0, INET_ADDRSTRLEN+1);
if (inet_ntop(AF_INET, (void *) &http_sin->sin_addr.s_addr, ip, INET_ADDRSTRLEN)) {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, ip, strlen(ip));
wsgi_req->remote_addr = (wsgi_req->buffer + wsgi_req->uh.pktsize) - strlen(ip);
wsgi_req->remote_addr_len = strlen(ip);
}
else {
uwsgi_error("inet_ntop()");
@@ -253,7 +284,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
remains = len - (j + 1);
http_parse(wsgi_req, ptr);
//is there a Content_Length ?
if (wsgi_req->post_cl) {
if (wsgi_req->post_cl > 0) {
wsgi_req->async_post = tmpfile();
if (!wsgi_req->async_post) {
free(wsgi_req->proto_parser_buf);
+1 -1
View File
@@ -56,7 +56,7 @@ int uwsgi_proto_uwsgi_parser(struct wsgi_request *wsgi_req) {
/* check for max buffer size */
if (wsgi_req->uh.pktsize > uwsgi.buffer_size) {
uwsgi_log("invalid request block size: %d...skip\n", wsgi_req->uh.pktsize);
uwsgi_log("invalid request block size: %d (max %d)...skip\n", wsgi_req->uh.pktsize, uwsgi.buffer_size);
return -1;
}
-1
View File
@@ -454,7 +454,6 @@ ssize_t uwsgi_proto_zeromq_sendfile(struct wsgi_request * wsgi_req) {
wsgi_req->sendfile_fd_chunk = 65536;
if (uwsgi.async > 1) {
len = read(wsgi_req->sendfile_fd, buf, UMIN(remains, wsgi_req->sendfile_fd_chunk));
if (len != (int) UMIN(remains, wsgi_req->sendfile_fd_chunk)) {
+150 -25
View File
@@ -173,6 +173,8 @@ ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t
}
close(fd);
udp_port[0] = ':';
return ret;
}
@@ -339,7 +341,7 @@ ssize_t uwsgi_send_message(int fd, uint8_t modifier1, uint8_t modifier2, char *m
}
int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header *uh, char *buffer, int (*socket_proto)(struct wsgi_request *)) {
int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
int rlen;
int status = UWSGI_AGAIN;
@@ -347,7 +349,7 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
timeout = 1;
while(status == UWSGI_AGAIN) {
rlen = poll(upoll, 1, timeout * 1000);
rlen = poll(&wsgi_req->poll, 1, timeout * 1000);
if (rlen < 0) {
uwsgi_error("poll()");
exit(1);
@@ -357,7 +359,12 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
//close(upoll->fd);
return 0;
}
status = socket_proto((struct wsgi_request *) uh);
if (wsgi_req->socket) {
status = wsgi_req->socket->proto(wsgi_req);
}
else {
status = uwsgi_proto_uwsgi_parser(wsgi_req);
}
if (status < 0) {
uwsgi_log("error parsing request\n");
//close(upoll->fd);
@@ -393,11 +400,12 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
if (ptrbuf + strsize <= bufferend) {
// item
argv[*argc] = uwsgi_cheap_string(ptrbuf, strsize);
uwsgi_log("arg %s\n", argv[*argc]);
ptrbuf += strsize;
*argc = *argc + 1;
}
else {
uwsgi_log( "invalid uwsgi array. skip this request.\n");
uwsgi_log( "invalid uwsgi array. skip this var.\n");
return -1;
}
}
@@ -411,6 +419,73 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
return 0;
}
int uwsgi_simple_parse_vars(struct wsgi_request *wsgi_req, char *ptrbuf, char *bufferend) {
uint16_t strsize;
while (ptrbuf < bufferend) {
if (ptrbuf + 2 < bufferend) {
memcpy(&strsize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
strsize = uwsgi_swap16(strsize);
#endif
/* key cannot be null */
if (!strsize) {
uwsgi_log( "uwsgi key cannot be null. skip this request.\n");
return -1;
}
ptrbuf += 2;
if (ptrbuf + strsize < bufferend) {
// var key
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
ptrbuf += strsize;
// value can be null (even at the end) so use <=
if (ptrbuf + 2 <= bufferend) {
memcpy(&strsize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
strsize = uwsgi_swap16(strsize);
#endif
ptrbuf += 2;
if (ptrbuf + strsize <= bufferend) {
if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this header.\n");
return -1;
}
// var value
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this var.\n");
return -1;
}
ptrbuf += strsize;
}
else {
uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
return -1;
}
}
else {
uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
return -1;
}
}
}
}
return 0;
}
int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
char *buffer = wsgi_req->buffer;
@@ -425,6 +500,13 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
/* set an HTTP 500 status as default */
wsgi_req->status = 500;
// has the protocol already parsed the request ?
if (wsgi_req->uri_len > 0) {
i = uwsgi_simple_parse_vars(wsgi_req, ptrbuf, bufferend);
if (i == 0) goto next;
return i;
}
while (ptrbuf < bufferend) {
if (ptrbuf + 2 < bufferend) {
@@ -434,7 +516,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
#endif
/* key cannot be null */
if (!strsize) {
uwsgi_log( "uwsgi key cannot be null. skip this request.\n");
uwsgi_log( "uwsgi key cannot be null. skip this var.\n");
return -1;
}
@@ -500,14 +582,17 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
else if (!uwsgi_strncmp("UWSGI_SCRIPT", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len )) {
wsgi_req->script = ptrbuf;
wsgi_req->script_len = strsize;
wsgi_req->dynamic = 1;
}
else if (!uwsgi_strncmp("UWSGI_MODULE", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->module = ptrbuf;
wsgi_req->module_len = strsize;
wsgi_req->dynamic = 1;
}
else if (!uwsgi_strncmp("UWSGI_CALLABLE", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->callable = ptrbuf;
wsgi_req->callable_len = strsize;
wsgi_req->dynamic = 1;
}
else if (!uwsgi_strncmp("UWSGI_PYHOME", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->pyhome = ptrbuf;
@@ -517,9 +602,14 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->chdir = ptrbuf;
wsgi_req->chdir_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_APPID", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->appid = ptrbuf;
wsgi_req->appid_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_FILE", 10, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->file = ptrbuf;
wsgi_req->file_len = strsize;
wsgi_req->dynamic = 1;
}
else if (!uwsgi_strncmp("UWSGI_TOUCH_RELOAD", 18, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->touch_reload = ptrbuf;
@@ -562,6 +652,10 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->if_modified_since = ptrbuf;
wsgi_req->if_modified_since_len = strsize;
}
else if (!uwsgi_strncmp("CONTENT_TYPE", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->content_type = ptrbuf;
wsgi_req->content_type_len = strsize;
}
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->post_cl = get_content_length(ptrbuf, strsize);
if (uwsgi.limit_post) {
@@ -577,7 +671,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this header.\n");
uwsgi_log( "max vec size reached. skip this var.\n");
return -1;
}
// var value
@@ -588,7 +682,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this header.\n");
uwsgi_log( "max vec size reached. skip this var.\n");
return -1;
}
ptrbuf += strsize;
@@ -610,6 +704,8 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
}
}
next:
if (uwsgi.post_buffering > 0 && !wsgi_req->body_as_file && !wsgi_req->async_post) {
// read to disk if post_cl > post_buffering (it will eventually do upload progress...)
if (wsgi_req->post_cl >= (size_t) uwsgi.post_buffering) {
@@ -621,7 +717,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
}
// on tiny post use memory
else {
if (!uwsgi_read_whole_body_in_mem(wsgi_req, wsgi_req->post_buffering_buf)) {
if (!uwsgi_read_whole_body_in_mem(wsgi_req, uwsgi.mem_post_buf[wsgi_req->async_id], uwsgi.post_buffering)) {
wsgi_req->status = -1;
return -1;
}
@@ -653,7 +749,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
}
if (uwsgi.manage_script_name) {
if (uwsgi.apps_cnt > 0 && wsgi_req->path_info_len > 1) {
if (uwsgi_apps_cnt > 0 && wsgi_req->path_info_len > 1) {
// starts with 1 as the 0 app is the default (/) one
int best_found = 0;
char *orig_path_info = wsgi_req->path_info;
@@ -661,7 +757,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
// if SCRIPT_NAME is not allocated, add a slot for it
if (script_name == -1) {
if (wsgi_req->var_cnt >= uwsgi.vec_size - (4 + 2)) {
uwsgi_log( "max vec size reached. skip this header.\n");
uwsgi_log( "max vec size reached. skip this var.\n");
return -1;
}
wsgi_req->var_cnt++;
@@ -670,13 +766,13 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->var_cnt++;
script_name = wsgi_req->var_cnt;
}
for(i=0;i<uwsgi.apps_cnt;i++) {
for(i=0;i<uwsgi_apps_cnt;i++) {
//uwsgi_log("app mountpoint = %.*s\n", uwsgi.apps[i].mountpoint_len, uwsgi.apps[i].mountpoint);
if (orig_path_info_len >= uwsgi.apps[i].mountpoint_len) {
if (!uwsgi_startswith(orig_path_info, uwsgi.apps[i].mountpoint, uwsgi.apps[i].mountpoint_len) && uwsgi.apps[i].mountpoint_len > best_found) {
best_found = uwsgi.apps[i].mountpoint_len;
wsgi_req->script_name = uwsgi.apps[i].mountpoint;
wsgi_req->script_name_len = uwsgi.apps[i].mountpoint_len;
if (orig_path_info_len >= uwsgi_apps[i].mountpoint_len) {
if (!uwsgi_startswith(orig_path_info, uwsgi_apps[i].mountpoint, uwsgi_apps[i].mountpoint_len) && uwsgi_apps[i].mountpoint_len > best_found) {
best_found = uwsgi_apps[i].mountpoint_len;
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
wsgi_req->path_info = orig_path_info+wsgi_req->script_name_len;
wsgi_req->path_info_len = orig_path_info_len-wsgi_req->script_name_len;
@@ -754,7 +850,7 @@ int uwsgi_ping_node(int node, struct wsgi_request *wsgi_req) {
}
uwsgi_poll.events = POLLIN;
if (!uwsgi_parse_response(&uwsgi_poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) wsgi_req, wsgi_req->buffer, uwsgi_proto_uwsgi_parser)) {
if (!uwsgi_parse_packet(wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
return -1;
}
@@ -819,7 +915,9 @@ int uwsgi_get_dgram(int fd, struct wsgi_request *wsgi_req) {
return -1;
}
uwsgi_log("recevied request from %s\n", inet_ntoa(sin.sin_addr));
#ifdef UWSGI_DEBUG
uwsgi_log("received request from %s\n", inet_ntoa(sin.sin_addr));
#endif
if (rlen < 4) {
uwsgi_log("invalid uwsgi packet\n");
@@ -843,7 +941,9 @@ int uwsgi_get_dgram(int fd, struct wsgi_request *wsgi_req) {
wsgi_req->buffer = buffer+4;
#ifdef UWSGI_DEBUG
uwsgi_log("request received %d %d\n", wsgi_req->uh.modifier1, wsgi_req->uh.modifier2);
#endif
return 0;
@@ -909,20 +1009,27 @@ int uwsgi_hooked_parse_dict_dgram(int fd, char *buffer, size_t len, uint8_t modi
return -1;
}
uwsgi_log("recevied request from %s\n", inet_ntoa(sin.sin_addr));
#ifdef UWSGI_DEBUG
uwsgi_log("RLEN: %d\n", rlen);
#endif
// check for valid dict 4(header) 2(non-zero key)+1 2(value)
if (rlen < (4+2+1+2)) {
#ifdef UWSGI_DEBUG
uwsgi_log("invalid uwsgi dictionary\n");
#endif
return -1;
}
uwsgi_log("received message from %s\n", inet_ntoa(sin.sin_addr));
uh = (struct uwsgi_header *) buffer;
if (uh->modifier1 != modifier1 || uh->modifier2 != modifier2) {
#ifdef UWSGI_DEBUG
uwsgi_log("invalid uwsgi dictionary received, modifier1: %d modifier2: %d\n", uh->modifier1, uh->modifier2);
#endif
return -1;
}
@@ -942,7 +1049,9 @@ int uwsgi_hooked_parse_dict_dgram(int fd, char *buffer, size_t len, uint8_t modi
}
#ifdef UWSGI_DEBUG
uwsgi_log("%p %p %d\n", ptrbuf, bufferend, bufferend-ptrbuf);
#endif
uwsgi_hooked_parse(ptrbuf, bufferend-ptrbuf, hook, data);
@@ -1096,8 +1205,7 @@ uint16_t fcgi_get_record(int fd, char *buf) {
char *uwsgi_simple_message_string(char *socket_name, uint8_t modifier1, uint8_t modifier2, char *what, uint16_t what_len, char *buffer, uint16_t *response_len, int timeout) {
struct uwsgi_header uh;
struct pollfd upoll;
struct wsgi_request msg_req;
int fd = uwsgi_connect(socket_name, timeout, 0);
@@ -1112,19 +1220,22 @@ char *uwsgi_simple_message_string(char *socket_name, uint8_t modifier1, uint8_t
return NULL;
}
upoll.fd = fd;
upoll.events = POLLIN;
memset(&msg_req, 0, sizeof(struct wsgi_request));
msg_req.poll.fd = fd;
msg_req.poll.events = POLLIN;
msg_req.buffer = buffer;
if (buffer) {
if (!uwsgi_parse_response(&upoll, timeout, &uh, buffer, uwsgi_proto_uwsgi_parser)) {
if (!uwsgi_parse_packet(&msg_req, timeout)) {
close(fd);
if (response_len) *response_len = 0;
return NULL;
}
if (response_len) *response_len = msg_req.uh.pktsize;
}
close(fd);
if (response_len) *response_len = uh.pktsize;
return buffer;
}
@@ -1314,3 +1425,17 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
}
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t *len) {
int i;
*len = 0;
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
if (!uwsgi_strncmp(key, strlen(key), wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
*len = wsgi_req->hvec[i + 1].iov_len;
return wsgi_req->hvec[i + 1].iov_base;
}
}
return NULL;
}
+5
View File
@@ -7,6 +7,11 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
struct uwsgi_rpc *urpc;
int ret = -1;
if (uwsgi.mywid != 0) {
uwsgi_log("you can register RPC functions only in the master\n");
return -1;
}
uwsgi_lock(uwsgi.rpc_table_lock);
if (uwsgi.shared->rpc_count < MAX_RPC) {
+14
View File
@@ -0,0 +1,14 @@
from threading import Thread
import time
def mess():
while True:
for i in xrange(0, 100):
print(i)
time.sleep(0.1)
t = Thread(target=mess)
t.daemon = True
t.start()
print("thread started")
+2
View File
@@ -76,7 +76,9 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
}
if (sf_ret) {
#ifdef UWSGI_DEBUG
uwsgi_log("sf_len = %d\n", sf_len);
#endif
uwsgi_error("sendfile()");
return 0;
}
+36 -10
View File
@@ -11,10 +11,18 @@ int uwsgi_signal_handler(uint8_t sig) {
if (!uwsgi.p[use->modifier1]->signal_handler) {
return -1;
}
return uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
}
int uwsgi_signal_registered(uint8_t sig) {
if (uwsgi.shared->signal_table[sig].handler != NULL)
return 1;
return 0;
}
int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t modifier1) {
struct uwsgi_signal_entry *use = NULL;
@@ -146,6 +154,7 @@ int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
void uwsgi_route_signal(uint8_t sig) {
int i;
struct uwsgi_signal_entry *use = &ushared->signal_table[sig];
// send to first available worker
if (use->receiver[0] == 0 || !strcmp(use->receiver, "worker") || !strcmp(use->receiver, "worker0")) {
@@ -156,21 +165,38 @@ void uwsgi_route_signal(uint8_t sig) {
}
// send to all workers
else if (!strcmp(use->receiver, "workers")) {
if (write(ushared->worker_signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to workers pool\n", sig);
for(i=1;i<=uwsgi.numproc;i++) {
if (write(uwsgi.signal_pipe[i][0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
}
}
// route to specific worker
else if (!strncmp(use->receiver, "worker", 6)) {
i = atoi(use->receiver+6);
if (i > uwsgi.numproc) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
if (write(uwsgi.signal_pipe[i][0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
}
// route to subscribed
else if (!strcmp(use->receiver, "subscribed")) {
}
// route to spooler
else if (!strcmp(use->receiver, "spooler")) {
if (ushared->worker_signal_pipe[0] != -1) {
if (write(ushared->spooler_signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to the spooler\n", sig);
}
}
}
else {
// unregistered signal, sending it to all the workers
uwsgi_log("^^^ ROUTING UNREGISTERED SIGNAL ^^^\n");
if (write(ushared->worker_signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to workers pool\n", sig);
}
uwsgi_log("^^^ UNSUPPORTED SIGNAL TARGET: %s ^^^\n", use->receiver);
}
}
+28
View File
@@ -0,0 +1,28 @@
import uwsgi
from uwsgidecorators import *
@signal(17, target='workers')
def hello(signum):
print("I AM THE WORKER %d" % uwsgi.worker_id())
@signal(30, target='worker2')
def hello2(signum):
print("I AM THE WORKER 2")
@postfork
def wait_for_signal():
if uwsgi.worker_id() != 2:
print("waiting for a signal...")
uwsgi.signal_wait()
print("signal %d received" % uwsgi.signal_received())
def application(e, s):
s('200 OK', [('Content-Type', 'text/html')])
if e['PATH_INFO'] == '/30':
uwsgi.signal(30)
uwsgi.signal(100)
else:
uwsgi.signal(17)
return "Signal raised"
+121
View File
@@ -53,6 +53,10 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
len = strlen(socket_name+1) + 1;
}
else if (abstract_socket) {
memcpy(uws_addr->sun_path + 1, socket_name, UMIN(strlen(socket_name), 101));
len = strlen(socket_name)+1;
}
else {
memcpy(uws_addr->sun_path + abstract_socket, socket_name, UMIN(strlen(socket_name), 102));
len = strlen(socket_name);
@@ -380,7 +384,10 @@ char *generate_socket_name(char *socket_name) {
uwsgi_log("your system does not support ifaddrs subsystem\n");
#else
char *new_socket;
#ifdef UWSGI_DEBUG
uwsgi_log("generate_socket_name(%s)\n", socket_name);
#endif
// get all the AF_INET addresses available
struct ifaddrs *ifap = NULL, *ifa, *ifaf;
if (getifaddrs(&ifap)) {
@@ -391,7 +398,9 @@ char *generate_socket_name(char *socket_name) {
// here socket_name will be truncated
asterisk[0] = 0;
#ifdef UWSGI_DEBUG
uwsgi_log("asterisk found\n");
#endif
char new_addr[16];
struct sockaddr_in *sin;
@@ -491,6 +500,28 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
uwsgi_nuclear_blast();
}
#ifdef __linux__
#ifdef IP_FREEBIND
if (uwsgi.freebind) {
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
uwsgi_nuclear_blast();
}
}
#endif
#endif
if (uwsgi.reuse_port) {
#ifdef SO_REUSEPORT
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
uwsgi_nuclear_blast();
}
#else
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
#endif
}
if (!uwsgi.no_defer_accept) {
#ifdef __linux__
@@ -624,6 +655,17 @@ int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_s
}
int uwsgi_count_sockets(struct uwsgi_socket *uwsgi_sock) {
int count = 0;
while(uwsgi_sock) {
count++;
uwsgi_sock = uwsgi_sock->next;
}
return count;
}
int uwsgi_get_socket_num(struct uwsgi_socket *uwsgi_sock) {
int count = 0;
@@ -685,6 +727,8 @@ struct uwsgi_socket *uwsgi_new_shared_socket(char *name) {
struct uwsgi_socket *uwsgi_new_socket(char *name) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets, *old_uwsgi_sock;
struct sockaddr_in sin;
socklen_t socket_type_len;
if (!uwsgi_sock) {
uwsgi.sockets = uwsgi_malloc(sizeof(struct uwsgi_socket));
@@ -702,6 +746,49 @@ struct uwsgi_socket *uwsgi_new_socket(char *name) {
memset(uwsgi_sock, 0, sizeof(struct uwsgi_socket));
uwsgi_sock->name = name;
if (!name) return uwsgi_sock;
char *tcp_port = strchr(name, ':');
if (tcp_port) {
// INET socket, check for 0 port
if (tcp_port[1] == 0 || tcp_port[1] == '0') {
uwsgi_sock->fd = bind_to_tcp(name, uwsgi.listen_queue, tcp_port);
uwsgi_sock->family = AF_INET;
uwsgi_sock->bound = 1;
uwsgi_sock->auto_port = 1;
socket_type_len = sizeof(struct sockaddr_in);
if (getsockname(uwsgi_sock->fd, (struct sockaddr *)&sin, &socket_type_len)) {
uwsgi_error("getsockname()");
exit(1);
}
char *auto_port = uwsgi_num2str(ntohs(sin.sin_port));
uwsgi_sock->name = uwsgi_concat3n(name, tcp_port-name, ":", 1, auto_port, strlen(auto_port));
}
// is it fd 0 ?
else if (tcp_port[1] == ':') {
uwsgi_sock->fd = 0;
uwsgi_sock->family = AF_INET;
uwsgi_sock->bound = 1;
socket_type_len = sizeof(struct sockaddr_in);
if (getsockname(0, (struct sockaddr *)&sin, &socket_type_len)) {
uwsgi_error("getsockname()");
exit(1);
}
char *auto_port = uwsgi_num2str(ntohs(sin.sin_port));
char *auto_ip = inet_ntoa(sin.sin_addr);
uwsgi_sock->name = uwsgi_concat3n(auto_ip, strlen(auto_ip), ":", 1, auto_port, strlen(auto_port));
}
}
return uwsgi_sock;
}
@@ -713,6 +800,10 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
union uwsgi_sockaddr usa;
int abstract = 0;
#ifdef UWSGI_DEBUG
uwsgi_log("creating socket from fd %d\n", fd);
#endif
socket_type_len = sizeof(struct sockaddr_un);
gsa.sa = &usa.sa;
if (!getsockname(fd, gsa.sa, &socket_type_len)) {
@@ -722,6 +813,20 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
}
if (gsa.sa->sa_family == AF_UNIX) {
if (usa.sa_un.sun_path[0] == 0) abstract = 1;
// is it a zerg ?
if (uwsgi_sock->name == NULL) {
uwsgi_sock->fd = fd;
uwsgi_sock->family = AF_UNIX;
uwsgi_sock->bound = 1;
uwsgi_sock->name = uwsgi_concat2(usa.sa_un.sun_path+abstract, "");
if (uwsgi.zerg) {
uwsgi_log("uwsgi zerg socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path+abstract, uwsgi_sock->fd);
}
else {
uwsgi_log("uwsgi socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path+abstract, uwsgi_sock->fd);
}
return;
}
if (!strcmp(usa.sa_un.sun_path+abstract, uwsgi_sock->name+abstract)) {
uwsgi_sock->fd = fd;
uwsgi_sock->family = AF_UNIX;
@@ -747,6 +852,22 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
else {
computed_addr = uwsgi_concat3(ipv4a, ":", computed_port);
}
// is it a zerg ?
if (uwsgi_sock->name == NULL) {
uwsgi_sock->fd = fd;
uwsgi_sock->family = AF_INET;
uwsgi_sock->bound = 1;
uwsgi_sock->name = uwsgi_concat2(computed_addr, "");
if (uwsgi.zerg) {
uwsgi_log("uwsgi zerg socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd);
}
else {
uwsgi_log("uwsgi socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd);
}
free(computed_addr);
return;
}
char *asterisk = strchr(uwsgi_sock->name, '*');
int match = 1;
if (asterisk) {
+300 -98
View File
@@ -3,7 +3,29 @@
extern struct uwsgi_server uwsgi;
static void spooler_readdir(char *);
#ifdef __linux__
static void spooler_scandir(char *);
#endif
void spooler_manage_task(char *, char *);
// fake function to allow waking the spooler
void spooler_wakeup() {}
pid_t spooler_start() {
int i;
if (uwsgi.master_process) {
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
if (uwsgi.shared->spooler_signal_pipe[1] != -1) close (uwsgi.shared->spooler_signal_pipe[1]);
// setup internal signalling system
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->spooler_signal_pipe)) {
uwsgi_error("socketpair()\n");
exit(1);
}
}
pid_t pid = fork();
if (pid < 0) {
@@ -11,21 +33,56 @@ pid_t spooler_start() {
exit(1);
}
else if (pid == 0) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
close(uwsgi_sock->fd);
uwsgi_sock = uwsgi_sock->next;
// USR1 will be used to wake up the spooler
signal(SIGUSR1, spooler_wakeup);
uwsgi.mywid = -1;
uwsgi.mypid = pid;
uwsgi_close_all_sockets();
if (uwsgi.master_process) {
close(uwsgi.shared->spooler_signal_pipe[0]);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.signal_pipe[i][0] != -1) {
close(uwsgi.signal_pipe[i][0]);
}
}
}
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->spooler_init) {
uwsgi.gp[i]->spooler_init();
}
}
spooler();
}
else if (pid > 0) {
if (uwsgi.master_process) {
close(uwsgi.shared->spooler_signal_pipe[1]);
}
uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uwsgi.spool_dir, pid);
}
return pid;
}
void destroy_spool(char *file) {
void destroy_spool(char *dir, char *file) {
if (chdir(dir)) {
uwsgi_error("chdir()");
uwsgi_log("something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
if (unlink(file)) {
uwsgi_error("unlink()");
@@ -36,7 +93,7 @@ void destroy_spool(char *file) {
}
int spool_request(char *filename, int rn, int core_id, char *buffer, int size) {
int spool_request(char *filename, int rn, int core_id, char *buffer, int size, char *priority, time_t at, char *body, size_t body_len) {
struct timeval tv;
int fd;
@@ -46,9 +103,24 @@ int spool_request(char *filename, int rn, int core_id, char *buffer, int size) {
gettimeofday(&tv, NULL);
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uwsgi.spool_dir, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
uwsgi_unlock(uwsgi.spooler_lock);
return 0;
if (priority) {
if (snprintf(filename, 1024, "%s/%s", uwsgi.spool_dir, priority) <= 0) {
uwsgi_unlock(uwsgi.spooler_lock);
return 0;
}
// no need to check for errors...
(void) mkdir(filename, 0777);
if (snprintf(filename, 1024, "%s/%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uwsgi.spool_dir, priority, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
uwsgi_unlock(uwsgi.spooler_lock);
return 0;
}
}
else {
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uwsgi.spool_dir, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
uwsgi_unlock(uwsgi.spooler_lock);
return 0;
}
}
fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
@@ -85,19 +157,47 @@ int spool_request(char *filename, int rn, int core_id, char *buffer, int size) {
goto clear;
}
if (body && body_len > 0) {
if ((size_t)write(fd, body, body_len) != body_len) {
goto clear;
}
}
if (at > 0) {
struct timeval tv[2];
tv[0].tv_sec = at;
tv[0].tv_usec = 0;
tv[1].tv_sec = at;
tv[1].tv_usec = 0;
#ifdef __sun__
if (futimesat(fd, NULL, tv)) {
#else
if (futimes(fd, tv)) {
#endif
uwsgi_error("futimes()");
}
}
close(fd);
uwsgi_log("written %d bytes to spool file %s\n", size + 4, filename);
uwsgi_log("written %d bytes to spool file %s\n", size + body_len + 4, filename);
uwsgi_unlock(uwsgi.spooler_lock);
/* wake up the spooler ... (HACKY) */
if (uwsgi.shared->spooler_pid > 0 ) {
(void) kill(uwsgi.shared->spooler_pid, SIGUSR1);
}
return 1;
clear:
uwsgi_unlock(uwsgi.spooler_lock);
uwsgi_error("write()");
unlink(filename);
if (unlink(filename)) {
uwsgi_error("unlink()");
}
close(fd);
return 0;
}
@@ -105,25 +205,10 @@ int spool_request(char *filename, int rn, int core_id, char *buffer, int size) {
void spooler() {
DIR *sdir;
struct dirent *dp;
int i, ret;
int spool_fd;
// prevent process blindly reading stdin to make mess
int nullfd;
struct uwsgi_header uh;
char spool_buf[0xffff];
if (chdir(uwsgi.spool_dir)) {
uwsgi_error("chdir()");
exit(1);
}
// asked by Marco Beri
#ifdef __HAIKU__
#ifdef UWSGI_DEBUG
@@ -148,85 +233,203 @@ void spooler() {
close(nullfd);
}
int spooler_event_queue = event_queue_init();
int interesting_fd = -1;
if (uwsgi.master_process) {
event_queue_add_fd_read(spooler_event_queue, uwsgi.shared->spooler_signal_pipe[1]);
}
for (;;) {
sleep(uwsgi.shared->spooler_frequency);
sdir = opendir(uwsgi.spool_dir);
if (sdir) {
while ((dp = readdir(sdir)) != NULL) {
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19)) {
struct stat sf_lstat;
if (lstat(dp->d_name, &sf_lstat)) {
continue;
}
if (!S_ISREG(sf_lstat.st_mode)) {
continue;
}
if (!access(dp->d_name, R_OK | W_OK)) {
uwsgi_log("managing spool request %s ...\n", dp->d_name);
if (chdir(uwsgi.spool_dir)) {
uwsgi_error("chdir()");
exit(1);
}
spool_fd = open(dp->d_name, O_RDONLY);
if (spool_fd < 0) {
uwsgi_error_open(dp->d_name);
continue;
}
#ifdef __sun__
if (lockf(spool_fd, F_LOCK, 0)) {
uwsgi_error("lockf()");
#else
if (flock(spool_fd, LOCK_EX)) {
uwsgi_error("flock()");
if (uwsgi.spooler_ordered) {
#ifdef __linux__
spooler_scandir(uwsgi.spool_dir);
#endif
close(spool_fd);
continue;
}
if (read(spool_fd, &uh, 4) != 4) {
uwsgi_error("read()");
close(spool_fd);
continue;
}
#ifdef __BIG_ENDIAN__
uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif
if (read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
uwsgi_error("read()");
destroy_spool(dp->d_name);
close(spool_fd);
continue;
}
close(spool_fd);
for(i=0;i<0xff;i++) {
if (uwsgi.p[i]->spooler) {
ret = uwsgi.p[i]->spooler(spool_buf, uh.pktsize);
if (ret == 0) continue;
if (ret == -2) {
uwsgi_log("done with task/spool %s\n", dp->d_name);
destroy_spool(dp->d_name);
}
// re-spool it
break;
}
}
}
}
}
closedir(sdir);
}
else {
uwsgi_error("opendir()");
spooler_readdir(uwsgi.spool_dir);
}
if (event_queue_wait(spooler_event_queue, uwsgi.shared->spooler_frequency, &interesting_fd) > 0) {
if (uwsgi.master_process) {
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[1]) {
uint8_t uwsgi_signal;
if (read(interesting_fd, &uwsgi_signal, 1) <= 0) {
uwsgi_log_verbose("uWSGI spooler screams: UAAAAAAH my master died, i will follow him...\n");
end_me(0);
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to the spooler\n", uwsgi_signal);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on the spooler\n", uwsgi_signal);
}
}
}
}
}
}
}
#ifdef __linux__
static void spooler_scandir(char *dir) {
struct dirent **tasklist;
int n;
n = scandir(dir, &tasklist, 0, versionsort);
if (n < 0) {
uwsgi_error("scandir()");
return;
}
while(n--) {
spooler_manage_task(dir, tasklist[n]->d_name);
free(tasklist[n]);
}
free(tasklist);
}
#endif
static void spooler_readdir(char *dir) {
DIR *sdir;
struct dirent *dp;
sdir = opendir(dir);
if (sdir) {
while ((dp = readdir(sdir)) != NULL) {
spooler_manage_task(dir, dp->d_name);
}
closedir(sdir);
}
else {
uwsgi_error("opendir()");
}
}
void spooler_manage_task(char *dir, char *task) {
int i, ret;
char spool_buf[0xffff];
struct uwsgi_header uh;
char *body = NULL;
size_t body_len = 0;
int spool_fd;
if (!strncmp("uwsgi_spoolfile_on_", task, 19) || (uwsgi.spooler_ordered && is_a_number(task))) {
struct stat sf_lstat;
if (lstat(task, &sf_lstat)) {
return;
}
// a spool request for the future
if (sf_lstat.st_mtime > time(NULL)) {
return;
}
#ifdef __linux__
if (S_ISDIR(sf_lstat.st_mode) && uwsgi.spooler_ordered) {
if (chdir(task)) {
uwsgi_error("chdir()");
return;
}
char *prio_path = realpath(".", NULL);
spooler_scandir(prio_path);
free(prio_path);
if (chdir(dir)) {
uwsgi_error("chdir()");
}
return;
}
#endif
if (!S_ISREG(sf_lstat.st_mode)) {
return;
}
if (!access(task, R_OK | W_OK)) {
uwsgi_log("managing spool request %s ...\n", task);
spool_fd = open(task, O_RDONLY);
if (spool_fd < 0) {
uwsgi_error_open(task);
return;
}
#ifdef __sun__
if (lockf(spool_fd, F_LOCK, 0)) {
uwsgi_error("lockf()");
#else
if (flock(spool_fd, LOCK_EX)) {
uwsgi_error("flock()");
#endif
close(spool_fd);
return;
}
if (read(spool_fd, &uh, 4) != 4) {
uwsgi_error("read()");
close(spool_fd);
return;
}
#ifdef __BIG_ENDIAN__
uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif
if (read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
uwsgi_error("read()");
destroy_spool(dir, task);
close(spool_fd);
return;
}
// body available ?
if (sf_lstat.st_size > (uh.pktsize+4)) {
body_len = sf_lstat.st_size - (uh.pktsize+4);
body = uwsgi_malloc(body_len);
if ((size_t)read(spool_fd, body, body_len) != body_len) {
uwsgi_error("read()");
destroy_spool(dir, task);
close(spool_fd);
free(body);
return;
}
}
close(spool_fd);
for(i=0;i<0xff;i++) {
if (uwsgi.p[i]->spooler) {
time_t now = time(NULL);
ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
if (body) {
free(body);
}
if (ret == 0) continue;
if (ret == -2) {
uwsgi_log("done with task/spool %s after %d seconds\n", task, time(NULL)-now);
destroy_spool(dir, task);
}
// re-spool it
break;
}
}
}
}
}
@@ -242,8 +445,7 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
return -1;
}
uwsgi_log("managing spool request...\n");
i = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, wsgi_req->buffer, wsgi_req->uh.pktsize);
i = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, wsgi_req->buffer, wsgi_req->uh.pktsize, NULL, 0, NULL, 0);
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
if (i > 0) {
+6 -5
View File
@@ -5,18 +5,19 @@
extern struct uwsgi_server uwsgi;
static int uwsgi_sqlite3_config_callback(void *foo, int field_count, char **fields, char **col) {
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
// make a copy of the string
if (field_count >= 2) {
add_exported_option( uwsgi_strncopy(fields[0], strlen(fields[0])), uwsgi_strncopy(fields[1], strlen(fields[1])), 0);
int value_len = strlen(fields[1]) + 1;
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
add_exported_option( uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
}
return 0;
}
void uwsgi_sqlite3_config(char *file) {
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
sqlite3 *db;
char *err = NULL;
@@ -43,7 +44,7 @@ void uwsgi_sqlite3_config(char *file) {
exit(1);
}
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, 0, &err)) {
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
uwsgi_log("sqlite3 error: %s\n", err);
sqlite3_close(db);
exit(1);
+36
View File
@@ -0,0 +1,36 @@
import Queue
from threading import Thread
import uwsgi
CONSUMERS = 4
def consumer(q):
while True:
item = q.get()
print(item)
#... DO A HEAVY TASK HERE ...
q.task_done()
def spawn_consumers():
global q
q = Queue.Queue()
for i in range(CONSUMERS):
t = Thread(target=consumer,args=(q,))
t.daemon = True
t.start()
print("consumer %d on worker %d started" % (i, uwsgi.worker_id()))
uwsgi.post_fork_hook = spawn_consumers
def application(env, start_response):
global q
# we pass a copy of the env dictionary as it gets cleared after yield/return
q.put(env.copy())
start_response('200 OK', [('Content-Type', 'text/html')])
yield "Task enqueued"
+23
View File
@@ -0,0 +1,23 @@
- case 1
single static app
- case 2
single static multiapp
- case 3
multi app static mountpoint
- case 4
dynamic apps with UWSGI_APPID
- case 5
dynamic apps with SCRIPT_NAME
- case 6
dynamic apps with vhost mode
+22
View File
@@ -0,0 +1,22 @@
from picasso import *
def home(req):
if not req["session"].get("user"):
return redirect("/login")
return "<h1>Welcome back, %s!</h1>" % req["session"]["user"]
def login(req):
return "<form method='post'><input type='submit' name='foo' value='login' /></form>"
def login_post(req):
print req
req["session"]["user"] = "James"
return redirect("/")
routes = setup_routes(
GET("/", home),
GET("/login", login),
POST("/login", login_post),
routing.not_found("<h1>Not Found</h1>"))
app = setup_app(routes)
+7
View File
@@ -0,0 +1,7 @@
def app(req):
print(req)
ret = {"status": 200,
"headers": {"content_type": "text/html", "foo":['bar0','bar1','bar2']},
"body": "<h1>Hello!</h1>"}
print(ret)
return ret

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