Compare commits

...
1083 Commits
Author SHA1 Message Date
roberto@dexter 920d5d7416 Changelog for 0.9.9 2011-08-29 11:32:27 +02:00
roberto@dexter dcb654d7fb spooler reload fix 2011-08-29 10:50:09 +02:00
roberto@solarisexpress a563da1223 solaris fix for lockf() 2011-08-29 10:34:46 +00:00
roberto@sirius 1e26cda615 fixed a race condition 2011-08-29 10:30:01 +02:00
roberto@dexter 97133b27ce the decoratortest is fully working, ready for release 2011-08-29 09:54:07 +02:00
roberto@sirius b428bd3b87 another bunch of build fixes 2011-08-29 08:02:37 +02:00
roberto@dexter 05136e74b4 fixed build system 2011-08-29 07:55:46 +02:00
roberto@mrspurr 9f28a8bdf1 improved upload progress 2011-08-28 20:53:46 +02:00
roberta@mrspurr d9361f1fee added test for upload progress 2011-08-28 19:13:56 +02:00
roberto@debian32 835230b1a4 emperor-tyrant 2011-08-28 09:15:13 +02:00
roberto@debian32 f88f51c553 added welcome.ini 2011-08-28 08:33:49 +02:00
roberto@debian32 1996305eb1 allows multiple --ini options 2011-08-28 07:55:54 +02:00
roberto@solrisexpress c7ad50e950 do not free getexecname() ret value 2011-08-28 07:37:21 +00:00
roberto@debian32 0ec0c29d67 fixed an indentation 2011-08-28 07:21:49 +02:00
roberto@solarisexpress 75af117e8a better magic plugin loading on binary_path 2011-08-28 07:14:42 +00:00
roberto@debian32 2b04cefe4e added help for a bunch of options 2011-08-27 19:37:34 +02:00
roberto@debian32 0e41c4111a fixed upstart 2011-08-27 18:46:53 +02:00
roberto@debian32 5f5d382c64 signal framework ported to gevent 2011-08-27 07:15:44 +02:00
roberto@dexter 3e867fe401 resolve domain names in socket logging 2011-08-26 16:20:14 +02:00
roberto@dexter 153142b8b0 fixed django uwsgi_admin without spooler 2011-08-26 15:02:02 +02:00
roberto@dexter 5562c0c047 use hub.join() instead of hub.switch() 2011-08-26 14:05:03 +02:00
roberto@debian32 f4a1f800ba timeout handling in gevent plugin 2011-08-26 12:34:12 +02:00
roberto@debian32 bdbc5e5605 another gevent improvement suggested by denis 2011-08-26 11:35:32 +02:00
roberto@debian32 4104f825ff another improvement for sys.executable in python3 2011-08-26 10:28:34 +02:00
roberto@longshot efa01ea404 better sys.executable and sys.argv values 2011-08-26 10:08:01 +02:00
roberto@debian32 982559ae66 snmp fixes 2011-08-26 09:54:11 +02:00
roberto@gambit 60002e8de8 Added tag 0.9.9-rc2 for changeset 6aa667612019 2011-08-26 08:17:20 +02:00
roberto@debian32 25d671e0f6 fixed python snmp api 2011-08-26 08:13:14 +02:00
roberto@debian32 5a58281a3f various gevent fixes 2011-08-26 07:37:26 +02:00
roberto@debian32 c422231806 ops another grunt fix 2011-08-25 18:16:58 +02:00
roberto@debian32 4979883fe5 fixed a grunt bug 2011-08-25 17:51:04 +02:00
roberto@debian32 8158a624d3 check for loop engine 2011-08-25 14:34:18 +02:00
roberto@debian32 06403b5fce fixed stupid bug in setup.py 2011-08-25 14:15:55 +02:00
roberto@debian32 bc482652fc updated setup.py 2011-08-25 14:13:13 +02:00
roberto@debian32 58aa5755e0 fixed a typo 2011-08-25 14:04:57 +02:00
roberto@debian32 bca835c58a added UWSGI_PROFILE unix env 2011-08-25 14:03:43 +02:00
roberto@debian32 4b0f68a57a check gevent version 2011-08-25 13:53:38 +02:00
roberto@debian32 b693d73ebe gevent dedicated plugin 2011-08-25 13:46:42 +02:00
roberto@dexter dfab80447b added a check for Riccardo 2011-08-24 18:24:45 +02:00
roberto@dexter bbde0c866a a couple of fixes, and reintroduction of string-based multiapp 2011-08-24 17:48:27 +02:00
roberto@mrspurr 7b3514f757 --emperor-throttle 2011-08-24 13:03:25 +02:00
roberto@mrspurr 6d5fb3b252 export cache and queue functions only if available 2011-08-20 11:12:32 +02:00
roberto@debian32 87e8f118d3 fix refcnt in async-disabled compilation 2011-08-19 16:35:16 +02:00
roberto@debian32 3ae78cc0a8 another bufsize fix 2011-08-19 16:28:44 +02:00
roberto@debian32 7ef921356f updated sharedarea 2011-08-19 15:22:20 +02:00
roberto@debian32 378185d997 added a build profile for uwsgi_pypy integration 2011-08-19 12:24:38 +02:00
roberto@debian32 c4b15a8509 changed final banner in library mode 2011-08-19 12:15:18 +02:00
roberto@debian32 96ef9d155b uwsgi.magic_table 2011-08-19 11:44:40 +02:00
roberto@debian32 d5e6412b20 uWSGI 0.9.9-rc1 2011-08-19 09:57:58 +02:00
roberto@debian32 eebe757c16 Added tag 0.9.9-rc1 for changeset fb168b0b8616 2011-08-19 08:51:26 +02:00
roberto@debian32 43a21d32cb fixed a stupid bug 2011-08-19 08:49:39 +02:00
roberto@debian32 9f9eb5ef17 improved apache2 SCRIPT_NAME/PATH_INFo handling 2011-08-19 08:48:15 +02:00
roberto@debian32 0116c62980 another refcnt fix 2011-08-19 07:06:29 +02:00
roberto@debian32 fae446e495 fix for 3.0-arch 2011-08-19 06:46:07 +02:00
roberto@debian32 6f7054df18 more tolerant cache and queue size 2011-08-18 14:27:21 +02:00
roberto@debian32 0f31c21f4a completed queue subsystem with test 2011-08-18 09:46:32 +02:00
roberto@debian32 bd3e234703 another xml app tag fix 2011-08-18 07:06:27 +02:00
roberto@gambit 71bfd63623 fixed xml app tag 2011-08-18 07:01:13 +02:00
unbit@localhost 98b89dc83c Added tag 0.9.9-beta1 for changeset 6945ee03c7ea 2011-08-18 06:33:20 +02:00
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
roberto@debian32 b7525475d8 ready for 0.9.8 release 2011-06-05 08:20:23 +02:00
roberto@debian32 f35a36ac02 set a mercy mode for INT/QUIT 2011-06-05 07:38:58 +02:00
roberto@netbsd64 3b53f89a24 netbsd fix 2011-06-05 09:17:38 +02:00
roberto@debian32 764d94e41b support for abstract unix socket prefixed with \0 2011-06-04 08:55:49 +02:00
roberto@indianajones 0292e15497 add /lib to linker on SunOS-derived systems 2011-06-02 19:35:05 +01:00
roberto@debian32 bde4ac7b2f uWSGI 0.9.8-rc4 2011-06-02 18:53:49 +02:00
roberto@debian32 c71fa3abd1 Added tag 0.9.8-rc4 for changeset 0f1f3924ee53 2011-06-02 18:53:38 +02:00
roberto@indianajones d2abdb5d3a fix accept() to receive the correct ip 2011-06-02 18:44:48 +01:00
roberto@indianajones 1392791837 OpenIndiana is now officially supported 2011-06-02 15:15:35 +01:00
roberto@goyle 6f7d9634d5 allows log-date 2011-06-02 12:08:56 +02:00
roberto@goyle 82b95114a8 added welcome.py 2011-06-02 11:38:18 +02:00
roberto@debian32 d90e701acd use int in uwsgi.version_info 2011-06-01 13:02:33 +02:00
roberto@debian32 42993022bb python3 fix 2011-06-01 12:55:20 +02:00
roberto@dj1 29b1e46252 uwsgi.version_info 2011-06-01 05:52:46 -05:00
roberto@sirius 260cea639f better myadmin.py 2011-06-01 10:04:57 +02:00
roberto@sirius 208aea8aca two new management flag for backlog queue 2011-06-01 10:00:17 +02:00
roberto@sirius f164d401d3 another uwsgi_log fix 2011-06-01 09:47:58 +02:00
roberto@dj1 5e1c34a08b really fix uwsgi_log 2011-06-01 02:15:53 -05:00
roberto@debian32 9c7b596a0d fixed uwsgi_log 2011-06-01 08:38:51 +02:00
roberto@debian32 5ff34ac6d0 a couple of admin plugin fixes 2011-06-01 08:12:50 +02:00
roberto@debian32 e304e34929 throw exception on too much big spool requests 2011-06-01 07:11:54 +02:00
roberto@dj1 6d7848248d added --early-emperor option 2011-05-31 08:44:26 -05:00
roberto@sirius dbc0da0586 support for idle mode in single process mode 2011-05-31 14:26:57 +02:00
roberto@debian32 fecdcf9d10 allows sub-emperors (emperors generated by emperors) 2011-05-31 08:56:03 +02:00
roberto@sirius bfd0ab2301 fixed a typo 2011-05-30 19:10:01 +02:00
roberto@sirius 8002777e75 uWSGI 0.9.8-rc3 2011-05-30 19:04:05 +02:00
roberto@debian32 d57d5acb30 --idle mode 2011-05-29 06:52:47 +02:00
roberto@debian32 43e6664dd9 --cheap option 2011-05-28 19:43:29 +02:00
roberto@dj1 d0c6dff83e --add-header option 2011-05-28 05:20:48 -05:00
roberto@dj1 54b40f5978 better cgroup support 2011-05-27 14:23:22 -05:00
roberto@dj1 1c59c03261 unlimited sockets for fastrouter 2011-05-27 08:55:15 -05:00
roberto@dj1 ce23fd38ab better emperor+master mode 2011-05-27 05:11:41 -05:00
roberto@dj1 4818efa7de emperor+amqp fixes 2011-05-27 04:07:07 -05:00
roberto@dj1 ea19e74229 better netlink ns detection 2011-05-27 03:21:21 -05:00
roberto@dj1 fe353de5a8 fixed netlink compilation 2011-05-27 01:58:43 -05:00
roberto@dj1 1d89266f2e unlimited shared sockets 2011-05-27 01:39:01 -05:00
roberto@debian32 61d79394ca --fastrouter-subscription-slot 2011-05-26 05:35:43 +02:00
roberto@debian32 491f2828b5 --no-fd-passing 2011-05-26 05:29:01 +02:00
roberto@nexenta32 431e05d4f4 fixed ifaddrs support 2011-05-26 06:17:46 +02:00
roberto@solarisexpress ae6780a487 remember: do not use the word 'sun' as variable on solaris... 2011-05-26 04:54:55 +00:00
roberto@debian32 5707a70141 added --log-socket 2011-05-25 08:57:13 +02:00
roberto@debian32 e9a7bd7da1 add abstract unix socket 2011-05-23 21:50:04 +02:00
roberto@debian32 91e45daf6c better unix socket support in abstract namespace (Linux only) 2011-05-23 16:10:27 +02:00
roberto@debian32 9f69998075 grunt improvement 2011-05-23 11:43:22 +02:00
roberto@debian32 4f6270976b fixed python3.x spooler 2011-05-22 14:07:01 +02:00
roberto@debian32 328caa43f2 allow --auto-snapshot to take a value 2011-05-22 11:56:58 +02:00
roberto@debian32 368408374a preliminary snapshotting support 2011-05-22 11:43:28 +02:00
roberto@debian32 c3a90db493 uWSGI 0.9.8-rc2 2011-05-21 08:10:03 +02:00
roberto@debian32 5bc0320877 Added tag 0.9.8-rc2 for changeset e91bc724325e 2011-05-21 08:09:49 +02:00
roberto@debian32 622ed620b9 fixed python 3.1 2011-05-21 08:03:22 +02:00
roberto@debian2 1b859413de add mercurial revision to uWSGI version string 2011-05-21 07:43:49 +02:00
roberto@maverick64 95432fd8e3 added --die-on-term 2011-05-19 20:35:47 +02:00
roberto@freebsd64 b3f3c5d7b3 fixed touch reload 2011-05-19 09:33:25 +02:00
roberto@debian32 02cef20462 another fix for wsgi.input 2011-05-19 08:33:11 +02:00
roberto@debian32 3edebe34ae improved upload test 2011-05-18 21:15:41 +02:00
roberto@longshot 28c9b75fb5 wsgi.input fix 2011-05-18 21:10:18 +02:00
roberto@fedora15 a2735e10b7 report number of vassals to systemd 2011-05-17 08:57:50 +02:00
roberto@fedora15 e03d26fd63 report emperor dead status to systemd 2011-05-17 08:36:54 +02:00
roberto@sirius 7c4c346e64 fix systemd on unsupported platform 2011-05-17 08:29:33 +02:00
roberto@fedora15 67b3c0c4a8 systemd integration 2011-05-17 08:26:39 +02:00
roberto@fedora15 dadca785e4 initial systemd support 2011-05-16 17:25:38 +02:00
roberto@debian32 accebe5597 add --log-prefix option 2011-05-16 10:06:47 +02:00
unbit@gambit 792965bedd uWSGI 0.9.8-rc1 2011-05-14 09:57:15 +02:00
unbit@localhost 1bb1bafe0c Added tag 0.9.8-rc1 for changeset d1e57707f631 2011-05-14 09:56:41 +02:00
roberto@debian32 28c11324ca merge 2011-05-14 09:34:29 +02:00
roberto@debian32 42d940c38e a bit of refactoring 2011-05-14 09:34:03 +02:00
roberto@freebsd64 c1ea05b925 fixed profiler compilation in older python 2011-05-14 07:08:33 +02:00
roberto@debian32 9435693865 removed old/useless writers.c 2011-05-13 18:49:31 +02:00
roberto@debian32 14da582637 various static file fixes 2011-05-13 18:46:21 +02:00
roberto@debian32 b2d4a795a1 various ruby.rack fixes 2011-05-13 18:19:26 +02:00
roberto@sirius 493696705b another off_t to size_t fix 2011-05-13 16:52:21 +02:00
roberto@debian32 d827c6f09a moved rack.input to the new POST api 2011-05-13 16:46:06 +02:00
roberto@debian32 df000b0cb2 support for jemalloc 2011-05-12 12:55:07 +02:00
roberto@debian32 d9630a32c7 added support for tcmalloc 2011-05-12 12:49:07 +02:00
roberto@debian32 71cc6f61bd fixed a stupid (really stupid) bug in uwsgi.core allocation 2011-05-11 19:04:52 +02:00
roberto@debian32 46eb832cc7 set in_request per core 2011-05-11 18:47:42 +02:00
roberto@debian32 11b2e4b430 lock goodbye_cruel_world in threading mode 2011-05-11 17:08:02 +02:00
roberto@debian32 11775532ee applied leonid patch for symlinks 2011-05-11 15:49:59 +02:00
roberto@debian32 f3388db8ba do not link core libraries in plugins 2011-05-11 12:28:15 +02:00
roberto@sirius 25ac86393f use size_t instead of off_t 2011-05-11 12:05:48 +02:00
roberto@debian32 b3432a95e1 finally fixed wsgi.input 2011-05-11 11:55:28 +02:00
roberto@debian32 e34d169fa6 merge 2011-05-11 06:24:11 +02:00
roberto@debian32 de84accb7a removed unused variable in pyerl 2011-05-11 06:23:40 +02:00
roberto@sirius 187577cbb5 fixed a stupid typo 2011-05-10 09:53:54 +02:00
roberto@debian32 72109b72d2 various rack fixes 2011-05-10 09:36:07 +02:00
roberto@debian32 f6c01d11e9 completed ruby 1.9 fiber support 2011-05-10 08:50:06 +02:00
roberto@debian32 d695ef4f57 removed garbage 2011-05-09 21:41:55 +02:00
roberto@debian32 16c6dcc573 better threading reload 2011-05-09 21:27:08 +02:00
roberto@debian32 3df19b286a support for plugin as symlinks 2011-05-09 20:18:49 +02:00
roberto@debian32 6f1b08762d adde fixup hook handler 2011-05-09 09:43:55 +02:00
roberto@debian32 a4a379f9d6 rack ported to new socket api 2011-05-07 09:32:49 +02:00
roberto@mrspurr 3d3d0304bc plugin autoloading (finally) 2011-05-07 09:21:07 +02:00
roberto@natty32 26135018a3 added check for patl method in psgi response 2011-05-06 08:09:30 +02:00
roberto@debian32 4bd381bb99 big PSGI update 2011-05-06 14:17:01 +02:00
roberto@debian32 cf08972e82 first round of memleak hunting in psgi/perl 2011-05-06 10:12:59 +02:00
roberto@natty32 d57a58d1e7 psgi input fix 2011-05-06 00:16:57 +02:00
roberto@natty32 f10789965e added seek to psgi custom object 2011-05-05 17:08:52 +02:00
roberto@natty32 94145bd300 temp --psgi-custom-input option 2011-05-05 17:04:51 +02:00
roberto@natty32 cdcb61d10d signal on python thread fix 2011-05-05 02:47:04 +02:00
roberto@natty32 56146a34af python get line number/profier fix 2011-05-05 02:40:53 +02:00
roberto@natty32 991e818449 fixes for python2.6 and forcing -bash in perl 2011-05-05 02:25:17 +02:00
roberto@natty32 80083cba76 funny hack to have a consistent __FILE__ in perl 2011-05-04 17:43:09 +02:00
roberto@natty32 2c44fd5aa2 fix stdout/stderr in python3 2011-05-04 15:39:24 +02:00
roberto@natty32 1561dd38fc another PSGI loading fix 2011-05-04 05:27:32 +02:00
roberto@natty32 8152648f66 psgi loading improvement 2011-05-04 04:59:01 +02:00
roberto@natty32 c1507d0381 put master logging in non-blocking mode 2011-05-04 03:33:44 +02:00
roberto@natty32 f0fb603af2 debug send/recv log buffer 2011-05-04 03:24:44 +02:00
roberto@natty32 93e891153f fixed sqlite3 support 2011-05-03 18:45:04 +02:00
roberto@natty32 26ece717b6 added support for sqlite3 configuration 2011-05-03 18:35:49 +02:00
roberto@natty32 93767335ca added --profiler 2011-05-03 15:01:51 +02:00
roberto@natty32 7cbe751a39 added --perl-local-lib 2011-05-02 17:12:32 +02:00
roberto@natty32 c45df83f19 set buffer size in $/ 2011-05-02 13:25:36 +02:00
roberto@natty32 fabce61a58 add PLACK_ENV and -bash 2011-05-02 12:11:38 +02:00
roberto@natty32 5c9ccae598 added PSGI streamer test 2011-05-02 08:44:50 +02:00
roberto@natty32 6c9d7239f2 uGreen support added to perl 2011-05-02 08:36:57 +02:00
roberto@natty32 4b75e2577e preliminary async/nonblocking support for PSGI 2011-05-02 07:58:16 +02:00
roberto@natty32 08c9d942a4 lazy mode support 2011-05-01 17:31:54 +02:00
roberto@natty32 3b59b4ad21 psgi: allows multiline headers 2011-05-01 17:01:05 +02:00
roberto@natty32 7682eec52a do not die on perl die() :P 2011-05-01 16:42:01 +02:00
roberto@sirius 694517bbe7 export all the required psgi.* vars and all of the supported psgix.* 2011-05-01 15:37:25 +02:00
roberto@natty32 7f443fdd05 allow globbed-pythonpath 2011-04-27 16:28:44 +02:00
roberto@natty32 01ab891c11 unlimited pythonpath entries 2011-04-27 15:56:33 +02:00
roberto@natty32 052aacfd36 fixed --map-socket 2011-04-27 15:46:00 +02:00
roberto@natty32 80a6d2ccfb various fixes in multiple sockets and support for file piped via stdin 2011-04-27 14:15:01 +02:00
roberto@debian32 b4ce175bdf add --master to carbon/graphite example 2011-04-27 08:08:59 +02:00
roberto@debian32 f6f52d32dc fixed a typo 2011-04-27 08:07:19 +02:00
roberto@debian32 865b2de9bb added an example script for graphite/carbon update 2011-04-27 08:04:45 +02:00
roberto@debian32 4a8233a041 support for libzmq 2.0 2011-04-26 19:39:40 +02:00
roberto@natty32 f856ad78a3 added --log-zeromq 2011-04-26 17:26:40 +02:00
roberto@debian32 653267cbe6 added libyaml support, for future advanced implementations 2011-04-26 08:45:44 +02:00
roberto@debian32 8b53df27ab gcc-4.6 fixes and applied Riccardo Magliocchetti patch for libm 2011-04-26 07:38:10 +02:00
roberto@debian32 c4b7c2b58c fix build without zeromq 2011-04-25 16:56:06 +02:00
roberto@maverick64 66f82f364c fixed clustering 2011-04-25 09:50:11 +02:00
roberto@maverick64 6d269607d2 allow clustering + zeromq 2011-04-25 09:38:26 +02:00
roberto@maverick64 8370977e5b fixed indentation 2011-04-25 07:15:41 +02:00
roberto@maverick64 e2c335ff73 threaded zeromq/mongrel2 support 2011-04-25 07:13:23 +02:00
roberto@maverick64 816b9d0343 refactored zeromq 2011-04-24 18:50:44 +02:00
roberto@maverick64 2922e1ba35 slowdown vassals spawn 2011-04-24 07:38:38 +02:00
roberto@maverick64 c86f341d29 first part of --socket-protocol option 2011-04-22 09:34:50 +02:00
roberto@maverick64 73cdd68283 fixed modifier1 30 2011-04-22 09:18:07 +02:00
roberto@maverick64 81641686bc various fixes 2011-04-22 08:51:29 +02:00
roberto@maverick64 14c58c8e62 fixed preforking+threading 2011-04-22 07:53:32 +02:00
roberto@maverick64 74b8f2587c prototype for uwsgidump protocol 2011-04-21 19:28:02 +02:00
roberto@mrspurr bebe041061 added psgi full streaming support 2011-04-21 06:24:41 +02:00
roberto@msrpurr 2e5d3d2952 fixed response size in PSGI 2011-04-21 04:26:58 +02:00
roberto@mrspurr c2d155b8ff --inherit and --vassals-inherit 2011-04-20 21:33:56 +02:00
roberto@natty32 fda368ff08 added support for mongrel2 tnetstrings 2011-04-20 11:49:41 +02:00
roberto@natty32 19cf592e77 fastcgi optimization 2011-04-20 09:32:37 +02:00
roberto@natty32 260cac6b59 fixed zeromq post-file close 2011-04-19 18:19:08 +02:00
roberto@natty32 673275e708 multiprotocol refactoring 2011-04-19 18:14:40 +02:00
roberto@freebsd64 a6bc778c25 conditionally compile libuuid 2011-04-19 20:46:31 +02:00
roberto@centos32 ef2f5879b6 conditionally compile netlink support 2011-04-19 13:46:26 +02:00
roberto@sirius ee725bf625 fixed compilation in no-zmq environments 2011-04-19 11:35:03 +02:00
roberto@natty32 5388fa442c completed zeromq support 2011-04-19 08:34:03 +02:00
roberto@natty32 913493fd2e mongrel2/zeromq support added 2011-04-19 06:59:34 +02:00
roberto@natty32 6d4a8c6619 added a pure-zeromq loop engine 2011-04-18 20:00:26 +02:00
roberto@natty32 4a57115336 edge triggered events support 2011-04-18 17:07:13 +02:00
roberto@natty32 1dd754a0d5 fallback to read/write instead of sendfile in fastcgi mode 2011-04-18 06:32:52 +02:00
roberto@natty32 509b78d906 fastcgi fixes 2011-04-18 05:04:11 +02:00
roberto@natty32 363366d012 preliminary fastcgi support 2011-04-17 07:35:15 +02:00
roberto@natty32 26d4fd4e00 fixed uwsgi protocol support 2011-04-16 20:02:27 +02:00
roberto@natty32 09ee97e775 first destructive commit for uWSGI 0.9.8 2011-04-16 19:41:58 +02:00
roberto@natty32 1400a95cec added JSON support to the Emperor 2011-04-14 09:38:06 +02:00
roberto@natty32 5e96c4ca79 fixed json support with pkg-config 2011-04-14 09:10:03 +02:00
roberto@sirius 3c068b2a00 fixed http support 2011-04-14 09:47:04 +02:00
roberto@sirius 81fd7757c1 JSON support, thanks jansson 2011-04-14 09:32:17 +02:00
roberto@natty32 1db64b72ae fixed build of PSGI plugin on non-Apple platform 2011-04-13 13:27:32 +02:00
roberto@natty32 ab1bed236c use close-on-exec instead of close() on osx reload 2011-04-13 07:38:46 +02:00
roberto@debian64 e503999392 fixed virtualhosting with dynamic virtualenv 2011-04-12 10:34:36 +02:00
roberto@dj1 2392eb7e0b fixed wait in emperor 2011-04-08 03:25:16 -05:00
roberto@dj1 c62b54f18d added vassal loyalty concept 2011-04-08 02:43:05 -05:00
roberto@natty32 603d46c1ae merge 2011-04-07 08:46:34 +02:00
roberto@natty32 c0e0ae551d use binary stream for wsgi.input in Python 3.x 2011-04-07 08:45:59 +02:00
unbit@localhost a0a2507c05 Added tag 0.9.7.2 for changeset a5f13497b392 2011-04-06 09:50:01 +02:00
roberto@natty32 6eed48b28d updated Changelog and copyright year 2011-04-06 09:29:46 +02:00
roberto@netbsd64 9c5d289098 better locking for NetBSD and OpenBSD 2011-04-06 08:16:03 +02:00
roberto@solarisexpress 42ab7f23d8 added timegm to solaris 2011-04-06 06:03:17 +00:00
roberto@natty32 c9c2f4232e preparing for 0.9.7.2 release 2011-04-06 05:06:38 +02:00
roberto@longshot d4f23cc6bd use realpath() for document_root 2011-04-05 20:55:48 +02:00
roberto@natty32 b0db67d4d4 refactored post limit management 2011-04-05 16:51:40 +02:00
roberto@natty32 703cad6715 disallow empty socket names 2011-04-05 11:32:15 +02:00
roberto@natty32 667d67460f do not build netlink support (still useless for non-third-party plugins) 2011-04-05 09:00:58 +02:00
roberto@natty32 35cf9ae328 implemented exc_info in WSGI start_response and added --reload-on-as and --reload-on-rss 2011-04-05 08:58:22 +02:00
roberto@natty32 c04131af4b fixed syslog support 2011-04-04 17:17:47 +02:00
roberto@natty32 9cc4db1a12 various fixes 2011-04-04 09:46:17 +02:00
roberto@natty32 b326500913 --static-map mountpoint=documentroot option 2011-04-04 08:31:17 +02:00
roberto@natty32 a26579fcf5 better plugin loading 2011-04-03 08:18:51 +02:00
roberto@natty32 a2b9c44433 -ldl should be used only for Linux 2011-04-02 15:57:57 +02:00
roberto@natty32 c3b97da1d4 various Riccardo Magliocchetti build fixes 2011-04-02 15:26:00 +02:00
roberto@natty32 048cf0232a nailed connection between emperor and rabbitmq 2011-04-01 16:11:18 +02:00
roberto@natty32 89c113bee6 added EXILE mode for vassals 2011-04-01 08:35:20 +02:00
roberto@natty32 6b9969a302 allow emperor config files to be taken via http 2011-04-01 08:09:34 +02:00
roberto@natty32 a6e7513d2a declare exchange automatically 2011-04-01 07:13:09 +02:00
roberto@natty32 8a04f4810f allow vassals configuration to be stored on amqp/rabbitmq servers 2011-04-01 06:31:54 +02:00
roberto@natty32 1d9d443de0 amqp/rabbitmq emperor fixes 2011-04-01 05:17:50 +02:00
roberto@natty32 00e5809a71 preliminary amqp/rabbitmq support for emperor 2011-04-01 03:14:51 +02:00
roberto@freebsd64 07ba4a040b fixed freebsd kvm_open 2011-03-30 20:48:01 +02:00
roberto@mrspurr 7b319d230a allow building of psgi plugin without ithreads 2011-03-30 08:03:48 +02:00
roberto@natty32 641bc2daec fixed unbitstaff build profile 2011-03-29 12:06:13 +02:00
roberto@dj2 fbaa30cc08 various fixes 2011-03-28 11:31:40 -05:00
roberto@dj2 a0c2c9056b fixed a couple fo emperor race conditions 2011-03-28 09:37:17 -05:00
roberto@dj2 30ab5fd76b added --exit-on-reload 2011-03-28 07:31:51 -05:00
roberto@dj2 30beab4017 fixed a regression in setgroups() 2011-03-28 05:38:29 -05:00
roberto@dj2 4ec1493b09 fixed subscription system 2011-03-28 04:29:04 -05:00
roberto@dj2 e7cbe9709e build netlink support in Linux 2011-03-28 04:17:07 -05:00
roberto@dj2 aacaeba525 shared sockets support 2011-03-28 04:15:31 -05:00
roberto@dj2 6e4da5efb7 add netlink library 2011-03-28 04:11:31 -05:00
roberto@natty32 87443a4ff2 Added tag 0.9.7.1 for changeset 486e7760bcbc 2011-03-26 09:39:57 +01:00
roberto@natty32 9746759c68 fixed changelog before official release 2011-03-26 09:39:53 +01:00
roberto@natty32 170ee2b98a date was wrong in 0.9.7.1 2011-03-26 09:38:21 +01:00
roberto@natty32 938fb777dd uWSGI 0.9.7.1 2011-03-26 09:36:11 +01:00
roberto@natty32 33e1aafcd1 Added tag 0.9.7.1 for changeset d9b9b540f7dc 2011-03-26 09:35:31 +01:00
roberto@natty32 597ee90041 add sys.abiflags if necessary 2011-03-26 09:27:30 +01:00
roberto@natty32 e87e54ea28 allow --namespace-net and fix python library name 2011-03-26 09:18:52 +01:00
roberto@natty32 5c64c1ac3f fixed post-buffering without pep3333-input 2011-03-25 19:11:53 +01:00
roberto@natty32 c611cbc2ca fixed current_wsgi_req in multithreading without cores 2011-03-23 11:59:05 +01:00
roberto@sirius 9d051f4171 fixed a buf on older OSX versions (i hope) 2011-03-22 19:34:12 +01:00
roberto@sirius 6aee788678 fixed cmsg parsing 2011-03-22 17:21:19 +01:00
roberto@natty32 425a45caa7 updated banner message in debug mode 2011-03-22 17:02:20 +01:00
roberto@natty32 0571601e02 added --map-socket 2011-03-22 14:55:54 +01:00
roberto@natty32 c1992c8c7a added --check-cache 2011-03-22 12:12:03 +01:00
roberto@natty32 bd913870c7 fixed setup.py 2011-03-21 10:36:52 +01:00
roberto@natty32 7a479dd47f add 304/If-Modified-Since support for --check-static <dir> 2011-03-21 10:31:50 +01:00
roberto@natty32 7ae77aa58d added UWSGI_CACHE_GET dynamic variable 2011-03-20 21:24:32 +01:00
roberto@natty32 97a4260d44 added --pidfile2 and --logfile-chown 2011-03-20 08:05:27 +01:00
roberto@mrspurr b90d711764 allow python modules to be on http server 2011-03-20 07:51:56 +01:00
roberto@mrspurr 22de5b523e reintroduce modifier1 30 2011-03-19 17:03:00 +01:00
roberto@mrspurr 5798b824c0 forbid daemonizing in vassal mode 2011-03-19 11:03:16 +01:00
roberto@goyle 4cbf6cfc33 various fixes in touch_reload 2011-03-19 09:33:28 +01:00
roberto@mrspurr 8b55460156 added persistence for queue 2011-03-18 20:20:36 +01:00
roberto@mrspurr a61d48a451 fixed stackless support 2011-03-18 08:14:12 +01:00
roberto@mrspurr b9f4d57d67 applied activestate fix for --root support in setup.py 2011-03-18 07:15:10 +01:00
roberto@natty32 92cd36d14d ready for first stable release 2011-03-17 09:15:52 +01:00
roberto@natty32 f74e61b126 fixed psgi compilation 2011-03-16 21:29:52 +01:00
roberto@natty32 c8b4ba2b5b updated iobound_async example and improved pep3333-input 2011-03-16 20:54:54 +01:00
roberto@natty32 0a15ba1c5b remove stackless support, move it to async plugin 2011-03-16 13:12:50 +01:00
roberto@natty32 7ee5948233 better error reporting on failed open/fopen 2011-03-16 12:14:41 +01:00
roberto@natty32 85c8bcf9d2 removed memory leak in greenlet plugin 2011-03-16 11:12:55 +01:00
roberto@natty32 67394c6664 added greenlet plugin 2011-03-16 11:02:05 +01:00
roberto@silente 66ef7d8229 remove uGreen compilation on unsupported platforms 2010-12-29 23:06:47 +01:00
roberto@solarisexpress 3773bc69f2 fixed ldap solaris support 2011-03-16 09:48:52 +00:00
roberto@natty32 912416b119 fixed openldap support 2011-03-16 09:45:15 +01:00
roberto@solarisexpress 7dfe125013 solaris fixes 2011-03-16 09:39:02 +00:00
roberto@mrspurr 87db34ef0b removed setjmp code 2011-03-16 07:46:11 +01:00
roberto@natty32 d4f75ab53c re-added ugreen support (better and faster) 2011-03-16 07:28:23 +01:00
roberto@natty32 dc97e8fce5 new help system 2011-03-15 12:14:22 +01:00
roberto@natty32 b3965d9d67 updated async support 2011-03-15 10:45:23 +01:00
roberto@natty32 7ee90d1e12 fixed python uwsgi.cache_get 2011-03-12 14:52:11 +01:00
roberto@sirius 9d8b373e4f uWSGI 0.9.7-rc3 2011-03-12 14:21:16 +01:00
roberto@natty32 a068a7eb5b added support for cache backing store 2011-03-12 14:14:43 +01:00
roberto@natty32 aa004c1893 less verbose file monitoring 2011-03-12 09:31:14 +01:00
roberto@natty32 9a9c149370 fixed emperor waitpid and erlang list encoding 2011-03-12 07:35:41 +01:00
roberto@natty32 9e6e226e4b improved snmp agent and fixed cache modifier 4 2011-03-11 11:55:44 +01:00
roberto@mrspurr 06c2aed0e0 add modifier 3 in cache plugin 2011-03-11 10:57:39 +01:00
roberto@natty32 df4f610cfc preliminary cpu-affinity support 2011-03-11 07:37:43 +01:00
roberto@natty32 64249abae1 improved ldap support 2011-03-10 19:14:13 +01:00
roberto@sirius 94f4be58bd auto configure ldap support 2011-03-10 10:40:56 +01:00
roberto@sirius 35987d3741 added --allowed-modifiers 2011-03-10 10:21:08 +01:00
roberto@natty32 be73e00dde merge 2011-03-10 09:56:33 +01:00
roberto@natty32 a5f272f337 fixed a bug in getopt_long 2011-03-10 09:56:04 +01:00
roberto@sirius 406691aa69 uWSGI 0.9.7-rc2 2011-03-09 11:26:27 +01:00
roberto@natty32 6827b3bf15 cron-like interface added to signal framework 2011-03-09 10:33:44 +01:00
roberto@natty32 2055a1472f great fix suggested by Damjan Georgievski for linux namespaces 2011-03-08 14:17:30 +01:00
roberto@natty32 f4f9018068 fixed multithreading + max-requests 2011-03-08 11:45:37 +01:00
roberto@sirius 3e82b5cd33 improved configuration system 2011-03-07 16:06:59 +01:00
roberto@sirius 07036bce20 fix %v usage in emperor 2011-03-07 11:52:44 +01:00
roberto@sirius a4a7a75f29 uWSGI 0.9.7-rc1 2011-03-07 09:42:53 +01:00
roberto@natty32 02d6006b2f added %v in emperor 2011-03-06 19:21:09 +01:00
roberto@natty32 e8e5f11c66 use sigaction() instead of signal() 2011-03-05 17:20:10 +01:00
roberto@natty32 e53a6fa4c0 fixed http fd passing on POST 2011-03-04 14:23:36 +01:00
roberto@natty32 c478b0a0c8 added uwsgi.erlang_register_process 2011-03-04 12:07:07 +01:00
roberto@natty32 5f207e6978 fix getsockname on unbound sockets 2011-03-04 09:01:14 +01:00
roberto@natty32 a2b74d0afd fixed linux namespace on recent kernel 2011-03-04 08:20:20 +01:00
roberto@maverick64 b867b11de3 fixed python2.x threads 2011-03-03 17:17:27 +01:00
roberto@maverick64 806765d1d3 fixed python3.2 threads 2011-03-03 17:15:01 +01:00
roberto@sirius 62d2b97e17 export build date 2011-03-03 14:06:29 +01:00
roberto@sirius c04e339034 report clustering without a socket 2011-03-03 11:07:58 +01:00
roberto@sirius 927b495646 nuclear blast all the processes on initialization error 2011-03-03 10:38:19 +01:00
roberto@mrspurr 57b5392590 fixed gateways reloading 2011-03-03 09:52:57 +01:00
roberto@mrspurr 463030108f fixed vacuum 2011-03-03 09:17:03 +01:00
roberto@netbsd64 46dd754264 NetBSD fixes 2011-03-02 19:54:13 +01:00
roberto@silente 12d9641b66 OpenBSD, endianess and clustering fixes 2010-12-16 07:21:51 +01:00
roberto@maverick64 6cb1203d26 fixed post buffering in python 2011-03-02 17:22:12 +01:00
roberto@maverick64 23d0ec333e encode python string/binary to erlang binary 2011-03-02 11:17:12 +01:00
roberto@maverick64 da579fd308 fix refcnt in erlang->python translation 2011-03-02 08:54:01 +01:00
roberto@longshot 14152bc999 removed broken log rotation 2011-03-01 20:55:04 +01:00
roberto@sirius 6c32e5f2e2 fixed no_argument options in ini and yaml parsing 2011-03-01 16:38:45 +01:00
roberto@freebsd64 62f74f2b60 uWSGI 0.9.7-beta1 2011-03-01 10:47:32 +01:00
roberto@maverick64 6ac7f6db7f python 3.2 fixes 2011-03-01 10:43:43 +01:00
roberto@mrspurr 388a836bbc added Changelog for beta1 2011-03-01 10:20:37 +01:00
roberto@mrspurr f0187e8b0f added --reload-mercy 2011-03-01 10:04:36 +01:00
roberto@sirius c698b82c30 do not rely on exit code for server reloads 2011-02-28 17:39:09 +01:00
roberto@fiorenzo afb3e3636e fixed lua and psgi plugins 2011-02-28 15:26:05 +01:00
roberto@cable 774548f268 --attach-daemon fixes 2011-02-28 08:47:04 +01:00
roberto@longshot ee38901855 various rack/rails fixes 2011-02-27 09:29:01 +01:00
roberto@longshot a07ecdb3e3 multiline headers in Rack plugin 2011-02-27 07:10:29 +01:00
roberto@longshot 143c286f3b fixed --eval 2011-02-27 05:54:20 +01:00
roberto@longshot 5f2f13c49e another --processes auto fix 2011-02-27 05:15:15 +01:00
roberto@longshot 2c19a031c7 added --processes auto 2011-02-26 20:28:26 +01:00
roberto@mrspurr a10e67538a passive clustering support 2011-02-26 15:42:56 +01:00
roberto@fiorenzo 4387075930 multicast clustering in http router 2011-02-26 15:25:46 +01:00
roberto@fiorenzo 6ec1eb5c90 added --harakiri-verbose 2011-02-26 11:21:46 +01:00
roberto@fiorenzo 6ac1cbe913 fixed python2.5-erlang bridge 2011-02-25 18:40:32 +01:00
roberto@fiorenzo 4923326bdd another fix for pyerl 2011-02-25 17:53:09 +01:00
roberto@sirius 0f8ca18e0d erlang build fix 2011-02-25 17:35:57 +01:00
roberto@mrspurr 7666e16072 fixed urack.rb 2011-02-24 19:22:22 +01:00
roberto@mrspurr a42f6e5d18 fixed a stupid bug in fd passing 2011-02-24 19:13:34 +01:00
roberto@sirius 67b22ff796 added iterations to uwsgi.add_rb_timer() 2011-02-24 10:50:52 +01:00
roberto@sirius 28c14f4d8c added uwsgi.add_rb_timer() 2011-02-24 10:29:06 +01:00
roberto@sirius 7133069ee9 updated signal framework to the new api 2011-02-24 09:48:28 +01:00
roberto@lupo b752425223 fixed REMOTE_ADDR in http router 2011-02-23 21:18:33 +01:00
roberto@lupo c5367bb338 http timeout fixes 2011-02-23 21:10:23 +01:00
roberto@sirius d1342241bd rbtree timers 2011-02-23 20:54:52 +01:00
roberto@cable 05be07aab4 removed debug from real gil 2011-02-23 10:29:01 +01:00
roberto@mrspurr 7f4f16e96a fixed ini/yaml parsing with optional values, added UWSGI_SETENV var 2011-02-23 09:35:38 +01:00
roberto@lupo f11664642f add REMOTE_ADDR in http router 2011-02-23 05:50:35 +01:00
roberto@lupo 28b074b6ea always export QUERY_STRING in http router 2011-02-22 15:18:49 +01:00
roberto@lupo f43161c939 subscription system fix 2011-02-22 14:10:54 +01:00
roberto@sirius d52b7111ea fixed reloading 2011-02-22 13:47:29 +01:00
roberto@sirius 9331d1154e damn, another fix for spooler leak 2011-02-21 11:03:46 +01:00
roberto@sirius 364a580090 fixed a leak in the spooler 2011-02-21 10:17:28 +01:00
roberto@lupo f33fa5005a better subscription system 2011-02-21 09:28:38 +01:00
roberto@lupo 8029d01b8b report client REMOTE_ADDR in SIGPIPE 2011-02-21 07:46:37 +01:00
roberto@lupo 69586a6134 fixed a couple of leaks spotted by Riccardo and added uwsgi.listen_queue() 2011-02-21 07:44:37 +01:00
roberto@lupo 7c9c50c6a9 --master-as-root can be used with gateways 2011-02-21 06:47:23 +01:00
roberto@lupo 97139a27d7 SERVER_PORT support in http server 2011-02-21 05:49:52 +01:00
roberto@mrspurr 3b67033d65 http fixes and new subscriber infrastructure 2011-02-20 20:06:26 +01:00
roberto@mrspurr ec08632a29 fixed python <= 2.5 support 2011-02-19 08:55:41 +01:00
roberto@mrspurr eea64e0178 new caching modifier2 2011-02-19 08:39:28 +01:00
roberto@goyle 78096fab30 cache items can have a 16bit flags 2011-02-18 19:34:02 +01:00
roberto@goyle 86fcd13dd9 structure for future response caching 2011-02-18 19:31:58 +01:00
roberto@goyle 4badecdbbc --attach-daemon option 2011-02-18 16:11:24 +01:00
roberto@fedora32 8d1a0d6a13 better check for linux namespace support 2011-02-17 15:24:24 +01:00
roberto@goyle b102b2979b allow uwsgi queue to be used as a stack 2011-02-17 08:04:17 +01:00
roberto@arch32 393235fbfe python3 fixes 2011-02-16 16:56:51 +01:00
roberto@goyle 183a109119 another bunch of async optimizations 2011-02-16 16:42:33 +01:00
roberto@goyle bcff6e0173 various fixes 2011-02-16 15:44:53 +01:00
roberto@goyle 3bd2c3a573 merge 2011-02-16 08:12:53 +01:00
roberto@goyle afba91ad61 added uwsgi queue subsystem 2011-02-16 08:12:21 +01:00
roberto@goyle a34c0f5556 http event optimization 2011-02-15 14:24:53 +01:00
roberto@openbsd32 3fd41a3d2e OpenBSD fixes 2011-02-15 11:53:56 +01:00
roberto@openbsd32 1c5ba25437 use gcc -dumpversion 2011-02-15 10:34:58 +01:00
roberto@arch32 f7ff6b5488 fix gcc version detect 2011-02-15 09:54:22 +01:00
roberto@goyle 53ac53167b osx rwlock fix 2011-02-15 08:39:42 +01:00
roberto@maverick64 c4eccd0d93 first attempt of a better wsgi.input 2011-02-14 20:48:01 +01:00
roberto@maverick64 7744285dc3 move caching locking to rwlock 2011-02-13 18:58:51 +01:00
roberto@maverick64 238c98c0bd a bunch of caching fixes 2011-02-12 10:59:20 +01:00
roberto@maverick64 f9a9ef5752 new cache subsystem 2011-02-12 10:33:12 +01:00
roberto@maverick64 6e5e357a36 suppress epoll_wait warning on reload 2011-02-11 05:36:37 +01:00
roberto@maverick64 0c4004ed14 fixed cache expire (again) 2011-02-11 05:10:42 +01:00
roberto@maverick64 008cd13c4f fixed cache expire 2011-02-10 18:39:29 +01:00
roberto@maverick64 7f3ba8324a fixed uwsgi.cache_exists 2011-02-10 18:37:09 +01:00
roberto@mmaverick64 e9002f2111 allow empty string in cache python api 2011-02-10 15:07:46 +01:00
roberto@maverick64 8f161909bb erlang_recv re-added 2011-02-10 09:48:08 +01:00
roberto@maverick64 1eea49a010 another bunch of erlang new features 2011-02-09 20:28:16 +01:00
roberto@maverick64 e62679cc26 another bunch of erlang features: atoms are mapped to unicode 2011-02-09 12:32:26 +01:00
roberto@sirius f8f9325cbc osx fixes 2011-02-08 16:10:51 +01:00
roberto@maverick64 fa1dd3fbfd the new (production-friendly) HTTP server 2011-02-08 16:04:41 +01:00
roberto@maverick64 0288313524 updated async stack 2011-02-07 10:28:11 +01:00
roberto@solarisexpress df18d66319 various solaris fixes 2011-02-05 22:29:54 +00:00
roberto@maverick64 e8eb86f998 merge 2011-02-05 15:17:13 +01:00
roberto@maverick64 534ff245f2 new Erlang subsystem 2011-02-05 15:16:22 +01:00
roberto@sirius 172654d409 fixed kqueue support 2011-02-04 09:48:38 +01:00
roberto@maverick64 4dea7cfb4b --fastrouter-use-base --fastrouter-use-pattern, multi fd wait in async stack 2011-02-04 09:09:58 +01:00
roberto@maverick64 f7955858bf better processes intercommunication 2011-02-03 21:02:26 +01:00
roberto@maverick64 fb5a5ddadd added uwsgi.erl in contrib 2011-02-03 16:25:56 +01:00
roberto@freebsd64 2bacd79c43 fixed a couple of leaks 2011-02-03 11:10:16 +01:00
roberto@freebsd64 6ca539497d add %d to magic table 2011-02-03 07:56:40 +01:00
roberto@mrspurr 78f3524fcb fixed kqueue 2011-02-02 19:20:46 +01:00
roberto@maverick64 937b2de41b the uWSGI fastrouter 2011-02-02 16:38:51 +01:00
roberto@maverick64 a07c79f7be moved listen queue to 100 by default 2011-01-30 05:55:34 +01:00
roberto@maverick64 9562c81590 the new spooler is working 2011-01-29 11:48:46 +01:00
roberto@maverick64 0a37852c5f ready to port the spooler to the new api 2011-01-29 10:08:35 +01:00
roberto@maverick64 460b78857c 64K are greater than 10K.... 2011-01-28 14:32:03 +01:00
roberto@maverick64 ac0e0a9f9e patch by Damjan Georgievski to allow compilation without xml 2011-01-27 18:20:07 +01:00
roberto@maverick64 740f16fe62 added exception for python cache_set 2011-01-27 18:04:35 +01:00
roberto@maverick64 faa0995c9c fix fd 0 usage 2011-01-27 15:41:47 +01:00
roberto@maverick64 dfff71a525 fixed xml and yaml parsing 2011-01-27 14:43:31 +01:00
roberto@maverick64 380d8cb3ea fixed --pyargv 2011-01-27 13:20:25 +01:00
roberto@maverick64 3f5aab2083 UWSGI_VASSAL_ support for Emperor, magic vars for configuration files 2011-01-27 09:27:55 +01:00
roberto@maverick64 2af5ef9016 added the uWSGI emperor 2011-01-26 16:29:49 +01:00
roberto@maverick64 f82dbfd300 support BROADCAST for clustering 2011-01-25 16:20:11 +01:00
roberto@maverick64 9cbf1c545d added uwsgi.fcgi() api function to allows uWSGI being a fastcgi proxy/router 2011-01-23 14:35:42 +01:00
roberto@maverick64 9ac598b9c3 better harakiri on threaded modes 2011-01-21 18:08:04 +01:00
roberto@maverick64 07dd0c2c0b Python3 support back to the future 2011-01-21 10:17:52 +01:00
roberto@maverick64 66b1cdd63c fixed threads startup 2011-01-19 07:59:59 +01:00
roberto@sirius 78980aab9e re-export uwsgi.env in non-threaded modes 2011-01-18 06:11:09 +01:00
roberto@sirius 0ac813be79 fixed reloading/respawn 2011-01-18 06:02:45 +01:00
roberto@maverick64 b09513bb2e xml,ini and yaml file can taken via http automagically 2011-01-17 22:02:13 +01:00
roberto@maverick64 c3e906f1ff threaded example 2011-01-16 09:32:58 +01:00
roberto@maverick64 666c1fec75 added support for cache_get, cache_set and call to PSGI 2011-01-15 19:05:05 +01:00
roberto@sirius 5d86ed46a3 fix psgi compilation 2011-01-15 17:43:01 +01:00
roberto@maverick64 2ee1c3ac32 allow append in build profiles 2011-01-15 14:26:46 +01:00
roberto@maverick64 ef530650c4 --dump-options 2011-01-15 14:07:58 +01:00
roberto@maverick64 fd1c7773ee gateways implementation -> proxy plugin 2011-01-15 12:56:10 +01:00
roberto@sirius 520ff8465b added exceptions counter 2011-01-14 14:49:45 +01:00
roberto@maverick64 170c66b000 fixed paste support: Plone threaded works perfectly 2011-01-13 18:10:13 +01:00
roberto@sirius c94206f7ba a huge list of threading fixes, we are near to ROCK SOLID threading mode 2011-01-13 11:42:59 +01:00
roberto@sirius f9158b39d8 pg async example 2011-01-11 10:38:20 +01:00
roberto@maverick64 daba88f947 --check-static option 2011-01-09 11:19:12 +01:00
roberto@maverick64 a7e4852621 --log-syslog option 2011-01-09 09:31:26 +01:00
roberto@maverick64 8a8d029357 lua build fixes 2011-01-09 08:07:51 +01:00
roberto@maverick64 b9621b620a reindent uwsgiconfig.py 2011-01-08 12:12:08 +01:00
roberto@debian32 cc0d656b86 fixed python multiapp loading 2011-01-08 12:01:19 +01:00
roberto@debian32 18080df77a fix for debian + python2.5 2011-01-08 11:26:45 +01:00
roberto@maverick64 059314e8f3 fixed uwsgi_rawlog 2011-01-08 09:47:26 +01:00
roberto@mrspurr 500e4e41fe uwsgi_rawlog() 2011-01-07 23:17:34 +01:00
roberto@sirius 8b21fb72b2 --logdate=strftime 2011-01-07 23:07:43 +01:00
roberto@mrspurr f8464ac733 fix debug build and better error reporting 2011-01-07 22:38:51 +01:00
roberto@sirius ac05ad1ef5 more tolerant uwsgi array parser 2011-01-07 16:03:29 +01:00
roberto@maverick64 ed5f501a19 improvements in multiple interpreter management 2011-01-06 19:45:43 +01:00
roberto@maverick64 515b9f2838 completely remove leave_open support (sorry that was a bad choice) 2011-01-06 11:48:10 +01:00
roberto@maverick64 d57ddff924 support for --mount option 2011-01-06 11:38:07 +01:00
roberto@maverick64 0a2da2a2ce jail-friendly setuid()/setgid() 2011-01-05 18:48:50 +01:00
roberto@maverick64 72f677bb0d working linux namespace support 2011-01-05 15:42:30 +01:00
roberto@sirius e176af1702 you can do RPC from uwsgicc 2011-01-04 17:42:48 +01:00
roberto@fiorenzo 6e748eafb9 the rpc plugin 2011-01-04 17:43:57 +01:00
roberto@sirius e11f84193a more rpc fixes 2011-01-04 16:02:44 +01:00
roberto@sirius ec4fbdff32 added generic functions for rpc 2011-01-03 20:52:23 +01:00
roberto@sirius d3ced01b43 added struct for uwsgi rpc 2011-01-03 20:25:00 +01:00
Riccardo Magliocchetti 64468ae69e uwsgicc: fix typo in template 2011-01-03 16:28:33 +01:00
Riccardo Magliocchetti 79d75e832f uwsgicc: template beautyfication, thanks to Simone Marcarino 2011-01-03 16:25:28 +01:00
roberto@sirius ae41506764 send log mesages via uwsgicc 2011-01-03 12:31:12 +01:00
roberto@fedora64 f0bb80b9b8 timerfd fix 2011-01-02 21:48:14 +01:00
roberto@solarisexpress 1955d63cad added support for solaris port event subsystem 2011-01-02 21:40:21 +00:00
roberto@mrspurr 4b2fdb3d30 OSX fixes 2011-01-02 18:53:14 +01:00
roberto@fedora64 d586fe2fb3 another test for linux namespace. They works perfectly 2011-01-02 17:51:50 +00:00
roberto@fedora64 924074175e using fedora14 as base for linux namespace support 2011-01-02 18:20:20 +01:00
roberto@fedora64 a64cbea6e8 old glibc fixes 2011-01-02 18:19:11 +01:00
roberto@sirius 9ef571b4fa allow usage of Linux namespace feautures 2011-01-02 12:15:52 +01:00
roberto@sirius 67666a1788 test for logrotation based on size 2011-01-02 10:43:00 +01:00
roberto@sirius e1daf1d360 add skel version of the uWSGI Control Center (flask+jinja2 app) 2011-01-01 12:42:17 +01:00
roberto@sirius 94f3b715e5 fixed cluster node names 2011-01-01 12:03:12 +01:00
roberto@sirius 31892a69df better cluster node management 2011-01-01 11:53:06 +01:00
roberto@sirius a43bc93492 add cluster_fd to master queue 2011-01-01 10:38:09 +01:00
roberto@sirius 8dd9149624 OSX build fixes 2010-12-28 10:10:37 +01:00
roberto@fiorenzo e422f7311a added register_signal tu lua api 2010-12-26 20:07:41 +01:00
roberto@fiorenzo bb093c7614 various Linux fixes 2010-12-26 18:33:12 +01:00
roberto@mrspurr 5186936c3a refactored signal framework 2010-12-26 10:33:50 +01:00
roberto 4269f0483f Leonid Borisenko patch for use absolute path as build profile 2010-12-26 09:39:30 +01:00
roberto@sirius 09f49bb5d6 added the list of healtchecks that will be available by default 2010-12-21 21:18:25 +01:00
roberto@sirius a054f2b968 various fixes for sendfile() and rack plugin 2010-12-21 08:38:43 +01:00
riccardo@unbit 149cf74fe6 compile on git Linux kernel 2010-12-21 07:23:51 +01:00
Riccardo Magliocchetti 123b3fd4b1 buildconf: update unbitstaff profile config 2010-12-20 12:07:28 +01:00
roberto@storm 2e18db2352 added inherit option for buildconf 2010-12-20 10:09:01 +01:00
roberto@freebsd64 d7c2856041 fixed timers on FreeBSD 2010-12-19 15:04:30 +01:00
roberto@mrspurr 07a87bdff3 fixed file monitor and timers on OSX 2010-12-19 14:58:01 +01:00
roberto@centos64 fca3c51351 fixed old linux kernel support 2010-12-19 13:05:37 +01:00
roberto@fiorenzo 70db2befb5 fully working file monitor and timer support for Linux/epoll 2010-12-19 12:50:36 +01:00
roberto@centos64 057fcb0693 remove timerfd() support for Linux kernel < 2.6.25 2010-12-19 09:18:45 +01:00
roberto@fiorenzo 051dc77712 move from poll() to epoll() on linux master.c 2010-12-18 16:48:43 +01:00
roberto@mrspurr 784191f127 moved master from poll() to kqueue() on OSX and *BSD 2010-12-18 14:58:44 +01:00
roberto@mrspurr 3454279ac7 thundering herd is solved even on OSX 2010-12-17 21:07:17 +01:00
roberto@fiorenzo e335cf5e96 solve the thundering herd bug 2010-12-17 20:58:57 +01:00
roberto@fiorenzo 44277b38cd leave_open should not be available for WSGI requests. It overcomplicates things 2010-12-17 18:05:41 +01:00
roberto@sirius 31bd3fa6c4 use uwsgi_signal framework for better/portable --no-orphans 2010-12-17 17:13:45 +01:00
roberto@freebsd64 3104f915e5 use umtx_* locking functions on FreeBSD 2010-12-17 13:44:33 +01:00
roberto@mrspurr 860a017060 remove a bit of pollution in the logs 2010-12-17 08:47:01 +01:00
roberto@mrspurr 23f00ec864 fixed mod_uwsgi for deflate filter 2010-12-16 22:56:24 +01:00
Riccardo Magliocchetti 69fd8aaa36 python plugin: prefer LIBDIR for LDFLAGS
Try to use LIBDIR instead of PREFIX as directory where to look for
python libraries to link with.
2010-12-16 18:41:35 +01:00
roberto@sirius 7ea77afb38 added base for lb (load-balancer) framework 2010-12-16 18:27:07 +01:00
roberto@sirius da577ef923 fixed poll() usage 2010-12-16 18:25:33 +01:00
roberto@sirius 26cae83139 build fix without udp 2010-12-15 18:37:56 +01:00
roberto@sirium a8c4f6bffe the cache can now contains upto 0xFFFFFFFF items, added uwsgi.cache_exists to the api 2010-12-15 10:47:01 +01:00
roberto@sirius eff66ef08f added router.lua 2010-12-13 18:16:15 +01:00
roberto@sirius 381da45196 completed caching framework api 2010-12-13 18:15:11 +01:00
roberto@goyle 43c347d20e use luaL_newstate 2010-12-12 18:29:03 +01:00
roberto@goyle fadee3242f LuaJit works perfectly and FAAAAST 2010-12-12 18:22:30 +01:00
roberto@goyle 27fda41398 first implementation of multi-request per connection (need optimization) 2010-12-12 17:37:28 +01:00
roberto@sirius f6f8dbecc0 better uwsgi_waitfd for nailed connections 2010-12-12 11:26:14 +01:00
roberto@fiorenzo 902991daa4 OOB for nailed connections 2010-12-12 11:22:39 +01:00
roberto@sirius 245ab6d815 various test for trying to allow pre-connected requests 2010-12-11 20:08:23 +01:00
roberto 96700a49e3 ok, i am stupid, added cache.c 2010-12-10 21:51:25 +01:00
roberto@sirius b75ba73264 caching infrastructure (need optimizations) 2010-12-09 19:54:37 +01:00
roberto@sirius 7d6f93d1cb uwsgi.recv_block and uwsgi.recv_frame 2010-12-07 05:38:57 +01:00
roberto@mrspurr 9aaf36141e extended the uwsgi api to allow easy implementation of websockets servers 2010-12-06 13:48:23 +01:00
roberto@mrspurr 68c6dd13b8 fixed fd close on uwsgirouter.py 2010-12-05 18:37:25 +01:00
roberto@mrspurr 8ac5176c4c fixed async routing 2010-12-05 10:52:01 +01:00
roberto@mrspurr fd49ba36eb more custom routing example and optimizations 2010-12-05 10:45:13 +01:00
roberto@mrspurr 047aac8426 export uwsgi.is_connected 2010-12-05 08:17:29 +01:00
roberto@mrspurr 103e7415f3 various threading fixes 2010-12-04 18:30:22 +01:00
roberto@mrspurr b64911d20e fixed uwsgirouter.py 2010-12-04 17:32:31 +01:00
roberto@mrspurr 2f970ce585 various async optimizations and routing python examples 2010-12-04 13:43:12 +01:00
roberto@sirius 47801964c4 merge 2010-12-03 18:27:14 +01:00
roberto@sirius da8eb4ad1b add uwsgirouter.py test script for upcoming custom routing 2010-12-03 18:26:29 +01:00
roberto@fiorenzo 320a2b8a7f various fixes 2010-12-01 13:35:40 +01:00
roberto@fiorenzo eab271e1e1 fixed a stupid bug 2010-11-30 14:27:39 +01:00
roberto@mrspurr d161962db1 pass custom apache variables via SetEnv 2010-11-28 09:54:31 +01:00
roberto@fiorenzo 36a3b408cf --proxy-node @self 2010-11-27 06:58:46 +01:00
roberto@fiorenzo 10af04becc uWSGI proxy is now cluster-aware 2010-11-27 06:06:22 +01:00
roberto@fiorenzo 4db259900e better virtual ip automagic 2010-11-27 05:37:29 +01:00
roberto@mrspurr fe4ba8130d cluster membership improvements 2010-11-27 04:58:20 +01:00
roberto@silente 4c4f92bad2 big endian fixes 2010-09-10 06:58:12 +02:00
roberto@fiorenzo 6f726d6370 wait forever for cluster configuration 2010-11-25 16:26:13 +01:00
roberto@fiorenzo c4f50fccfb various fixes 2010-11-25 16:21:25 +01:00
roberto@sirius 7e2daed0e8 fixed cluster logging (again) 2010-11-25 11:26:39 +01:00
roberto@sirius e4d3f79492 fixed cluster reloading 2010-11-25 11:10:58 +01:00
roberto@sirius d128a958cf cluster realod and logging 2010-11-25 11:07:27 +01:00
roberto@fiorenzo 0024bf56be fixed python module split 2010-11-25 09:53:56 +01:00
roberto@sirius 1d03fdee64 use recvfrom() instead of read() 2010-11-25 09:44:07 +01:00
roberto@sirius 152fb9cde9 cluster announce 2010-11-25 08:51:54 +01:00
roberto@mrspurr e6c5710657 use getifaddrs() instead of ioctl() 2010-11-25 07:33:47 +01:00
roberto@fiorenzo df0b3f7eb5 configuration can now be taken from the cluster nodes automagically 2010-11-24 18:55:15 +01:00
roberto@sirius f420bf3266 save multicast addr structure for performance 2010-11-24 18:28:54 +01:00
roberto@sirius 7a262159dc cluster configuration 2010-11-24 13:25:30 +01:00
roberto@fiorenzo 3dec2821f4 various new clustering implementations 2010-11-24 11:42:15 +01:00
roberto@sirius 652a9c5825 various multiapp and virtualhosting fixes 2010-11-22 11:15:02 +01:00
roberto@debian32 79c30fed23 added --manage-script-name 2010-11-21 15:21:06 +01:00
roberto 5ab8d800d8 more powerful --pymodule-alias directive 2010-11-20 17:57:48 +01:00
roberto@sirius 0beb7108e4 added python module aliases 2010-11-20 12:47:52 +01:00
roberto@sirius 356d59a38d fixed setup.py 2010-11-18 10:06:51 +01:00
roberto@sirius 87853d0ca3 fixed fiber support for kqueue 2010-11-17 15:38:48 +01:00
roberto c9056630b7 Fiber support is now working (no fd monitoring and sleep yet) 2010-11-17 15:06:31 +01:00
roberto@sirius a4120efabe added experimental fiber support for ruby1.9 2010-11-17 07:42:51 +01:00
roberto@sirius 0bd017f722 fixed plugin initialization 2010-11-17 05:13:42 +01:00
roberto@fiorenzo 5a738fba8a i am afraid that ruby will never run on uGreen, time to pass to fibers 2010-11-16 17:53:15 +01:00
roberto@fiorenzo 856fd8b00f towards a better uGreen (with ruby support) 2010-11-16 10:06:19 +01:00
roberto@mrspurr d60d90afe3 various uGreen fixes 2010-11-15 21:55:55 +01:00
roberto@mrspurr 0132c00f41 fix after_request 2010-11-15 18:34:04 +01:00
roberto@mrspurr aebc637f2b new async example 2010-11-15 14:00:09 +01:00
roberto@fiorenzo d4c4643ddc YAML config file support 2010-11-14 20:20:41 +01:00
roberto@mrspurr aea66427f1 various fixes for magic options and new --remap-modifier 2010-11-14 07:18:49 +01:00
roberto@mrspurr 0376c804f9 reintroduced magic configuration 2010-11-13 20:09:54 +01:00
roberto@nexenta32 4a99069a4e NexentaOS is officially supported 2010-11-13 08:36:41 +01:00
roberto@freebsd64 e3bbcc5c84 freebsd notes for JVM 2010-11-13 08:03:01 +01:00
roberto@freebsd64 6fc40077be FreeBSD fixes 2010-11-13 07:04:51 +01:00
roberto@longshot 040d1a9d0b new amazing option: --upload-progress 2010-11-12 08:28:11 +01:00
roberto@longshot 8a121ada9d various fixes 2010-11-12 05:45:37 +01:00
roberto@mrspurr 373c45c7d4 use symlinks to automagically load plugins 2010-11-12 04:08:50 +01:00
roberto@mrspurr 3e7992d0ac added perl embedded module 2010-11-08 18:14:36 +01:00
roberto@fiorenzo 4a4455cd16 fixed jvm/jwsgi compilation on Linux 2010-11-08 16:38:44 +01:00
roberto@mrspurr 444e8d2637 utest.java, jwsgi example 2010-11-08 16:21:42 +01:00
roberto@mrspurr bcd6f7de32 jwsgi fake protocol support, better JVM api 2010-11-08 15:58:06 +01:00
roberto@mrspurr 5346ca68f9 added JVM core plugin 2010-11-07 09:15:20 +01:00
roberto@mrspurr ab83b1c7aa fixed psgi compilation 2010-11-06 08:13:46 +01:00
roberto@fiorenzo bc0eec51b4 PSGI streaming support. WebGUI is running pretty well 2010-11-05 16:02:18 +01:00
roberto@sirius 187100f2bf uwsgi.opt dictionary 2010-11-04 17:52:38 +01:00
roberto@sirius 2e4e23f63f merge 2010-11-03 19:34:55 +01:00
roberto@sirius 6f1f990f69 threads support for perl 2010-11-03 19:34:08 +01:00
roberto@mrspurr.local 75d2109254 added wt.join() in urack.rb 2010-11-03 07:35:25 +01:00
roberto@mrspurr cada9ed520 add threads support in urack.rb 2010-11-03 07:08:34 +01:00
roberto@sirius 6f3fe261d0 added buildconf/psgi.ini 2010-11-01 20:42:35 +01:00
roberto@sirius c78c0a2798 PSGI fixes 2010-11-01 18:14:38 +01:00
roberto@sirius 6249c25411 various virtual hosting fixes 2010-11-01 08:53:20 +01:00
roberto@shadowcat 36fc098c5d various ruby 1.9 fixes 2010-10-31 08:06:36 +01:00
roberto@haiku 070e84125a a bunch of haiku fixes 2010-10-29 19:34:22 +00:00
roberto@sirius aa50669237 python, ping and nagio are embedded by default 2010-10-29 13:53:05 +02:00
roberto@sirius 32ab7e79ca python fixes and optimizations 2010-10-29 13:02:59 +02:00
roberto@sirius 8971539550 pluginize ugreen and nagios 2010-10-29 10:36:58 +02:00
roberto@sirius df52dfd31f uwsgi.h vacuum 2010-10-29 08:14:03 +02:00
roberto@sirius 61756d45a2 even erlang.c was accidentally removed 2010-10-29 08:05:05 +02:00
roberto@sirius fe7a5eb5d3 reintroduce accidentally-removed mod_uwsgi.c 2010-10-29 07:47:16 +02:00
roberto@sirius e744d36fa0 investigating ruby 1.9 fiber and pluggable uWSGI loop 2010-10-28 09:25:31 +02:00
roberto@sirius 2108c85f7e trying to map ruby1.9 pthreads in uWSGI pthreads 2010-10-27 08:48:21 +02:00
roberto@mrspurr e2c405fe02 merge 2010-10-26 06:44:45 +02:00
roberto@sirius 8668b9a614 applied Dan Loewenherz stylish patch 2010-10-26 06:43:40 +02:00
roberto@fiorenzo 87ae9d780e ruby1.9 support 2010-10-25 20:11:40 +02:00
roberto@fiorenzo d0c071e759 pyargv fixes 2010-10-25 08:59:50 +02:00
roberto@fiorenzo 1a6324e825 python24, python27, python20, python31, python32 plugins 2010-10-25 08:51:52 +02:00
roberto@sirius bee3ba73d8 python25, python26 plugins 2010-10-25 08:47:31 +02:00
roberto@sirius 8dde9c2984 multiple python plugin version with the same server core 2010-10-25 08:34:10 +02:00
roberto@sirius 094d4128dc lua sputnik test with threads 2010-10-24 22:05:42 +02:00
roberto@sirius da25f77326 report correct response size in Lua plugin 2010-10-24 12:52:09 +02:00
roberto@sirius c5073f7056 Lua support improvement 2010-10-24 12:28:43 +02:00
roberto@sirius c461d2e6b3 lua plugin ported to the new api 2010-10-24 08:28:47 +02:00
roberto@sirius 6adca06764 fixed python embedded module, first refactoring of the spooler, better rack compliance 2010-10-23 21:59:43 +02:00
roberto@fiorenzo 746f645e6c disable LDAP by default even on rack plugin 2010-10-23 13:19:49 +02:00
roberto@fiorenzo e6ef84bb4b disable LDAP by default 2010-10-23 13:18:44 +02:00
roberto@sirius 17975acb45 modular buildconf 2010-10-23 13:11:13 +02:00
roberto@fiorenzo 4b81ff61eb fix plugins loading 2010-10-23 08:48:41 +02:00
roberto@fiorenzo bf868ff636 build system improvements 2010-10-23 08:44:22 +02:00
roberto@mrspurr c777a0f926 support for rack to_path and ruby GC frequency. Now Radiant works too 2010-10-23 08:41:50 +02:00
roberto@fiorenzo 7a7f499f63 Typo 5 is working \!\!\! 2010-10-22 23:12:28 +02:00
roberto@sirius b22b46b153 another bunch of rails fixes 2010-10-22 21:26:12 +02:00
roberto@sirius bbd8ea51c0 better ruby plugin, we are near to a beta version 2010-10-22 18:40:22 +02:00
roberto@sirius e1969d92ab python and ping plugins now embedded by default 2010-10-21 22:35:38 +02:00
roberto@fiorenzo e8e8b6902c fix compilation on Linux 2010-10-21 16:26:51 +02:00
roberto@sirius 7041a9fa45 xml parsing and pluginized getopt_long stabilization 2010-10-21 11:45:49 +02:00
roberto@sirius bfbca5bc96 ping plugin 2010-10-20 21:56:51 +02:00
roberto@sirius be183bf07f add new files to the tree 2010-10-20 21:55:37 +02:00
roberto@sirius f7aa451af4 uWSGI is now language agnostic, all can be pluginized, python included 2010-10-20 21:54:19 +02:00
roberto@sirius 53ccd3d4b8 new option --http-modifer1 2010-10-17 12:25:50 +02:00
roberto@sirius aaa6033c2a --log-sendfile 2010-10-16 09:09:54 +02:00
roberto@sirius 345c8ed962 another PSGI fixes round 2010-10-14 15:37:01 +02:00
roberto@sirius 9e0c7a3bdc updated PSGI plugin for 0.9.7-dev 2010-10-14 11:43:02 +02:00
Riccardo Magliocchetti 616ed04c79 Show spooler jobs in django admin 2010-10-13 11:00:22 +02:00
roberto@mrspurr 441fb06129 uwsgi.post_fork_hook 2010-10-13 07:17:00 +02:00
roberto@fiorenzo 4b92ba5cbe dynamic apps are now supported in threaded modes 2010-10-12 09:18:36 +02:00
roberto@mrspurr 13932641e5 pthread_atfork() 2010-10-12 08:23:37 +02:00
roberto@sirius 85752ccf2c add pthread locking for init_uwsgi_app 2010-10-12 07:59:37 +02:00
roberto@mrspurr 6d9b753735 various pyloaders fixes 2010-10-11 15:00:15 +02:00
roberto@fedora32 6b7e3a6429 better (race-condition-free) request counters 2010-10-10 07:48:05 +02:00
roberto@fedora32 6ef043c40a reduce GIL impact on yielding apps 2010-10-09 19:20:50 +02:00
roberto@mrspurr 9704abd3e4 apache2 right socket RST handling 2010-10-09 11:27:02 +02:00
roberto@sirius 723acced71 --close-on-exec option 2010-10-06 12:16:15 +02:00
roberto@mrspurr ca43ad0a91 various stabilization fixes 2010-10-05 05:48:20 +02:00
roberto@fiorenzo 17e2dbf85b renamed async_switches to switches 2010-10-04 17:51:22 +02:00
roberto@fiorenzo 7e40c902e6 various threading fixes 2010-10-04 17:24:59 +02:00
roberto@fiorenzo 074d0b95d1 theading support improvements 2010-10-04 14:01:56 +02:00
roberto@mrspurr 36c8a8c675 initial threading mode support 2010-10-03 22:49:22 +02:00
roberto@mrspurr 00a70c2ea2 new 0.9.7 codebase for app loading is complete 2010-10-02 18:34:55 +02:00
roberto@sirius 2bf20631e1 stabilization fixes 2010-10-01 11:50:00 +02:00
roberto 74b9579531 2 new loaders LOADER_CALLABLE and LOADER_STRING_CALLABLE 2010-10-01 10:02:46 +02:00
roberto@sirius 5a152d1bae another big loader refactoring 2010-10-01 07:45:33 +02:00
roberto@sirius 551152ade9 new loader refactoring 2010-09-30 18:13:40 +02:00
roberto@sirius 42c5b356f5 add a note to add dynamic loaders 2010-09-30 14:10:24 +02:00
roberto@sirius 33bd68c44c compilation fix 2010-09-30 14:08:05 +02:00
roberto@sirius 46b715fcc3 first merge from 0.9.6.5 (headers management still missing) 2010-09-29 08:46:38 +02:00
roberto@mrspurr b004168401 automagic recognition of the last parameter by extension 2010-09-28 07:08:04 +02:00
roberto@fiorenzo 6cebf19468 fix --wsgi-file and --pythonpath cooperation 2010-09-27 17:05:58 +02:00
roberto@mrspurr fb73324d25 more code refactoring 2010-09-26 12:17:04 +02:00
roberto@mrspurr 94624c7e52 another one destructive commit, move master to dedicated file 2010-09-26 09:11:57 +02:00
roberto@fiorenzo c4033a5970 http fix 2010-09-25 09:16:44 +02:00
roberto@fiorenzo e66e56b593 get_linux_tcp_info() refactoring 2010-09-25 08:24:16 +02:00
roberto@fiorenzo b408423b03 conditional logging 2010-09-25 08:09:34 +02:00
roberto@fiorenzo c37a2d7842 advanced socket binding and system reloading, need optimizations for single socket 2010-09-24 20:48:52 +02:00
roberto@mrspurr da339bb3a9 remove profiler 2010-09-19 09:56:14 +02:00
roberto@mrspurr f30be82926 First destructive commit for 0.9.7, big python loaders refactoring 2010-09-18 16:41:03 +02:00
roberto@mrspurr f04aa843ff fix argument count check 2010-09-18 08:41:16 +02:00
roberto@fiorenzo 5c42c27cd4 the master process will signal the overload of the listen queue on linux tcp sockets 2010-09-17 10:31:58 +02:00
roberto@fiorenzo fc744f5719 another cgroup fix 2010-09-16 19:09:24 +02:00
roberto@fiorenzo 855c963fb3 working cgroup support 2010-09-16 18:39:33 +02:00
roberto@fiorenzo dd932b0a78 OK. The Web3 test app works 2010-09-16 09:40:33 +02:00
roberto@fiorenzo e4e75a4d64 merge 2010-09-16 09:03:12 +02:00
roberto@fiorenzo ef0464dba6 Web3 support 2010-09-16 09:01:41 +02:00
roberto@fiorenzo bc2b49c8e8 uWSGI 0.9.7-dev started. Cgroup support and initial Web3 support 2010-09-16 09:00:32 +02:00
roberto@sirius 409ce34a0b uWSGI 0.9.6.2 2010-09-15 09:18:02 +02:00
roberto@sirius 89158b0509 better virtual host mode 2010-09-14 17:54:33 +02:00
roberto@sirius 86b90b8b16 fix a regression in PYTHONPATH management under INI/PASTE 2010-09-14 15:14:08 +02:00
roberto@sirius fe4c88c1c5 uWSGI 0.9.6.1 2010-09-12 09:26:54 +02:00
roberto@sirius f0f08728ab more verbose callable loading error 2010-09-12 08:57:43 +02:00
roberto@mrspurr 5259c803e8 dynamic app optimizations 2010-09-12 08:38:43 +02:00
roberto@haiku c6e5e533fa memory_report for Haiku 2010-09-12 07:41:52 +00:00
roberto@sirius 21e4cc19c8 export x-wsgiorg.uwsgi.version in WSGI env 2010-09-11 17:40:52 +02:00
roberto@haiku 045001fd6c fix Haiku usage of AF_UNIX 2010-09-11 16:17:11 +00:00
roberto@sirius eadaf3407a build system fixes 2010-09-11 14:51:51 +02:00
roberto@haiku 7434d3113c Haiku OS and gcc 2.95 support 2010-09-11 14:49:02 +00:00
roberto@sirius ab9fade14d fix no-strict-aliasing 2010-09-10 20:46:19 +02:00
roberto@sirius 5be63b02e8 fixed a typo 2010-09-10 17:25:34 +02:00
roberto@sirius 7694c38021 less verbose on SNMP management 2010-09-10 17:21:14 +02:00
roberto@sirius d13f7a45b9 ready for 0.9.6.1 2010-09-10 17:04:34 +02:00
roberto@sirius 44e8f01671 log request on SIGPIPE and HARAKIRI 2010-09-10 15:47:58 +02:00
roberto@sirius 09a8104256 protocol parsing optimization 2010-09-10 13:31:24 +02:00
roberto@fiorenzo 09d8ac2656 encoding fixes in uwsgiconfig.py 2010-09-10 11:48:11 +02:00
roberto@mrspurr c5877df60c fix --logto usage in cherokee 2010-09-10 08:35:34 +02:00
roberto@sirius 0f2fff31ee new --eval config option 2010-09-09 14:06:51 +02:00
roberto@sirius ebcdd294aa allow --pp as --pythonpath 2010-09-09 11:59:15 +02:00
roberto@sirius d663e10584 add -fno-strict-aliasing only for python 2.x or gcc < 4.3 2010-09-08 18:20:31 +02:00
roberto@sirius 048299e1d3 new spooler optimizations 2010-09-08 17:18:52 +02:00
roberto@sirius 96aaa9fa3f spooler fixes and uwsgi.spooler_jobs() 2010-09-08 17:00:32 +02:00
roberto@netbsd 015f17192c fix another strict check 2010-09-08 12:24:44 +02:00
roberto@silente f0ac801ecd support gcc < 4 2010-06-23 23:15:47 +02:00
roberto@fiorenzo f3b207c024 get return value of write() in http.c 2010-09-08 09:47:57 +02:00
roberto@freebsd64 0379e200b6 -O2 is now officially supported 2010-09-08 09:43:53 +02:00
roberto@voldemort abe6168bc3 uwsgi.is_a_reload 2010-09-07 12:27:38 +02:00
roberto@voldemort a6aa2c31c6 fixed PASTE=False compilation 2010-09-07 10:01:34 +02:00
roberto@voldemort f35ad319cf other 'c strict' fixes 2010-09-06 09:03:42 +02:00
riccardo@montag 527ad44463 fix osx compilation 2010-09-05 14:00:55 +02:00
riccardo@montag b245307f55 stricter compiler flags 2010-09-05 13:58:24 +02:00
roberto 9285b403d9 SNMP test 2010-09-05 12:47:21 +02:00
roberto@voldemort 58b72a4c80 another subprocess fix 2010-09-05 11:51:50 +02:00
roberto@sirius 73f706723e better handling of subprocesses 2010-09-03 15:46:33 +02:00
roberto@sirius 4d22f7171f fix a little comment 2010-09-03 12:20:11 +02:00
roberto@sirius b60e22b4e5 default fallback for unknown SCRIPT_NAME 2010-09-03 12:19:27 +02:00
roberto@sirius 7310b73289 fixed stupid bug in INI parsing 2010-09-03 08:14:17 +02:00
roberto@sirius 4fa61c225a uWSGI 0.9.6 2010-08-29 06:51:52 +02:00
roberto@sirius 63b41856e5 Changelog for 0.9.6 2010-08-28 19:58:55 +02:00
roberto@sirius ed1e668240 NetBSD latest fixes. Ready for 0.9.6 release 2010-08-28 19:36:55 +02:00
roberto@freebsd64 e3a7e70180 fix pidfile on HTTP mode 2010-08-28 13:51:38 +02:00
roberto@freebsd64 9f0b20c8d2 use getsockname() in vacuum() 2010-08-28 13:16:22 +02:00
roberto@freebsd64 68aff372ce HTTP final fixes, better reloading system, better cwd detection, powered up vacuum 2010-08-28 13:00:21 +02:00
roberto@sirius 38cfa72318 close ini file 2010-08-27 11:07:35 +02:00
roberto@sirius 31047e1e10 fixes for --file and shebang support 2010-08-27 07:32:44 +02:00
roberto@sirius bbb90296bb applied Leonid Borisenko patch to allow -O2 and -fno-strict-aliasing CFLAGS 2010-08-27 06:21:43 +02:00
roberto@sirius 00c6aa2f65 0.9.6-rc2 2010-08-26 17:08:15 +02:00
roberto@sirius 720da09631 xmlconf fixes 2010-08-26 15:33:25 +02:00
roberto@fiorenzo 47f7c09b97 add empty QUERY_STRING in http server 2010-08-26 14:55:39 +02:00
roberto@sirius cb5704da10 --callable 2010-08-26 14:09:15 +02:00
roberto@fiorenzo c64356b231 uwsgi packet watermark in HTTP server 2010-08-26 11:38:48 +02:00
roberto@sirius 2acd2f5224 another solaris hack 2010-08-26 11:01:57 +02:00
roberto@sirius ba251f8e3d another solaris fix 2010-08-26 10:09:40 +02:00
roberto@sirius 48019f9044 first round of http fixes 2010-08-26 10:06:17 +02:00
roberto@sunsparc d9a1f2448c solaris fixes 2010-08-26 09:33:23 +02:00
roberto@ubuntu64 553a947c2d fix routing 2010-08-26 08:43:28 +02:00
roberto@sirius 736aedfa89 add --ini-paste commodity and removal of strlc* functions 2010-08-26 08:36:44 +02:00
roberto@sirius 6184acc727 updated --help 2010-08-25 20:00:10 +02:00
roberto@sirius f0d96b03fa added --ping and --ping-timeout 2010-08-25 19:21:31 +02:00
roberto@sirius 14bf840eef fix urack.rb upload 2010-08-24 16:44:32 +02:00
roberto@sirius 7ea08093c7 uWSGI 0.9.6-rc1 2010-08-24 08:41:25 +02:00
roberto@sirius 8eb8d07151 ready for rc1 ? 2010-08-24 08:37:24 +02:00
roberto@sirius cdd95b434e http and sendfile fix 2010-08-24 08:33:03 +02:00
roberto@ubuntu64 82cbcea886 Linux has no strlcat 2010-08-23 18:51:02 +02:00
roberto@silente ea54a05fc3 OpenBSD fixes by Piotr Sikora 2010-06-08 07:43:48 +02:00
roberto@ubuntu64 eba39dcd67 LDAP support 2010-08-23 14:27:49 +02:00
roberto@ubuntu64 d71ea1404d allow non-numeric uid and gid 2010-08-22 18:31:18 +02:00
roberto@ubuntu64 0f0d5b2a5f safer automatic unix socket and --vacuum option 2010-08-22 18:02:09 +02:00
roberto@mrspurr 10a75ef848 support key-only value (without '=') in ini files 2010-08-22 08:10:23 +02:00
roberto@sirius 4bd9bf8917 remove REMOTE_USER in http server 2010-08-19 08:16:42 +02:00
roberto@mrspurr 323da1299e another fix for PEP 333 file_wrapper compatiblity 2010-08-18 19:42:21 +02:00
roberto@mrspurr 75d08898b4 http server fixes 2010-08-18 16:37:10 +02:00
roberto@sirius 5e47796a02 something to fix in utf8 handling [2] 2010-08-17 14:13:04 +02:00
roberto@sirius 0ade5aba0a something to fix in utf8 handling 2010-08-17 14:12:52 +02:00
roberto@sirius f7b1ad8cb0 add a little comment 2010-08-17 14:10:52 +02:00
roberto@sirius 3bd147e687 fixed random seeding (thanks to Jonas Borgström) 2010-08-17 14:04:44 +02:00
roberto@voldemort 66c99e257f fix pidfile (will be written at server startup and only if it is not a reload) 2010-08-15 18:55:48 +02:00
roberto@voldemort 8407a5921b warn user about harakiri without post buffering 2010-08-15 18:52:20 +02:00
roberto@voldemort 5f36987827 applied Jonas Borgström patch for lighttpd REMOTE_USER 2010-08-15 18:40:09 +02:00
roberto@voldemort ede1622368 fix a stupid bug in apache module 2010-08-14 15:59:36 +02:00
roberto@voldemort a28dfb790e does a fix for not reading post data really exists ? 2010-08-14 08:17:33 +02:00
roberto@voldemort 3711cbbd61 ini file improvement 2010-08-14 08:13:04 +02:00
roberto@voldermort c9ef6281ff added --catch-exceptions, it will print app exceptions to your browser 2010-08-13 17:37:34 +02:00
roberto@voldemort 604ea6fd57 INI files support 2010-08-13 15:46:37 +02:00
roberto@longshot 41dfcaa705 added --chdir2 2010-08-11 17:35:14 +02:00
roberto@sirius daa41d4a51 fixed --unbit PYLIB_PATH 2010-08-11 09:20:22 +02:00
roberto@sirius ded4450a70 http build option 2010-08-11 09:18:50 +02:00
roberto@sirius cd0be56bbe fixed --unbit 2010-08-11 08:59:12 +02:00
roberto@sirius 0bf7b64b46 mjpeg streaming example using uwsgi.sendfile() 2010-08-08 15:43:24 +02:00
roberto@sirius 215d2e7055 full PEP 333 compliant file_wrapper and advanced uwsgi.sendfile() 2010-08-08 15:41:34 +02:00
roberto@voldemort 2b5b0cf1bc fix spooler stdin 2010-08-05 12:21:34 +02:00
roberto@voldemort 67231da4a9 added uwsgi.env 2010-08-03 18:03:34 +02:00
roberto@sirius 8c25b38470 fix UNBIT compilation 2010-07-29 10:19:06 +02:00
roberto@sirius 08bbe0cd30 MINTERPRETERS build fixes 2010-07-28 14:37:47 +02:00
roberto@sirius 9f9f63fe2f UDP build fixes 2010-07-28 14:31:58 +02:00
roberto@sirius 997bd63cc3 add LD_RUN_PATH option 2010-07-27 11:43:22 +02:00
roberto@siris 6a566d9dca fix static compilation 2010-07-27 11:40:54 +02:00
roberto@sirius d2e743a800 rack/rails plugin base added. NOT USABLE 2010-07-27 08:47:27 +02:00
roberto@sirius 2fedb175b4 disable WSGI2 flag by default 2010-07-21 11:02:18 +02:00
roberto@sirius 6c5e25dbfe sendfile fix 2010-07-20 17:56:54 +02:00
roberto@fiorenzo 94fd3f0bfd mega.xml example 2010-07-20 15:45:19 +02:00
roberto@fiorenzo ca169b05fb xml id, working multi-thread http server, --env support 2010-07-20 15:43:09 +02:00
roberto@voldemort 10ea1fee6e a bunch of fixes 2010-07-19 12:22:16 +02:00
roberto@sirius d7b8704165 conditional paste inclusion and django_admin fix 2010-07-14 16:34:56 +02:00
roberto@voldemort 0f774b840c quick_callable, --chdir and (broken) multithread http.c 2010-07-14 00:19:00 +02:00
roberto@sirius 81521a314b embedded HTTP server for easy development 2010-07-12 18:34:16 +02:00
roberto@sirius 37ee7f8908 better management of SCRIPT_NAME 2010-07-07 11:47:39 +02:00
roberto@sirius 309648f68b more verbose spooler 2010-07-06 10:44:00 +02:00
roberto@sirius 5cfa65d04e Python 2.7 support 2010-07-06 09:20:41 +02:00
roberto@voldemort e73c8194a0 64 bit fixes [2] 2010-06-28 10:37:46 +02:00
roberto@voldemort 00a3f6ae7f 64 bit fixes 2010-06-28 10:36:02 +02:00
roberto@voldemort b7edaa68c8 various fixes from 0.9.5.2 2010-06-26 22:37:46 +02:00
roberto@sirius 2877ba54de better routing 2010-06-23 19:55:41 +02:00
roberto@mrspurr f74a19a71a preliminary routing support (PCRE needed) 2010-06-21 17:42:03 +02:00
roberto@sirius 3da5238ee5 PSGI embedded support 2010-06-14 16:59:50 +02:00
roberto@fedora-arm 567dd36592 remove UGREEN on arm 2010-06-11 02:48:53 -04:00
roberto@sirius b48062a026 add 0x to hex debug printing 2010-06-10 08:34:02 +02:00
roberto@sirius b039cb713f VirtualHosting mode and UWSGI_PYHOME uwsgi var 2010-06-10 08:05:11 +02:00
roberto@sirius 8e987ffa18 proposed WSGI2.0 response support 2010-06-08 17:44:43 +02:00
roberto@mrspurr 52502342e0 fix copyright year 2010-06-03 12:59:48 +02:00
roberto@mrspurr cb9e3c22f9 added apache2 mod_Ruwsgi 2010-06-03 12:53:27 +02:00
roberto@sirius 0c465775ad force next_upstream on http_502 and http_504 on nginx 2010-06-03 08:08:28 +02:00
roberto@sirius a5417f4963 Davies Liu fix for protocol parsing 2010-06-03 08:01:34 +02:00
roberto@mrspurr b48076f6e4 support for 'grunt' processes 2010-05-31 14:06:42 +02:00
roberto@voldemort c472eae332 upstart contrib example 2010-05-22 06:54:23 +02:00
roberto@voldemort 918fc654f4 --no-orphans option (uses prctl on Linux and getppid on others) 2010-05-22 06:39:09 +02:00
roberto@voldemort 9097cbe10d 0.9.5.1 tag 2010-05-19 16:09:08 +02:00
roberto@sirius e260873338 uWSGI 0.9.5.1 2010-05-19 16:08:29 +02:00
roberto@voldemort a7822742c0 lighttpd PATH_INFO fix 2010-05-18 08:01:32 +02:00
roberto@voldemort f1316ef4bb fix env configuration 2010-05-18 07:34:36 +02:00
roberto@sirius 4106931175 fix getrlimit() 2010-05-18 07:06:07 +02:00
roberto@sirius fb5ba40f0c support for unladen swallow 2010-05-16 12:34:19 +02:00
roberto@sirius 854e51f0ad fix for eval modifier 2010-05-13 13:47:15 +02:00
roberto@sirium 676b43f17d UWSGI_MODIFIER_EVAL and nginx module update 2010-05-13 13:04:37 +02:00
roberto@sirius 48b68e6a92 updated help and version 2010-05-12 16:40:47 +02:00
roberto@sirius 61f33721e1 add --limit-post 2010-05-12 13:13:01 +02:00
roberto@sirius 5c3c46598f --post-buffering, this will help harakiri mode with big uploads 2010-05-12 12:54:49 +02:00
roberto@sirius 4358036f9e add --prio option 2010-05-12 09:10:04 +02:00
roberto@sirius 54d75d92ef fix paste support 2010-05-10 18:04:01 +02:00
roberto@sirius b1ae57c932 applied gentoo fixes 2010-05-10 10:58:52 +02:00
roberto@sirius 2636baa33f added --logto 2010-05-02 12:38:39 +02:00
roberto@sirius 926c739517 0.9.5 2010-05-01 08:24:21 +02:00
roberto@sirius 79fa25c4e0 latest (i hope) pip hack 2010-05-01 08:10:36 +02:00
roberto@sirius 02050675a8 pip hack [5] 2010-05-01 08:06:44 +02:00
roberto@sirius 0d5857a1bc pip hack [4] 2010-05-01 08:04:05 +02:00
roberto@sirius e3a51be1f9 pip hack [3] 2010-05-01 07:58:53 +02:00
roberto@sirius 57cb098a6e move to setuptools 2010-05-01 07:39:56 +02:00
roberto@sirius 5f285eef56 pip hack [2] 2010-05-01 07:29:07 +02:00
roberto@sirius 7d5cf6f318 pip hack 2010-05-01 07:14:14 +02:00
roberto@silente 99d305c7a1 snmp big endian fixes 2010-04-30 16:41:57 +02:00
roberto@sirius b9cc3b6a7d snmp fix 2010-04-30 15:51:32 +02:00
roberto@sirius e1f8c69d3d minor fixes 2010-04-30 15:16:18 +02:00
roberto@sirius 67b6fbd15b admin modifier fix 2010-04-30 14:46:27 +02:00
roberto@sirius 50f407eb9e no_server fix 2010-04-30 14:41:30 +02:00
roberto@freebsd b127699c0a FreeBSD/Dragonfly little fix 2010-04-30 14:12:51 +02:00
roberto@netbsd 4d74fa6759 small netbsd include fix 2010-04-30 16:04:02 +02:00
roberto@sirius 2b9d6cb7c2 uwsgi_log everywhere 2010-04-30 12:28:01 +02:00
roberto@solaris e0b67bba58 uwsgi_log instead of fprintf [1] 2010-04-30 12:22:07 +02:00
roberto@silente 3cdf17df75 strlcopy insted of strcpy 2010-04-30 09:54:25 +02:00
roberto@silente 43c086494b be more verbose on extreme cases 2010-04-30 09:18:53 +02:00
roberto@silente ae26e90b3a OpenBSD ha no RLIMIT_AS and swapcontext(), added an harakiri message to avoid user confusion 2010-04-30 09:01:26 +02:00
roberto@sirius d35a7d8725 updated urack.rb for unbit 2010-04-27 12:47:29 +02:00
roberto@sirius 043e7ddde4 uWSGI 0.9.5-rc2 2010-04-20 10:51:54 +02:00
310 changed files with 46227 additions and 10337 deletions
+4
View File
@@ -0,0 +1,4 @@
syntax: glob
*.o
*.pyc
+30
View File
@@ -1,3 +1,33 @@
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
+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
+485
View File
@@ -1,3 +1,488 @@
*** august 2011 ***
* 0.9.9 [20110829]
- various spooler improvements
- upload progress optimizations and fixes
- new emperor mode: Tyrant
- allows multiple --ini options
- better binary path detection
- gevent loop engine support
- resolve domain names in socket logging
- snmp fixes and reintroduction of the snmp-api
- fixed grunt mode
- you can specify build profile via env var UWSGI_PROFILE
- reintroduction of string-based multiapp
- new option --emperor-throttle
- improved queue and sharedarea subsystems
- uWSGI can now be built as a shared library
- new api attribute: uwsgi.magic_table
- improved apache2 module
- new option --pyshell
- allow threads in gateways
- fastrouter improvements
- the application list is now shared and exported to the api
- allows setting the thread stack size
- UWSGI_APPID for better multiapp hosting
- better reloading in lazy mode
- native pump support
- various rack fixes
- support for attaching binary data in the executable
- new option --set
- extreme-optimized http protocol parser
- WSGI handler optimizations
*** 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]
- fixed REMOTE_ADDR when --protocol=http
- official support for OpenIndiana
- added a welcome.py test script
- new api attribute uwsgi.version_info
- improved the admin plugin
- two new management flag for backlog queue monitoring
- fixed uwsgi_log for bigger loglines
- new option --early-emperor to allows out-of-jail emperors
- emperor can now spawn other emperors (sub-emperors)
- fixed idle mode in single-process
- fixed solaris iovec
*** may 2011 ***
* 0.9.8-rc3 [20110530]
- snapshotting support
- fixed python 3.x spooler
- improvements for grunt processes
- better abstract unix socket
- --log-socket allows logging to generic DGRAM sockets
- a bunch of solaris fixes
- new option --no-fd-passing for fastrouter
- --fastrouter-subscription-slot to set the number of slot in subscription server
- unlimited shared sockets
- fixed netlink compilation
- auto-reconnect on emperor+amqp server disconnection
- various emperor fixes
- unlimited fastrouter sockets
- better cgroup support
- --add-header option allow adding of custom HTTP response headers
- cheap and idle operational modes
* 0.9.8-rc2 [20110521]
- new option --die-on-term
- fixed touch reload
- a couple of optimizations for wsgi.input
- systemd integration
* 0.9.8-rc1 [20110514]
- massive code cleanup and refactoring
- added vassals loyalty concept
- fixed virtualhosting with dynamic virtualenv
- fixed reloading on grand-central-dispatch-enabled OSX
- improved PSGI support with uGreen and async support
- improved Rack support with complete fiber+async in ruby 1.9
- support for JSON config files
- native multi-protocol support (added fastcgi and http)
- Mongrel2 support
- support for templates in vassals
- various threading fixes
- gcc-4.6 support
- support for logging via zeromq
- support for configuration passed via pipe/stdin
- pythonpath entries are now unlimited
- socket entries are unlimited
- pythonpath can be a glob
- lazy mode added
- new language-independent profiling subsystem
- support for configuration stored in a sqlite3 db
- allow workers to survive to syslogd death (when --log-syslog is used)
- fix traceback in Python 3.x
- support for uwsgi signals in threads
- plugin autoloading
- graceful reloading for threads
- new wsgi.input object
- support for alternative allocators (tcmalloc and jemalloc)
*** april 2011 ***
* 0.9.7.2 [20110406]
- new option --touch-reload <file> to reload the stack on <file> modification
--static-map <mountpoint=documentroot> allows to serve static files
- fixed --post-limit management
- disallow empty socket names
- implemented exception_info WSGI support
- new options --reload-on-as <n> and --reload-on-rss <n> allows
to recycle workers when their memory usage is higher than <n> MB
- fixed syslog support (use --log-syslog[=facility] to enable it)
- improved plugin loading system
- added support for RabbitMQ as event dispatcher for the Emperor
- fixed FreeBSD memory report
- PSGI plugin can be compiled without ithreads
- various Emperor fixes
- fixed a regression with setgroups()
- support for shared sockets (used in jails within network namespaces)
*** march 2011 ***
* 0.9.7.1 [20110326]
- fixed python stackless support
- added persistence for queue
- forbid daemonizing in vassal mode
- modifier1 30 is available again
- allow python modules to be mapped/aliased via http
- added --pidfile2 and --logfile-chown
- added UWSGI_CACHE_GET dynamic variable
- 304/If-Modified-Since support for --check-static
- option --check-cache for integrated caching
- option --map-socket to assign specific workers to socket
- fixed unix fd passing on older OSX versions
- fixed post-buffering without pep3333-input
- fixed python threading without uwsgi cores
- support for Linux network namespace
- build with sys.abiflags if necessary
* 0.9.7 [20110317]
- fixed psgi compilation on GNU systems
- improved --pep3333-input
- better error reporting on failed open/fopen
- fixed uGreen
- added greenlet support
- various solaris fixes
- new help system
- updated async support
- fixed uwsgi.cache_get in python
* 0.9.7-rc3 [20110312]
- added support for persistent cache (--cache-store <filename>)
- less verbose file monitoring
- fixed a race condition in emperor startup
- fixed erlang empty list encoding
- improved snmp support
- fixed cache modifier 111 for 3 and 4
- preliminary cpu-affinity support (Linux only)
- fixed ldap support
- auto-configure ldap compilation
- added --allowed-modifiers (allow only a subset of modifiers)
- fixed a bug with getopt_long
* 0.9.7-rc2 [20110309]
- added cron-like interface to signal framework
- improved Linux namespaces support
- fixed multithreading + --max-requests
- added support for reference in configuration files
* 0.9.7-rc1 [20110307]
- export %v in emperor mode
- fixed signal race condition in server reload
- fixed http router post handling bug
- added uwsgi.erlang_register_process in pyerl plugin
- fixed unix socket inherit
- fixed linux namespace support in recent kernel/gcc
- ported threading to python 3.2
- add build date to uWSGI startup info
- do not allow clustering without defining a socket
- kill all the gateways/daemons on startup errors
- fixed vacuum after chdir()
- fixed gateways reload
- re-added support for OpenBSD and NetBSD
- fixed post-buffering in python
- use erlang binary for python string
- fixed memory leak in pyerl plugin
- removed broken log rotation (post-poned)
- fixed no_argument options in ini and yaml parsing
* 0.9.7-beta1 [20110301]
- fully modular re-design
- advanced build system with presets
- threading support
- emperor mode for massive auto-hosting
- caching subsystem
- message queue (even stacked) support
- improved server reloading system
- support for Linux Cgroups and Namespaces
- integrated upload progress
- Clustering infrastructure via multicast, broadcast or subscriptions
- support for attaching/monitoring external apps to the master process
- improved virtualhosting mode
- extremely improved Python support with better usage of multiple interpreters
- improved multiple apps support
- Production ready, evented HTTP router/proxy/load-balancer
- Production ready, evented uwsgi router/proxy/load-balancer
- new Erlang stack
- Internal signal subsystem
- support for RubyOnRails and Rack apps
- A huge series of fixes and optimizations
*** february 2011 ***
* 0.9.6.8 [20110207]
- fixed a bug when using --limit-as
- fixed a erlang buffer initialization
- added --ignore-sigpipe
- added --master-as-root
*** january 2011 ***
* 0.9.6.7 [20110130]
- a huge amount of async optimizations and fixes
- --logdate takes an optional strftime-like value
- follow $PATH on reloading
- uwsgi.core is exported in WSGI env
- uwsgi.log() respect for --logdate
- initial banner respect for --logdate
- fixed --post-buffering
- default listen backlog queue is now 100
- Python 3 support is no more marked as experimental
- Python 3.2 support
- new option --chroot-reload will force a reload of the uWSGI stack after a chroot
- fixed a typo in INI parsing
*** december 2010 ***
* 0.9.6.6 [20101230]
- support for YAML configuration files
- backported python module aliasing from 0.9.7-dev
- better apache2 module (support for SetEnv directive, fixed REQUEST_URI and improved connection handling)
- uwsgi.post_fork_hook implementation (to execute function after fork()) (thanks George Kollias)
- option --gid calls setgroups() after setgid() (thanks Jorge Cardona)
- fixed uGreen compilation (and uGreen is now built by default)
- fixed timeout and thundering herd problem in async modes (many thanks to Test157 for giving us a good async-test-app)
- disable TCP_INFO in older Linux kernels (thanks Bo Shi)
- enable TCP_INFO in FreeBSD (limited usage due to FreeBSD kernel support)
- fixed static virtualhosting mode using xml files (thanks Guido Notari of Link I.T. spa)
- new option --close-on-exec (thanks Jean-Baptiste Quenot)
- use HTTP_HOST var (and fallback to SERVER_NAME) in virtual hosting mode
- fixed a buffer overflow in automatic socket_name allocation (spotted by Riccardo Magliocchetti)
- Official support for Nexenta
*** september 2010 ***
* 0.9.6.5 [20100929]
- PEP 3333 support
- fix --pythonpath with --wsgi-file
- x-wsgiorg.uwsgi.version renamed to uwsgi.version
* 0.9.6.4 [20100925]
- fix a stupid bug in conditional logging backport
* 0.9.6.3 [20100925]
- fix a buffer overflow in .ini parsing (it throws a glibc error on malloc)
- backport of conditional logging from 0.9.7-dev
- backport of backlog queue monitor from 0.9.7-dev (only Linux)
* 0.9.6.2 [20100915]
- fix a regression in virtual hosting mode
- fix pythonpath usage in --ini and --ini-paste
- new uwsgi packet var: UWSGI_CHDIR
* 0.9.6.1 [20100912]
- print the request uri during SIGPIPE or HARAKIRI
- added SIGUSR2 support (it will print the current running request, if available)
- protocol parsing optimization
- fixed --logto support
- new --eval option allows inline definition of WSGI script
- support for defining WSGI script in xml using CDATA
- allow --pp as --pythonpath shortcut
- various spooler optimizations and fixes
- added -O2 optimization by default
- added uwsgi.is_a_reload commodity function
- .ini file support fix
- SNMP agent fix
- support for subprocesses generated by master
- fix a regression in SCRIPT_NAME handling
- Haiku official support
- gcc 2.95 support
- dynamic app management optimizations
- export x-wsgiorg.uwsgi.version in WSGI env
*** august 2010 ***
* 0.9.6 [20100829]
- better handling of SCRIPT_NAME
- vacuum option for deleting unix sockets and pidfiles after usage
- advanced XML configuration
- new configuration systems: INI files and LDAP
- embedded HTTP server for development/testing
- better signal handling
- PSGI plugin improved
- usability fixes and new commodities options for root startup
- grunt processes (detached workers)
- preliminary integrated virtualhosting mode
- new option catch-exceptions can redirect python exceptions to your browser
- logging improvements (--logto and --logdate options)
- Full PEP 333 compliant usage of wsgi.file_wrapper
- re-initialize random seed after every fork() [security fix]
- fix Spooler's usage of stdin
- export WSGI environment in uwsgi.env (for doing evil things)
- logsize tracking (uwsgi.logsize) for future embedded log rotation
*** july 2010 ***
* 0.9.5.4 [20100706]
*** june 2010 ***
* 0.9.5.3 [20100628]
- fixed linux x86_64 compilation (sorry)
* 0.9.5.2 [20100626] *
- fixed a request parsing bug
- applied debian fixes
- fixed multiple interpreter sys.argv
- improved --chmod-socket
- fixed uid 0 SIGHUP
- updated nginx and apache modules
- updated PSGI, lua and example plugin
- fixed --pyargv with python 3.x
- improved plugin build system
*** may 2010 ***
* 0.9.5.1 [20100519] *
- fixed paste support
- added a new modifier (22)
- full support for configuration via environment variables
- nginx_string option in nginx module
- fix for harakiri without master
- backported unladen swallow support for 0.9.6-dev
- fixed address space limit detection via getrlimit()
- http body buffering implementation
- added --prio option (to set priority)
- added --post-limit to limit the size of uploads
- added --logto option to allow udp logging without daemonizing
- applied Gentoo's packagers fixes for build system
* 0.9.5 [20100501] *
- hook based request/modifier management
- plugin support via dlopen
- on-the-fly management flag
- integrated proxy
- logging via udp
- improved spooler for cron-like apps
- async support
- green thread platform (uGreen) on top of the async mode
- transparent Erlang integration
- embedded snmp agent
- nagios mode
- improved python 3.x support
- improved xml configuration
- new build system
- address space usage limiting
- lot of portability fixes
- lot of optimizations and code refactoring
*** april 2010 ***
* Fourth Maintenance release [20100427] *
- backported non-yielding app optimization from 0.9.5
- backported udp logging from 0.9.5
- backported uwsgi_error() from 0.9.5 (no more dumb perror())
- fix a rare (but possible) segmentation fault
- added --version
- updated apache2 module
*** march 2010 ***
* Third Maintenance release [20100310] *
+3
View File
@@ -1,2 +1,5 @@
all:
python uwsgiconfig.py --build
clean:
python uwsgiconfig.py --clean
+2
View File
@@ -0,0 +1,2 @@
all:
python2.7 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python3.2 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python uwsgiconfig.py --build pylua
+923
View File
@@ -0,0 +1,923 @@
/*
*** uWSGI/mod_Ruwsgi ***
Copyright 2009-2010 Roger Florkowski <rflorkowski@mypublisher.com>
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define MOD_UWSGI_VERSION "1.0"
#include "ap_config.h"
#include "apr_version.h"
#include "apr_lib.h"
#include "apr_strings.h"
#include "httpd.h"
#include "http_core.h"
#include "http_request.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "util_script.h"
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <time.h>
#include <poll.h>
#define DEFAULT_TIMEOUT 60 /* default socket timeout */
#define DEFAULT_CGIMODE 0 /* not enabled */
#define UNSET 0
#define ENABLED 1
#define DISABLED 2
#if APR_MAJOR_VERSION == 0
#define apr_socket_send apr_send
#define GET_PORT(port, addr) apr_sockaddr_port_get(&(port), addr)
#define CREATE_SOCKET(sock, family, pool) \
apr_socket_create(sock, family, SOCK_STREAM, pool)
#else
#define GET_PORT(port, addr) ((port) = (addr)->port)
#define CREATE_SOCKET(sock, family, pool) \
apr_socket_create(sock, family, SOCK_STREAM, APR_PROTO_TCP, pool)
#endif
typedef struct {
char *path;
char *addr;
apr_port_t port;
} mount_entry;
/*
* Configuration record. Used per-directory configuration data.
*/
typedef struct {
mount_entry mount;
int enabled; /* mod_uwsgi is enabled from this directory */
int timeout;
int cgi_mode;
uint8_t modifier1;
uint8_t modifier2;
} uwsgi_cfg;
/* Server level configuration */
typedef struct {
apr_array_header_t *mounts;
int timeout;
int cgi_mode;
} uwsgi_server_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
/*
* Locate our directory configuration record for the current request.
*/
static uwsgi_cfg *
our_dconfig(request_rec *r)
{
return (uwsgi_cfg *) ap_get_module_config(r->per_dir_config, &uwsgi_module);
}
static uwsgi_server_cfg *our_sconfig(server_rec *s)
{
return (uwsgi_server_cfg *) ap_get_module_config(s->module_config,
&uwsgi_module);
}
static int
mount_entry_matches(const char *url, const char *prefix,
const char **path_info)
{
int i;
for (i=0; prefix[i] != '\0'; i++) {
if (url[i] == '\0' || url[i] != prefix[i])
return 0;
}
if (url[i] == '\0' || url[i] == '/') {
*path_info = url + i;
return 1;
}
return 0;
}
static int uwsgi_translate(request_rec *r)
{
uwsgi_cfg *cfg = our_dconfig(r);
if (cfg->enabled == DISABLED) {
return DECLINED;
}
if (cfg->mount.addr != UNSET) {
ap_assert(cfg->mount.port != UNSET);
r->handler = "uwsgi-handler";
r->filename = r->uri;
return OK;
}
else {
int i;
uwsgi_server_cfg *scfg = our_sconfig(r->server);
mount_entry *entries = (mount_entry *) scfg->mounts->elts;
for (i = 0; i < scfg->mounts->nelts; ++i) {
const char *path_info;
mount_entry *mount = &entries[i];
if (mount_entry_matches(r->uri, mount->path, &path_info)) {
r->handler = "uwsgi-handler";
r->path_info = apr_pstrdup(r->pool, path_info);
r->filename = r->uri;
ap_set_module_config(r->request_config, &uwsgi_module, mount);
return OK;
}
}
}
return DECLINED;
}
static int uwsgi_map_location(request_rec *r)
{
if (r->handler && strcmp(r->handler, "uwsgi-handler") == 0) {
return OK; /* We don't want directory walk. */
}
return DECLINED;
}
static void log_err(const char *file, int line, request_rec *r,
apr_status_t status, const char *msg)
{
ap_log_rerror(file, line, APLOG_ERR, status, r, "uwsgi: %s", msg);
}
static void log_debug(const char *file, int line, request_rec *r, const
char *msg)
{
/*
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, msg);
ap_log_rerror(file, line, APLOG_WARNING, APR_SUCCESS, r, "uwsgi: %s", msg);
*/
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
}
/* buffered socket implementation (buckets are overkill) */
#define BUFFER_SIZE 8000
struct sockbuff {
apr_socket_t *sock;
char buf[BUFFER_SIZE];
int used;
};
static void binit(struct sockbuff *s, apr_socket_t *sock)
{
s->sock = sock;
s->used = 0;
}
static apr_status_t sendall(apr_socket_t *sock, char *buf, apr_size_t len)
{
apr_status_t rv;
apr_size_t n;
while (len > 0) {
n = len;
if ((rv = apr_socket_send(sock, buf, &n))) return rv;
buf += n;
len -= n;
}
return APR_SUCCESS;
}
static apr_status_t bflush(struct sockbuff *s)
{
apr_status_t rv;
ap_assert(s->used >= 0 && s->used <= BUFFER_SIZE);
if (s->used) {
if ((rv = sendall(s->sock, s->buf, s->used))) return rv;
s->used = 0;
}
return APR_SUCCESS;
}
static apr_status_t bwrite(struct sockbuff *s, char *buf, apr_size_t len)
{
apr_status_t rv;
if (len >= BUFFER_SIZE - s->used) {
if ((rv = bflush(s))) return rv;
while (len >= BUFFER_SIZE) {
if ((rv = sendall(s->sock, buf, BUFFER_SIZE))) return rv;
buf += BUFFER_SIZE;
len -= BUFFER_SIZE;
}
}
if (len > 0) {
ap_assert(len < BUFFER_SIZE - s->used);
memcpy(s->buf + s->used, buf, len);
s->used += len;
}
return APR_SUCCESS;
}
static apr_status_t bputs(struct sockbuff *s, char *buf)
{
return bwrite(s, buf, strlen(buf));
}
static apr_status_t bputc(struct sockbuff *s, char c)
{
char buf[1];
buf[0] = c;
return bwrite(s, buf, 1);
}
static apr_status_t bputh(struct sockbuff *s, unsigned short h)
{
return bwrite(s, (char *)&h, 2);
}
#define CONFIG_VALUE(value, fallback) ((value) != UNSET ? (value) : (fallback))
static apr_status_t
open_socket(apr_socket_t **sock, request_rec *r)
{
int timeout;
int retries = 4;
int sleeptime = 1;
apr_status_t rv;
apr_sockaddr_t *sockaddr;
uwsgi_server_cfg *scfg = our_sconfig(r->server);
uwsgi_cfg *cfg = our_dconfig(r);
mount_entry *m = (mount_entry *) ap_get_module_config(r->request_config,
&uwsgi_module);
if (!m) {
m = &cfg->mount;
}
timeout = CONFIG_VALUE(cfg->timeout, CONFIG_VALUE(scfg->timeout,
DEFAULT_TIMEOUT));
rv = apr_sockaddr_info_get(&sockaddr,
CONFIG_VALUE(m->addr, "localhost"),
APR_UNSPEC,
CONFIG_VALUE(m->port, 5000),
0,
r->pool);
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_sockaddr_info_get() error");
return rv;
}
restart:
*sock = NULL;
rv = CREATE_SOCKET(sock, sockaddr->family, r->pool);
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_socket_create() error");
return rv;
}
rv = apr_socket_timeout_set(*sock, apr_time_from_sec(timeout));
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_socket_timeout_set() error");
return rv;
}
rv = apr_socket_connect(*sock, sockaddr);
if (rv) {
apr_socket_close(*sock);
if ((APR_STATUS_IS_ECONNREFUSED(rv) |
APR_STATUS_IS_EINPROGRESS(rv)) && retries > 0) {
/* server may be temporarily down, retry */
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, rv, r,
"uwsgi: connection failed, retrying");
apr_sleep(apr_time_from_sec(sleeptime));
--retries;
sleeptime *= 2;
goto restart;
}
log_err(APLOG_MARK, r, rv, "uwsgi: can't connect to server");
return rv;
}
#ifdef APR_TCP_NODELAY
/* disable Nagle, we don't send small packets */
apr_socket_opt_set(*sock, APR_TCP_NODELAY, 1);
#endif
return APR_SUCCESS;
}
/* This code is a duplicate of what's in util_script.c. We can't use
* r->unparsed_uri because it gets changed if there was a redirect. */
static char *original_uri(request_rec *r)
{
char *first, *last;
if (r->the_request == NULL) {
return (char *) apr_pcalloc(r->pool, 1);
}
first = r->the_request; /* use the request-line */
while (*first && !apr_isspace(*first)) {
++first; /* skip over the method */
}
while (apr_isspace(*first)) {
++first; /* and the space(s) */
}
last = first;
while (*last && !apr_isspace(*last)) {
++last; /* end at next whitespace */
}
return apr_pstrmemdup(r->pool, first, last - first);
}
static char *lookup_name(apr_table_t *t, const char *name)
{
const apr_array_header_t *hdrs_arr = apr_table_elts(t);
apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
int i;
for (i = 0; i < hdrs_arr->nelts; ++i) {
if (hdrs[i].key == NULL)
continue;
if (strcasecmp(hdrs[i].key, name) == 0)
return hdrs[i].val;
}
return NULL;
}
static char *lookup_header(request_rec *r, const char *name)
{
return lookup_name(r->headers_in, name);
}
static void add_header(apr_table_t *t, const char *name, const char *value)
{
if (name != NULL && value != NULL)
apr_table_addn(t, name, value);
}
static int find_path_info(const char *uri, const char *path_info)
{
int n;
n = strlen(uri) - strlen(path_info);
ap_assert(n >= 0);
return n;
}
static char *http2env(apr_pool_t *p, const char *name)
{
char *env_name = apr_pstrcat(p, "HTTP_", name, NULL);
char *cp;
for (cp = env_name + 5; *cp != 0; cp++) {
if (*cp == '-') {
*cp = '_';
}
else {
*cp = apr_toupper(*cp);
}
}
return env_name;
}
static apr_status_t
send_headers(request_rec *r, struct sockbuff *s)
{
int i;
const apr_array_header_t *hdrs_arr, *env_arr;
apr_table_entry_t *hdrs, *env;
char *buf;
unsigned short int n = 0;
apr_table_t *t;
apr_status_t rv = 0;
apr_port_t port = 0;
GET_PORT(port, r->connection->remote_addr);
uwsgi_cfg *cfg = our_dconfig(r);
log_debug(APLOG_MARK,r, "sending headers");
t = apr_table_make(r->pool, 40);
if (!t)
return APR_ENOMEM;
/* headers to send */
/* CONTENT_LENGTH must come first and always be present */
buf = lookup_header(r, "Content-Length");
if (buf == NULL)
buf = "0";
add_header(t, "CONTENT_LENGTH", buf);
add_header(t, "REQUEST_METHOD", (char *) r->method);
add_header(t, "QUERY_STRING", r->args ? r->args : "");
add_header(t, "SERVER_SOFTWARE", ap_get_server_version());
add_header(t, "SERVER_ADMIN", r->server->server_admin);
add_header(t, "SERVER_NAME", (char *) ap_get_server_name(r));
add_header(t, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)));
add_header(t, "SERVER_ADDR", r->connection->local_ip);
add_header(t, "SERVER_PROTOCOL", r->protocol);
add_header(t, "REQUEST_URI", original_uri(r));
add_header(t, "REMOTE_ADDR", r->connection->remote_ip);
add_header(t, "REMOTE_PORT", apr_psprintf(r->pool, "%d", port));
add_header(t, "REMOTE_USER", r->user);
add_header(t, "DOCUMENT_ROOT", (char *) ap_document_root(r));
if (r->path_info) {
int path_info_start = find_path_info(r->uri, r->path_info);
add_header(t, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri,
path_info_start));
add_header(t, "PATH_INFO", r->path_info);
}
else {
/* skip PATH_INFO, don't know it */
add_header(t, "SCRIPT_NAME", r->uri);
}
add_header(t, "CONTENT_TYPE", lookup_header(r, "Content-type"));
/* HTTP headers */
hdrs_arr = apr_table_elts(r->headers_in);
hdrs = (apr_table_entry_t *) hdrs_arr->elts;
for (i = 0; i < hdrs_arr->nelts; ++i) {
if (hdrs[i].key) {
add_header(t, http2env(r->pool, hdrs[i].key), hdrs[i].val);
}
}
/* environment variables */
env_arr = apr_table_elts(r->subprocess_env);
env = (apr_table_entry_t*) env_arr->elts;
for (i = 0; i < env_arr->nelts; ++i) {
add_header(t, env[i].key, env[i].val);
}
hdrs_arr = apr_table_elts(t);
hdrs = (apr_table_entry_t*) hdrs_arr->elts;
/* calculate length of header data */
for (i = 0; i < hdrs_arr->nelts; ++i) {
n += strlen(hdrs[i].key);
n += strlen(hdrs[i].val);
n += 4; /* XXX */
}
log_debug(APLOG_MARK,r, apr_psprintf(r->pool, "pktheader size is %u", n));
log_debug(APLOG_MARK,r, apr_psprintf(r->pool, "num headers %u", hdrs_arr->nelts));
/* write pkt header */
rv = bputc(s, cfg->modifier1); /* marker */
if (rv) return rv;
rv = bputh(s, n); /* length of header data */
if (rv) return rv;
rv = bputc(s, cfg->modifier2); /* marker */
if (rv) return rv;
/* write out headers */
for (i = 0; i < hdrs_arr->nelts; ++i) {
rv = bputh(s, strlen(hdrs[i].key)); /* length */
if (rv) return rv;
rv = bputs(s, hdrs[i].key); /* key */
if (rv) return rv;
rv = bputh(s, strlen(hdrs[i].val)); /* length */
if (rv) return rv;
rv = bputs(s, hdrs[i].val); /* data */
if (rv) return rv;
}
return APR_SUCCESS;
}
static apr_status_t send_request_body(request_rec *r, struct sockbuff *s)
{
if (ap_should_client_block(r)) {
char buf[BUFFER_SIZE];
apr_status_t rv;
apr_off_t len;
while ((len = ap_get_client_block(r, buf, sizeof buf)) > 0) {
if ((rv = bwrite(s, buf, len))) return rv;
}
if (len == -1)
return HTTP_INTERNAL_SERVER_ERROR; /* what to return? */
}
return APR_SUCCESS;
}
static int uwsgi_handler(request_rec *r)
{
apr_status_t rv = 0;
int cgi_mode, http_status = 0;
struct sockbuff s;
apr_socket_t *sock;
apr_bucket_brigade *bb = NULL;
apr_bucket *b = NULL;
const char *location;
uwsgi_cfg *cfg = our_dconfig(r);
uwsgi_server_cfg *scfg = our_sconfig(r->server);
if (strcmp(r->handler, "uwsgi-handler"))
return DECLINED;
http_status = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
if (http_status != OK)
return http_status;
log_debug(APLOG_MARK, r, "connecting to server");
rv = open_socket(&sock, r);
if (rv) {
return HTTP_INTERNAL_SERVER_ERROR;
}
binit(&s, sock);
rv = send_headers(r, &s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request headers");
return HTTP_INTERNAL_SERVER_ERROR;
}
rv = send_request_body(r, &s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request body");
return HTTP_INTERNAL_SERVER_ERROR;
}
rv = bflush(&s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request");
return HTTP_INTERNAL_SERVER_ERROR;
}
log_debug(APLOG_MARK, r, "reading response headers");
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
cgi_mode = CONFIG_VALUE(cfg->cgi_mode, CONFIG_VALUE(scfg->cgi_mode, DEFAULT_CGIMODE));
if (!cgi_mode) {
/* receive implemented with http-0.9 based protocol */
apr_interval_time_t timeout;
char buf[4096];
apr_pollfd_t pollfd = {r->pool, APR_POLL_SOCKET, APR_POLLIN, 0, { NULL }, NULL };
pollfd.desc.s = sock;
timeout = CONFIG_VALUE(cfg->timeout, CONFIG_VALUE(scfg->timeout,
DEFAULT_TIMEOUT)) * 1000 * 1000;
r->assbackwards = 1; /* XXX */
for(;;) {
apr_int32_t nsds;
apr_size_t len;
if ((rv = apr_poll(&pollfd, 1, &nsds, timeout)) == APR_TIMEUP) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
break;
}
if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
break;
}
len = 4096;
rv = apr_socket_recv(sock, buf, &len);
if (rv == APR_SUCCESS) {
apr_brigade_write(bb, NULL, NULL, buf, len);
}
else if (rv == APR_EOF) {
break;
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
}
}
log_debug(APLOG_MARK,r, "recv finished");
b = apr_bucket_flush_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
} else {
/* receive implemented with http-1.x based protocol */
b = apr_bucket_socket_create(sock, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
rv = ap_scan_script_header_err_brigade(r, bb, NULL);
if (rv) {
if (rv == HTTP_INTERNAL_SERVER_ERROR) {
log_err(APLOG_MARK, r, rv, "error reading response headers");
}
else {
/* Work around an Apache bug whereby the returned status is
* ignored and status_line is used instead. This bug is
* present at least in 2.0.54.
*/
r->status_line = NULL;
}
apr_brigade_destroy(bb);
return rv;
}
location = apr_table_get(r->headers_out, "Location");
if (location && location[0] == '/' &&
((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) {
apr_brigade_destroy(bb);
/* Internal redirect -- fake-up a pseudo-request */
r->status = HTTP_OK;
/* This redirect needs to be a GET no matter what the original
* method was.
*/
r->method = apr_pstrdup(r->pool, "GET");
r->method_number = M_GET;
ap_internal_redirect_handler(location, r);
return OK;
}
}
rv = ap_pass_brigade(r->output_filters, bb);
if (rv) {
log_err(APLOG_MARK, r, rv, "ap_pass_brigade()");
return HTTP_INTERNAL_SERVER_ERROR;
}
return OK;
}
static int uwsgi_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
server_rec *base_server)
{
ap_add_version_component(p, "mod_uwsgi/" MOD_UWSGI_VERSION);
return OK;
}
static void *
uwsgi_create_dir_config(apr_pool_t *p, char *dirspec)
{
uwsgi_cfg *cfg = apr_pcalloc(p, sizeof(uwsgi_cfg));
cfg->enabled = UNSET;
cfg->mount.addr = UNSET;
cfg->mount.port = UNSET;
cfg->timeout = UNSET;
cfg->cgi_mode = UNSET;
cfg->modifier1 = UNSET;
cfg->modifier2 = UNSET;
return cfg;
}
#define MERGE(b, n, a) (n->a == UNSET ? b->a : n->a)
static void *
uwsgi_merge_dir_config(apr_pool_t *p, void *basev, void *newv)
{
uwsgi_cfg* cfg = apr_pcalloc(p, sizeof(uwsgi_cfg));
uwsgi_cfg* base = basev;
uwsgi_cfg* new = newv;
cfg->enabled = MERGE(base, new, enabled);
cfg->mount.addr = MERGE(base, new, mount.addr);
cfg->mount.port = MERGE(base, new, mount.port);
cfg->timeout = MERGE(base, new, timeout);
cfg->cgi_mode = MERGE(base, new, cgi_mode);
cfg->modifier1 = MERGE(base, new, modifier1);
cfg->modifier2 = MERGE(base, new, modifier2);
return cfg;
}
static void *
uwsgi_create_server_config(apr_pool_t *p, server_rec *s)
{
uwsgi_server_cfg *c =
(uwsgi_server_cfg *) apr_pcalloc(p, sizeof(uwsgi_server_cfg));
c->mounts = apr_array_make(p, 20, sizeof(mount_entry));
c->timeout = UNSET;
c->cgi_mode = UNSET;
return c;
}
static void *
uwsgi_merge_server_config(apr_pool_t *p, void *basev, void *overridesv)
{
uwsgi_server_cfg *c = (uwsgi_server_cfg *)
apr_pcalloc(p, sizeof(uwsgi_server_cfg));
uwsgi_server_cfg *base = (uwsgi_server_cfg *) basev;
uwsgi_server_cfg *overrides = (uwsgi_server_cfg *) overridesv;
c->mounts = apr_array_append(p, overrides->mounts, base->mounts);
c->timeout = MERGE(base, overrides, timeout);
c->cgi_mode = MERGE(base, overrides, cgi_mode);
return c;
}
static const char *
cmd_uwsgi_mount(cmd_parms *cmd, void *dummy, const char *path, const char *addr)
{
int n;
apr_status_t rv;
char *scope_id = NULL; /* A ip6 parameter - not used here. */
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
mount_entry *new = apr_array_push(scfg->mounts);
n = strlen(path);
while (n > 0 && path[n-1] == '/') {
n--; /* strip trailing slashes */
}
new->path = apr_pstrndup(cmd->pool, path, n);
rv = apr_parse_addr_port(&new->addr, &scope_id, &new->port, addr,
cmd->pool);
if (rv)
return "error parsing address:port string";
return NULL;
}
static const char *
cmd_uwsgi_server(cmd_parms *cmd, void *pcfg, const char *addr_and_port)
{
apr_status_t rv;
uwsgi_cfg *cfg = pcfg;
char *scope_id = NULL; /* A ip6 parameter - not used here. */
if (cmd->path == NULL)
return "not a server command";
rv = apr_parse_addr_port(&cfg->mount.addr, &scope_id, &cfg->mount.port,
addr_and_port, cmd->pool);
if (rv)
return "error parsing address:port string";
return NULL;
}
static const char *
cmd_uwsgi_handler(cmd_parms* cmd, void* pcfg, int flag)
{
uwsgi_cfg *cfg = pcfg;
if (cmd->path == NULL) /* server command */
return "not a server command";
if (flag)
cfg->enabled = ENABLED;
else
cfg->enabled = DISABLED;
return NULL;
}
static const char *
cmd_uwsgi_timeout(cmd_parms *cmd, void* pcfg, const char *strtimeout)
{
uwsgi_cfg *dcfg = pcfg;
int timeout = atoi(strtimeout);
if (cmd->path == NULL) {
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
scfg->timeout = timeout;
}
else {
dcfg->timeout = timeout;
}
return NULL;
}
static const char *
cmd_uwsgi_force_cgi_mode(cmd_parms *cmd, void *pcfg, const char *value)
{
int cgi_mode;
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value)) {
cgi_mode = 1;
}
else {
cgi_mode = 0;
}
if (cmd->path == NULL) {
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
scfg->cgi_mode = cgi_mode;
}
else {
uwsgi_cfg *dcfg = pcfg;
dcfg->cgi_mode = cgi_mode;
}
return NULL;
}
static const char *
cmd_uwsgi_modifier1(cmd_parms *cmd, void *pcfg, const char *value)
{
uwsgi_cfg *cfg = pcfg;
int val;
if (cmd->path == NULL) /* server command */
return "not a server command";
val = atoi(value);
if (val < 0 || val > 255) {
return "ignored uWSGImodifier1. Value must be between 0 and 255";
}
else {
cfg->modifier1 = (uint8_t) val;
}
return NULL;
}
static const char *
cmd_uwsgi_modifier2(cmd_parms *cmd, void *pcfg, const char *value)
{
uwsgi_cfg *cfg = pcfg;
int val;
if (cmd->path == NULL) /* server command */
return "not a server command";
val = atoi(value);
if (val < 0 || val > 255) {
return "ignored uWSGImodifier2. Value must be between 0 and 255";
}
else {
cfg->modifier2 = (uint8_t) val;
}
return NULL;
}
static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE2("uWSGImount", cmd_uwsgi_mount, NULL, RSRC_CONF,
"path prefix and address of UWSGI server"),
AP_INIT_TAKE1("uWSGIserver", cmd_uwsgi_server, NULL, ACCESS_CONF,
"Address and port of an UWSGI server (e.g. localhost:4000)"),
AP_INIT_FLAG( "uWSGIhandler", cmd_uwsgi_handler, NULL, ACCESS_CONF,
"On or Off to enable or disable the UWSGI handler"),
AP_INIT_TAKE1("uWSGIserverTimeout", cmd_uwsgi_timeout, NULL, ACCESS_CONF|RSRC_CONF,
"Timeout (in seconds) for communication with the UWSGI server."),
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF|RSRC_CONF,
"Force uWSGI CGI mode for perfect integration with apache filter"),
AP_INIT_TAKE1("uWSGImodifier1", cmd_uwsgi_modifier1, NULL, ACCESS_CONF,
"Set uWSGI modifier1"),
AP_INIT_TAKE1("uWSGImodifier2", cmd_uwsgi_modifier2, NULL, ACCESS_CONF,
"Set uWSGI modifier2"),
/*
AP_INIT_TAKE12("uWSGIsocket", cmd_uwsgi_socket, NULL, RSRC_CONF|ACCESS_CONF,
"Absolute path and optional timeout in seconds of uwsgi server socket"),
AP_INIT_TAKE1("uWSGIsocket2", cmd_uwsgi_socket2, NULL, RSRC_CONF|ACCESS_CONF,
"Absolute path of failover uwsgi server socket"),
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF,
"Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
*/
{NULL}
};
static void uwsgi_register_hooks(apr_pool_t *p)
{
ap_hook_post_config(uwsgi_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(uwsgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_translate_name(uwsgi_translate, NULL, NULL, APR_HOOK_LAST);
ap_hook_map_to_storage(uwsgi_map_location, NULL, NULL, APR_HOOK_FIRST);
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA uwsgi_module = {
STANDARD20_MODULE_STUFF,
uwsgi_create_dir_config, /* create per-dir config structs */
uwsgi_merge_dir_config, /* merge per-dir config structs */
uwsgi_create_server_config, /* create per-server config structs */
uwsgi_merge_server_config, /* merge per-server config structs */
uwsgi_cmds, /* table of config file commands */
uwsgi_register_hooks, /* register hooks */
};
+135 -87
View File
@@ -1,18 +1,18 @@
/*
*** uWSGI/mod_uwsgi ***
*** uWSGI/mod_uwsgi ***
Copyright 2009 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
@@ -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,8 @@ 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;
c->script_name[0] = 0;
return c;
}
@@ -164,6 +176,13 @@ 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;
c->script_name[0] = 0;
if (dir) {
if (strcmp(dir, "/")) {
strncpy(c->script_name, dir, 255);
}
}
return c;
}
@@ -243,11 +262,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;
@@ -264,7 +280,6 @@ static int uwsgi_handler(request_rec *r) {
char uwsgi_http_status[13] ;
int uwsgi_http_status_read = 0;
apr_bucket_brigade *bb;
if (strcmp(r->handler, "uwsgi-handler"))
@@ -287,7 +302,6 @@ static int uwsgi_handler(request_rec *r) {
return HTTP_INTERNAL_SERVER_ERROR;
}
if ( (ret = timed_connect(&uwsgi_poll, (struct sockaddr *) &c->s_addr, c->addr_size, c->socket_timeout, r) ) != 0) {
close(uwsgi_poll.fd);
@@ -317,68 +331,49 @@ 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->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) ;
}
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) ;
}
if (c->script_name[0] != 0) {
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) ;
}
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) ;
}
}
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) ;
}
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);
@@ -390,10 +385,17 @@ 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) ;
}
}
}
/* environment variables */
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, r, h[i].key, h[i].val, &pkt_size) ;
}
uwsgi_vars[0].iov_base = pkt_header;
@@ -413,11 +415,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;
}
@@ -429,6 +433,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;
}
}
@@ -453,37 +458,60 @@ 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) {
cnt = recv(uwsgi_poll.fd, buf, 4096, 0) ;
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
if (!c->cgi_mode && uwsgi_http_status_read < 12) {
if (uwsgi_http_status_read + cnt >= 12) {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, 12-uwsgi_http_status_read);
r->status = atoi(uwsgi_http_status+8);
uwsgi_http_status_read+=cnt;
}
else {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, cnt);
uwsgi_http_status_read+=cnt;
}
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
}
else {
break;
if (uwsgi_poll.revents & POLLIN || uwsgi_poll.revents & POLLHUP) {
cnt = recv(uwsgi_poll.fd, buf, 4096, 0) ;
if (cnt < 0) {
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 {
break;
}
}
else if (cnt > 0) {
if (!c->cgi_mode && uwsgi_http_status_read < 12) {
if (uwsgi_http_status_read + cnt >= 12) {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, 12-uwsgi_http_status_read);
r->status = atoi(uwsgi_http_status+8);
uwsgi_http_status_read+=cnt;
}
else {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, cnt);
uwsgi_http_status_read+=cnt;
}
}
// check for client disconnect
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);
}
else {
// EOF
break;
}
}
// error
if (uwsgi_poll.revents & POLLERR || uwsgi_poll.revents & POLLNVAL) {
break;
}
}
else {
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;
}
}
@@ -497,6 +525,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;
}
}
@@ -504,11 +533,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) ;
}
@@ -540,6 +571,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 ;
@@ -683,6 +730,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}
};
+377 -398
View File
@@ -1,459 +1,438 @@
#ifdef UWSGI_ASYNC
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef __linux__
#include <sys/epoll.h>
int async_queue_init(int serverfd) {
int epfd ;
struct epoll_event ee;
epfd = epoll_create(256);
if (epfd < 0) {
uwsgi_error("epoll_create()");
return -1 ;
}
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = serverfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, serverfd, &ee)) {
uwsgi_error("epoll_ctl()");
close(epfd);
return -1;
}
return epfd;
struct wsgi_request *find_wsgi_req_proto_by_fd(int fd) {
return uwsgi.async_proto_fd_table[fd];
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
return uwsgi.async_waiting_fd_table[fd];
}
int ret ;
void runqueue_remove(struct uwsgi_async_request *u_request) {
if (timeout <= 0) {
timeout = block;
struct uwsgi_async_request *parent = u_request->prev;
struct uwsgi_async_request *child = u_request->next;
if (parent) {
parent->next = child;
}
if (child) {
child->prev = parent;
}
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
if (u_request == uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last = parent;
}
free(u_request);
uwsgi.async_runqueue_cnt--;
}
void runqueue_push(struct wsgi_request *wsgi_req) {
struct uwsgi_async_request *uar;
if (uwsgi.async_runqueue == NULL) {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
uwsgi.async_runqueue_cnt++;
}
struct wsgi_request *find_first_available_wsgi_req() {
struct wsgi_request *wsgi_req;
if (uwsgi.async_queue_unused_ptr < 0) {
return NULL;
}
wsgi_req = uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr];
uwsgi.async_queue_unused_ptr--;
return wsgi_req;
}
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
time_t current_time = time(NULL);
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for(;;) {
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (urbt == NULL) return;
if (urbt->key <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
uaf = wsgi_req->waiting_fds;
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
while(uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
current_uaf = uaf;
uaf = current_uaf->next;
free(current_uaf);
}
wsgi_req->waiting_fds = NULL;
// put th request in the runqueue
runqueue_push(wsgi_req);
continue;
}
break;
}
}
void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0) return ;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_read();
uad->prev = last_uad;
uad->next = NULL;
if (last_uad) {
last_uad->next = uad;
}
else {
timeout = timeout*1000;
wsgi_req->waiting_fds = uad;
}
//fprintf(stderr,"waiting with timeout %d nevents %d\n", timeout, nevents);
ret = epoll_wait(queuefd, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
uwsgi_error("epoll_wait()");
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
return ret ;
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_read(uwsgi.async_queue, fd);
}
int async_add(int queuefd, int fd, int etype) {
struct epoll_event ee;
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, time(NULL)+timeout, wsgi_req);
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
struct epoll_event ee;
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (epoll_ctl(queuefd, EPOLL_CTL_MOD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
if (fd < 0) return ;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
return 0;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_write();
uad->prev = last_uad;
uad->next = NULL;
int async_del(int queuefd, int fd, int etype) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
return 0;
}
#elif defined(__sun__)
int async_queue_init(int serverfd) {
int dpfd ;
struct pollfd dpev;
dpfd = open("/dev/poll", O_RDWR);
if (dpfd < 0) {
uwsgi_error("open()");
return -1 ;
}
dpev.fd = serverfd;
dpev.events = POLLIN ;
dpev.revents = 0;
if (write(dpfd, &dpev, sizeof(struct pollfd)) < 0) {
uwsgi_error("write()");
return -1;
}
return dpfd;
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret ;
struct dvpoll dv ;
if (timeout <= 0) {
timeout = block;
}
else {
timeout = timeout*1000;
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
dv.dp_fds = (struct pollfd *) events;
dv.dp_nfds = nevents;
dv.dp_timeout = timeout;
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_write(uwsgi.async_queue, fd);
//fprintf(stderr,"waiting with timeout %d nevents %d\n", timeout, nevents);
ret = ioctl(queuefd, DP_POLL, &dv);
if (ret < 0) {
uwsgi_error("ioctl()");
}
return ret ;
}
int async_add(int queuefd, int fd, int etype) {
struct pollfd pl;
pl.fd = fd ;
pl.events = etype ;
pl.revents = 0 ;
if (write(queuefd, &pl, sizeof(struct pollfd)) < 0) {
uwsgi_error("write()");
return -1;
}
return 0;
void async_schedule_to_req(void) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
}
int async_mod(int queuefd, int fd, int etype) {
// using the same fd will overwrite existing rule
return async_add(queuefd, fd, etype);
}
void *async_loop(void *arg1) {
int async_del(int queuefd, int fd, int etype) {
// use POLLREMOVE to remove an fd
return async_add(queuefd, fd, POLLREMOVE);
}
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
struct uwsgi_rb_timer *min_timeout;
int timeout;
int is_a_new_connection;
int proto_parser_status;
#else
int async_queue_init(int serverfd) {
int kfd ;
struct kevent kev;
time_t now, last_now = 0;
kfd = kqueue();
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
if (kfd < 0) {
uwsgi_error("kqueue()");
return -1 ;
void *events = event_queue_alloc(64);
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);
}
EV_SET(&kev, serverfd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(kfd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
return kfd;
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret;
struct timespec ts ;
if (timeout <= 0) {
if (!block) {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout ;
ret = kevent(queuefd, NULL, 0, events, nevents, &ts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
else {
ret = kevent(queuefd, NULL, 0, events, nevents, NULL);
}
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout ;
ret = kevent(queuefd, NULL, 0, events, nevents, &ts);
}
if (ret < 0) {
uwsgi_error("kevent()");
}
return ret;
}
int async_add(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, etype, EV_ADD, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, ASYNC_OUT, EV_DISABLE, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
EV_SET(&kev, fd, etype, EV_ADD, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
int async_del(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, etype, EV_DELETE, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
#endif
inline struct wsgi_request *next_wsgi_req(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
uint8_t *ptr = (uint8_t *) wsgi_req ;
ptr += sizeof(struct wsgi_request) ;
return (struct wsgi_request *) ptr ;
}
int async_get_timeout(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
if (!uwsgi->async_running) return 0;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_timeout_expired) {
return 0;
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return 0;
}
void async_expire_timeouts(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t deadline = time(NULL);
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN && wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_timeout = 0 ;
wsgi_req->async_timeout_expired = 1 ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_OK) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return NULL ;
}
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *uwsgi, int async_id) {
uint8_t *ptr = (uint8_t *) uwsgi->wsgi_requests ;
ptr += sizeof(struct wsgi_request) * async_id ;
return (struct wsgi_request *) ptr ;
}
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *uwsgi, int fd, int etype) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
if (etype != -1) {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd && wsgi_req->async_waiting_fd_type == etype) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
else {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
return NULL ;
}
void async_set_timeout(struct wsgi_request *wsgi_req, time_t timeout) {
wsgi_req->async_timeout = time(NULL);
wsgi_req->async_timeout += timeout;
wsgi_req->async_timeout_expired = 0 ;
}
void async_write_all(struct uwsgi_server *uwsgi, char *data, size_t len) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
ssize_t rlen ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
uwsgi_error("write()");
if (min_timeout) {
timeout = min_timeout->key - time(NULL);
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
}
}
else {
wsgi_req->response_size += rlen ;
timeout = -1;
}
}
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
// timeout ???
if (uwsgi.async_nevents == 0) {
async_expire_timeouts();
}
}
}
void async_unpause_all(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
}
}
}
struct wsgi_request * async_loop(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req ;
int i ;
uwsgi->async_running = -1 ;
wsgi_req = uwsgi->wsgi_requests ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_waiting_fd != -1 && !wsgi_req->async_waiting_fd_monitored) {
// add fd to monitoring
if (async_add(uwsgi->async_queue, wsgi_req->async_waiting_fd, wsgi_req->async_waiting_fd_type)) {
// error adding fd to the async queue, better to close it...
close(wsgi_req->async_waiting_fd);
wsgi_req->async_status = UWSGI_OK ;
return wsgi_req;
for(i=0;i<uwsgi.async_nevents;i++) {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
is_a_new_connection = 0;
// new request coming in ?
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (interesting_fd == uwsgi_sock->fd) {
is_a_new_connection = 1;
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
now = time(NULL);
if (now > last_now) {
uwsgi_log("async queue is full !!!\n");
last_now = now;
}
break;;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi_sock->arg) < 0) {
uwsgi_error("fcntl()");
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
}
#endif
if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
runqueue_push(uwsgi.wsgi_req);
}
break;
}
wsgi_req->async_waiting_fd_monitored = 1;
wsgi_req->async_status = UWSGI_AGAIN;
uwsgi_sock = uwsgi_sock->next;
}
else if (wsgi_req->async_waiting_fd == -1 && wsgi_req->async_timeout <= 0) {
uwsgi->async_running = 0 ;
// st global wsgi_req for python functions
uwsgi->wsgi_req = wsgi_req ;
wsgi_req->async_status = (*uwsgi->shared->hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
wsgi_req->async_switches++;
if (wsgi_req->async_status < UWSGI_AGAIN) {
return wsgi_req;
if (!is_a_new_connection) {
// proto event
uwsgi.wsgi_req = find_wsgi_req_proto_by_fd(interesting_fd);
if (uwsgi.wsgi_req) {
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
// reset timeout
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
// parsing complete
if (!proto_parser_status) {
// remove fd from event poll and fd proto table
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
#endif
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
continue;
}
else if (proto_parser_status == -1) {
uwsgi_log("error parsing request\n");
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
close(interesting_fd);
continue;
}
// re-add timer
async_add_timeout(uwsgi.wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
continue;
}
// app event
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
// unknown fd, remove it (for safety)
if (uwsgi.wsgi_req == NULL) {
close(interesting_fd);
continue;
}
// remove all the fd monitors and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
uwsgi.wsgi_req->async_ready_fd = 1;
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
// event queue managed, give cpu to runqueue
if (!current_request)
current_request = uwsgi.async_runqueue;
if (uwsgi.async_runqueue_cnt) {
uwsgi.wsgi_req = current_request->wsgi_req;
uwsgi.schedule_to_req();
uwsgi.wsgi_req->switches++;
next_async_request = current_request->next;
// request ended ?
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
// remove all the monitored fds and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
// remove from the list
runqueue_remove(current_request);
uwsgi_close_request(uwsgi.wsgi_req);
// push wsgi_request in the unused stack
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from suspended list
runqueue_remove(current_request);
}
current_request = next_async_request;
}
}
return NULL;
}
#endif
+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
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = null
+44
View File
@@ -0,0 +1,44 @@
[uwsgi]
xml = true
ini = true
yaml = true
json = auto
sqlite3 = auto
zeromq = auto
snmp = true
sctp = false
spooler = true
embedded = true
udp = true
multicast = true
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = auto
pcre = auto
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
plugins =
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
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,erlang
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, gevent
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = null
as_shared_library = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = lua
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
plugins = lua
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
plugins = python, ping, rack, psgi, cache, http, fastrouter
plugin_dir = plugins
embedded_plugins = null
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = default
plugin_dir = /usr/lib/uwsgi
embedded_plugins = null
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = psgi
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,erlang,pyerl
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,lua
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = symcall
as_shared_library = true
+31
View File
@@ -0,0 +1,31 @@
[uwsgi]
xml = true
ini = true
snmp = true
sctp = false
erlang = false
spooler = true
embedded = true
udp = true
multicast = true
threading = true
sendfile = true
proxy = true
minterpreters = true
async = true
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rack
[python]
paste = true
web3 = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = rack, ping, cache, nagios, rpc, fastrouter, http, ugreen
+30
View File
@@ -0,0 +1,30 @@
[uwsgi]
xml = true
ini = true
yaml = true
snmp = true
sctp = false
erlang = false
spooler = false
embedded = false
udp = true
multicast = false
threading = true
sendfile = true
nagios = true
proxy = true
minterpreters = true
async = true
ugreen = false
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins = rack
bin_name = uwsgi
plugin_dir = .
embedded_plugins =
+35
View File
@@ -0,0 +1,35 @@
[uwsgi]
xml = true
ini = true
yaml = true
json = true
sqlite3 = true
zeromq = false
snmp = false
sctp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
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
+6
View File
@@ -0,0 +1,6 @@
[uwsgi]
inherit = unbit
json = false
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
+716
View File
@@ -0,0 +1,716 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_init_cache() {
int i;
if (!uwsgi.cache_blocksize)
uwsgi.cache_blocksize = UMAX16;
if ((uwsgi.cache_blocksize * uwsgi.cache_max_items) % uwsgi.page_size != 0) {
uwsgi_log("invalid cache blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.cache_blocksize, uwsgi.page_size);
exit(1);
}
uwsgi.cache_hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache_hashtable) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.cache_hashtable, 0, sizeof(uint64_t) * UMAX16);
uwsgi.cache_unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache_unused_stack) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.cache_unused_stack, 0, sizeof(uint64_t) * uwsgi.cache_max_items);
// the first cache item is always zero
uwsgi.shared->cache_first_available_item = 1;
uwsgi.shared->cache_unused_stack_ptr = 0;
//uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (uwsgi.cache_store) {
uwsgi.cache_filesize = (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items);
int cache_fd;
struct stat cst;
if (stat(uwsgi.cache_store, &cst)) {
uwsgi_log("creating a new cache store file: %s\n", uwsgi.cache_store);
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (cache_fd >= 0) {
// fill the caching store
if (ftruncate(cache_fd, uwsgi.cache_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
if ((size_t) cst.st_size != uwsgi.cache_filesize || !S_ISREG(cst.st_mode)) {
uwsgi_log("invalid cache store file. Please remove it or fix cache blocksize/items to match its size\n");
exit(1);
}
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
uwsgi_log("recovered cache from backing store file: %s\n", uwsgi.cache_store);
}
if (cache_fd < 0) {
uwsgi_error_open(uwsgi.cache_store);
exit(1);
}
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, uwsgi.cache_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
uwsgi_cache_fix();
}
else {
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
}
}
if (!uwsgi.cache_items) {
uwsgi_error("mmap()");
exit(1);
}
/*
uwsgi.cache = mmap(NULL, uwsgi.cache_blocksize * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache) {
uwsgi_error("mmap()");
exit(1);
}
*/
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
uwsgi.cache_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.cache_lock);
uwsgi_log("*** Cache subsystem initialized: %dMB preallocated ***\n", ((sizeof(uint64_t) * UMAX16) + (sizeof(uint64_t) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024));
}
struct uwsgi_subscriber_name *uwsgi_get_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint64_t ovl;
struct uwsgi_subscriber *usub;
struct uwsgi_subscriber_name *ret = NULL;
usub = (struct uwsgi_subscriber *) uwsgi_dict_get(udict, key, keylen, &ovl);
if (usub == NULL || !ovl) return NULL;
if (!usub->nodes) return NULL;
if (usub && ovl) {
ret = &usub->names[usub->current];
// dead node
if (ret->len == 0) {
if (usub->current == usub->nodes-1) {
usub->nodes--;
}
// retry with another node (if available)
if (usub->nodes > 0) {
usub->current++;
if (usub->current >= usub->nodes) usub->current = 0;
return uwsgi_get_subscriber(udict, key, keylen);
}
}
if (usub->nodes > 1) {
usub->current++;
if (usub->current >= usub->nodes) usub->current = 0;
}
}
return ret;
}
void uwsgi_add_subscriber(struct uwsgi_dict *udict, struct uwsgi_subscribe_req *usr) {
char *ptr;
uint64_t vallen = 0;
struct uwsgi_subscriber *usub, nusub;
int found = 0;
int i;
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, usr->address, usr->address_len)) {
found = 1;
break;
}
}
if (!found) {
found = usub->nodes;
// check for unallocated slot
for(i=0;i<(int)usub->nodes;i++) {
if (usub->names[i].len == 0) {
found = i;
break;
}
}
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++;
}
}
return;
}
else {
nusub.nodes = 1;
nusub.current = 0;
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));
}
}
struct uwsgi_dict *uwsgi_dict_create(uint64_t items, uint64_t blocksize) {
int i;
struct uwsgi_dict *udict = (struct uwsgi_dict *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict) {
uwsgi_error("mmap()");
exit(1);
}
if (!blocksize) blocksize = 4096;
if (blocksize % uwsgi.page_size != 0) {
uwsgi_log("invalid shared dictionary blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) udict->blocksize, uwsgi.page_size);
exit(1);
}
udict->blocksize = blocksize;
udict->max_items = items;
udict->hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->hashtable) {
uwsgi_error("mmap()");
exit(1);
}
memset(udict->hashtable, 0, sizeof(uint64_t) * UMAX16);
udict->unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->unused_stack) {
uwsgi_error("mmap()");
exit(1);
}
memset(udict->unused_stack, 0, sizeof(uint64_t) * udict->max_items);
udict->items = (struct uwsgi_dict_item *) mmap(NULL, sizeof(struct uwsgi_dict_item) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->items) {
uwsgi_error("mmap()");
exit(1);
}
udict->data = mmap(NULL, udict->blocksize * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->data) {
uwsgi_error("mmap()");
exit(1);
}
for(i=0;i< (int) udict->max_items;i++) {
memset(&udict->items[i], 0, sizeof(struct uwsgi_dict_item));
}
udict->first_available_item = 1;
udict->unused_stack_ptr = 0;
udict->lock = uwsgi_mmap_shared_lock();
uwsgi_lock_init(udict->lock);
return udict;
}
uint32_t djb33x_hash(char *key, int keylen) {
register uint32_t hash = 5381;
int i;
for(i=0;i<keylen;i++) {
hash = ((hash << 5) + hash) ^ key[i];
}
return hash;
}
inline uint64_t uwsgi_dict_get_index(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
uint64_t slot = udict->hashtable[hash_key];
struct uwsgi_dict_item *udi;
udi = &udict->items[slot];
// first round
if (udi->djbhash != hash) goto cycle;
if (udi->keysize != keylen) goto cycle;
if (memcmp(udi->key, key, keylen)) goto cycle;
return slot;
cycle:
while(udi->next) {
slot = udi->next;
udi = &udict->items[slot];
if (udi->djbhash != hash) continue;
if (udi->keysize != keylen) continue;
if (!memcmp(udi->key, key, keylen)) return slot;
}
return 0;
}
char *uwsgi_dict_get(struct uwsgi_dict *udict, char *key, uint16_t keylen, uint64_t *valsize) {
uint64_t index = uwsgi_dict_get_index(udict, key, keylen);
if (index) {
*valsize = udict->items[index].valsize;
udict->items[index].hits++;
return udict->data+(index*udict->blocksize);
}
return NULL;
}
int uwsgi_dict_del(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint64_t index = 0;
struct uwsgi_dict_item *udi;
int ret = -1;
index = uwsgi_dict_get_index(udict, key, keylen);
if (index) {
udi = &udict->items[index] ;
udi->keysize = 0;
udi->valsize = 0;
udict->unused_stack_ptr++;
udict->unused_stack[udict->unused_stack_ptr] = index;
// try to return to initial condition...
if (index == udict->first_available_item-1) {
udict->first_available_item--;
}
ret = 0;
// relink collisioned entry
if (udi->prev) {
udict->items[udi->prev].next = udi->next;
}
if (udi->next) {
udict->items[udi->next].prev = udi->prev;
}
if (!udi->prev && !udi->next) {
// reset hashtable entry
udict->hashtable[udi->djbhash % 0xffff] = 0;
}
udi->djbhash = 0;
udi->prev = 0;
udi->next = 0;
}
return ret;
}
inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
uint64_t slot = uwsgi.cache_hashtable[hash_key];
struct uwsgi_cache_item *uci;
//uwsgi_log("found slot %d for key %d\n", slot, hash_key);
uci = &uwsgi.cache_items[slot];
// first round
if (uci->djbhash != hash) goto cycle;
if (uci->keysize != keylen) goto cycle;
if (memcmp(uci->key, key, keylen)) goto cycle;
return slot;
cycle:
while(uci->next) {
slot = uci->next;
uci = &uwsgi.cache_items[slot];
if (uci->djbhash != hash) continue;
if (uci->keysize != keylen) continue;
if (!memcmp(uci->key, key, keylen)) return slot;
}
return 0;
}
uint32_t uwsgi_cache_exists(char *key, uint16_t keylen) {
return uwsgi_cache_get_index(key, keylen);
}
char *uwsgi_cache_get(char *key, uint16_t keylen, uint64_t *valsize) {
uint64_t index = uwsgi_cache_get_index(key, keylen);
if (index) {
if (uwsgi.cache_items[index].flags & UWSGI_CACHE_FLAG_UNGETTABLE) return NULL;
*valsize = uwsgi.cache_items[index].valsize;
uwsgi.cache_items[index].hits++;
return uwsgi.cache+(index*uwsgi.cache_blocksize);
}
return NULL;
}
int uwsgi_cache_del(char *key, uint16_t keylen) {
uint64_t index = 0;
struct uwsgi_cache_item *uci;
int ret = -1;
index = uwsgi_cache_get_index(key, keylen);
if (index) {
uci = &uwsgi.cache_items[index] ;
uci->keysize = 0;
uci->valsize = 0;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = index;
// try to return to initial condition...
if (index == uwsgi.shared->cache_first_available_item-1) {
uwsgi.shared->cache_first_available_item--;
//uwsgi_log("FACI: %llu STACK PTR: %llu\n", (unsigned long long) uwsgi.shared->cache_first_available_item, (unsigned long long) uwsgi.shared->cache_unused_stack_ptr);
}
ret = 0;
// relink collisioned entry
if (uci->prev) {
uwsgi.cache_items[uci->prev].next = uci->next;
}
if (uci->next) {
uwsgi.cache_items[uci->next].prev = uci->prev;
}
if (!uci->prev && !uci->next) {
// reset hashtable entry
//uwsgi_log("!!! resetted hashtable entry !!!\n");
uwsgi.cache_hashtable[uci->djbhash % 0xffff] = 0;
}
uci->djbhash = 0;
uci->prev = 0;
uci->next = 0;
}
return ret;
}
void uwsgi_cache_fix() {
uint64_t i;
for(i=0;i< uwsgi.cache_max_items;i++) {
// valid record ?
if (uwsgi.cache_items[i].keysize) {
if (!uwsgi.cache_items[i].prev) {
// put value in hash_table
uwsgi.cache_hashtable[ uwsgi.cache_items[i].djbhash % 0xffff] = i;
}
}
else {
// put this record in unused stack
uwsgi.shared->cache_first_available_item = i;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = i;
}
}
}
int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint16_t flags) {
uint64_t index = 0, last_index = 0 ;
struct uwsgi_cache_item *uci, *ucii;
int ret = -1;
int slot;
if (!keylen || !vallen) return -1;
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
if (uwsgi.shared->cache_first_available_item >= uwsgi.cache_max_items && !uwsgi.shared->cache_unused_stack_ptr) {
uwsgi_log("*** DANGER cache is FULL !!! ***\n");
goto end;
}
//uwsgi_log("putting cache data in key %.*s %d\n", keylen, key, vallen);
index = uwsgi_cache_get_index(key, keylen);
if (!index) {
if (uwsgi.shared->cache_unused_stack_ptr) {
//uwsgi_log("!!! REUSING CACHE SLOT !!! (faci: %llu)\n", (unsigned long long) uwsgi.shared->cache_first_available_item);
index = uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr];
uwsgi.shared->cache_unused_stack_ptr--;
}
else {
index = uwsgi.shared->cache_first_available_item;
if (uwsgi.shared->cache_first_available_item < uwsgi.cache_max_items) {
uwsgi.shared->cache_first_available_item++;
}
}
uci = &uwsgi.cache_items[index] ;
if (expires) expires += time(NULL);
uci->expires = expires;
uci->djbhash = djb33x_hash(key, keylen);
uci->hits = 0;
uci->flags = flags;
memcpy(uci->key, key, keylen);
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
// set this as late as possibile (to reduce races risk)
uci->valsize = vallen;
uci->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
slot = uci->djbhash % 0xffff;
if (uwsgi.cache_hashtable[slot] == 0) {
uwsgi.cache_hashtable[slot] = index;
}
else {
//uwsgi_log("HASH COLLISION !!!!\n");
// append to first available next
last_index = uwsgi.cache_hashtable[slot];
ucii = &uwsgi.cache_items[ last_index ];
while(ucii->next) {
last_index = ucii->next;
ucii = &uwsgi.cache_items[ last_index ];
}
ucii->next = index;
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;
}
int uwsgi_dict_set(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *val, uint64_t vallen) {
uint64_t index = 0, last_index = 0 ;
struct uwsgi_dict_item *udi, *udii;
int ret = -1;
int slot;
if (!keylen || !vallen) return -1;
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
if (udict->first_available_item >= udict->max_items && !udict->unused_stack_ptr) {
uwsgi_log("*** DANGER dictionary %p is FULL !!! ***\n", udict);
goto end;
}
index = uwsgi_dict_get_index(udict, key, keylen);
if (!index) {
if (udict->unused_stack_ptr) {
index = udict->unused_stack[udict->unused_stack_ptr];
udict->unused_stack_ptr--;
}
else {
index = udict->first_available_item;
if (udict->first_available_item < udict->max_items) {
udict->first_available_item++;
}
}
udi = &udict->items[index] ;
udi->djbhash = djb33x_hash(key, keylen);
udi->hits = 0;
memcpy(udi->key, key, keylen);
memcpy(udict->data+(index*udict->blocksize), val, vallen);
// set this as late as possibile (to reduce races risk)
udi->valsize = vallen;
udi->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
slot = udi->djbhash % 0xffff;
if (udict->hashtable[slot] == 0) {
udict->hashtable[slot] = index;
}
else {
// append to first available next
last_index = udict->hashtable[slot];
udii = &udict->items[ last_index ];
while(udii->next) {
last_index = udii->next;
udii = &udict->items[ last_index ];
}
udii->next = index;
udi->prev = last_index;
}
}
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;
}
+18
View File
@@ -0,0 +1,18 @@
require 'fiber'
require 'sinatra'
get '/hi' do
class Response
def each
for i in 1..10
yield "ciao<br/>"
Fiber.yield
end
end
end
Response.new
end
run Sinatra::Application
+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")]
}
+7
View File
@@ -0,0 +1,7 @@
require 'sinatra'
get '/hi' do
"Hello World"
end
run Sinatra::Application
+68 -68
View File
@@ -17,10 +17,10 @@ sub new {
sub run {
my ($self, $app) = @_;
my $server ;
my $server;
if (exists($ENV{'UWSGI_FD'})) {
$server = IO::Socket::UNIX->new_from_fd($ENV{'UWSGI_FD'}, '+<');
$server = IO::Socket::UNIX->new_from_fd($ENV{'UWSGI_FD'}, '+<');
}
else {
$server = IO::Socket::INET->new(LocalPort => $self->{port}, LocalAddr => $self->{host}, Listen => 100, ReuseAddr => 1);
@@ -28,62 +28,62 @@ sub run {
while ( my $client = $server->accept ) {
my $head = '';
my $remains = 4 ;
my $head = '';
my $remains = 4;
while($remains) {
$client->recv(my $buf, $remains);
last unless $buf;
$head.=$buf;
$remains -= length($buf);
}
while($remains) {
$client->recv(my $buf, $remains);
last unless $buf;
$head.=$buf;
$remains -= length($buf);
}
if (length($head) != 4) {
$client->close ;
next;
}
if (length($head) != 4) {
$client->close;
next;
}
my ($mod1, $envsize, $mod2) = unpack('CvC', $head) ;
my ($mod1, $envsize, $mod2) = unpack('CvC', $head);
unless ($envsize) {
$client->close ;
next;
}
unless ($envsize) {
$client->close;
next;
}
$remains = $envsize ;
my $envbuf = '' ;
while($remains) {
my $buf ;
if ($remains >= 4096) {
$client->recv($buf, 4096);
}
else {
$client->recv($buf, $remains);
}
$remains = $envsize;
my $envbuf = '';
while($remains) {
my $buf;
if ($remains >= 4096) {
$client->recv($buf, 4096);
}
else {
$client->recv($buf, $remains);
}
unless($buf) {
$client->close ;
next;
}
unless($buf) {
$client->close;
next;
}
$envbuf.=$buf;
$remains -= length($buf);
}
$envbuf.=$buf;
$remains -= length($buf);
}
if (length($envbuf) != $envsize ) {
$client->close ;
next;
}
if (length($envbuf) != $envsize ) {
$client->close;
next;
}
my %env ;
my %env;
my $i = 0;
while($i < $envsize) {
my $kl = unpack('v', substr($envbuf, $i, 2)) ; $i+=2;
my $key = substr($envbuf, $i, $kl); $i+=$kl;
my $vl = unpack('v', substr($envbuf, $i, 2)) ; $i+=2;
$env{$key} = substr($envbuf, $i, $vl); $i+=$vl;
}
my $i = 0;
while($i < $envsize) {
my $kl = unpack('v', substr($envbuf, $i, 2)); $i+=2;
my $key = substr($envbuf, $i, $kl); $i+=$kl;
my $vl = unpack('v', substr($envbuf, $i, 2)); $i+=2;
$env{$key} = substr($envbuf, $i, $vl); $i+=$vl;
}
my $env = {
%env,
@@ -105,40 +105,40 @@ sub run {
}
elsif (ref $res eq 'CODE') {
$res->(sub {
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $_[0]);
});
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $_[0]);
});
}
else {
die "Bad response $res";
}
$client->close ;
$client->close;
}
}
sub _handle_response {
my ($self, $client, $protocol, $res) = @_;
my ($self, $client, $protocol, $res) = @_;
$client->send($protocol.' '.$res->[0].' '.HTTP::Status::status_message( $res->[0] )."\r\n");
$client->send($protocol.' '.$res->[0].' '.HTTP::Status::status_message( $res->[0] )."\r\n");
my $headers = $res->[1];
my $hdrs = '';
while (my ($k, $v) = splice @$headers, 0, 2) {
$hdrs .= "$k: $v\r\n";
}
$hdrs .= "\r\n";
my $headers = $res->[1];
my $hdrs = '';
while (my ($k, $v) = splice @$headers, 0, 2) {
$hdrs .= "$k: $v\r\n";
}
$hdrs .= "\r\n";
$client->send($hdrs);
$client->send($hdrs);
my $cb = sub { $client->send($_[0]) };
my $body = $res->[2];
if (defined $body) {
Plack::Util::foreach($body, $cb);
}
else {
return Plack::Util::inline_object write => $cb,close => sub { };
}
my $cb = sub { $client->send($_[0]) };
my $body = $res->[2];
if (defined $body) {
Plack::Util::foreach($body, $cb);
}
else {
return Plack::Util::inline_object write => $cb,close => sub { };
}
}
1;
+33
View File
@@ -0,0 +1,33 @@
# uwsgi --master --chdir /opt/graphite/webapp/graphite --module graphite_uwsgi ...
#
#
# this module will update a carbon server (used by the graphite tool: http://graphite.wikidot.com/)
# with requests count made by a Django app (and can track graphite itself as it is a Django app ;)
#
#
import os
import uwsgi
import time
from django.core.handlers.wsgi import WSGIHandler
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
CARBON_SERVER = "127.0.0.1:2003"
def update_carbon(signum):
# connect to the carbon server
carbon_fd = uwsgi.connect(CARBON_SERVER)
# send data to the carbon server
uwsgi.send(carbon_fd, "uwsgi.%s.requests %d %d\n" % (uwsgi.hostname, uwsgi.total_requests(), int(time.time())))
# close the connection with the carbon server
uwsgi.close(carbon_fd)
# register a new uwsgi signal (signum: 17)
uwsgi.register_signal(17, '', update_carbon)
# attach a timer of 10 seconds to signal 17
uwsgi.add_timer(17, 10)
# the Django app
application = WSGIHandler()
+66
View File
@@ -0,0 +1,66 @@
import django
from django.core.management.base import BaseCommand
from django.conf import settings
import os
import sys
class Command(BaseCommand):
help = "Runs this project as a uWSGI application. Requires the uwsgi binary in system path."
http_port = '8000'
socket_addr = None
def handle(self, *args, **options):
for arg in args:
k,v = arg.split('=')
if k == 'http':
if self.http_port:
self.http_port = v
elif k == 'socket':
self.http_port = None
self.socket_addr = v
# load http and python plugin: first the specific version, otherwise try with the generic one
if self.http_port:
os.environ['UWSGI_PLUGINS'] = 'http,python%d%d:python' % (sys.version_info[0], sys.version_info[1])
else:
os.environ['UWSGI_PLUGINS'] = 'python%d%d:python' % (sys.version_info[0], sys.version_info[1])
# load the Django WSGI handler
os.environ['UWSGI_MODULE'] = 'django.core.handlers.wsgi:WSGIHandler()'
# DJANGO settings
if options['settings']:
os.environ['DJANGO_SETTINGS_MODULE'] = options['settings']
else:
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
# bind the http server to the default port
if self.http_port:
os.environ['UWSGI_HTTP'] = ':%s' % self.http_port
elif self.socket_addr:
os.environ['UWSGI_SOCKET'] = self.socket_addr
# map admin static files
os.environ['UWSGI_STATIC_MAP'] = '%s=%s' % (settings.ADMIN_MEDIA_PREFIX, os.path.join(django.__path__[0], 'contrib', 'admin', 'media'))
# remove sockets/pidfile at exit
os.environ['UWSGI_VACUUM'] = '1'
# retrieve/set the PythonHome
os.environ['UWSGI_PYHOME'] = sys.prefix
# increase buffer size a bit
os.environ['UWSGI_BUFFER_SIZE'] = '8192'
# add threads for concurrency
os.environ['UWSGI_THREADS'] = '8'
# enable the master process
os.environ['UWSGI_MASTER'] = '1'
# use uWSGI python module aliasing to fix the PYTHONPATH
os.environ['UWSGI_PYMODULE_ALIAS'] = '%s=./' % os.path.basename(os.getcwd())
# exec the uwsgi binary
os.execvp('uwsgi', ('uwsgi',))
def usage(self, subcomand):
return r"""
run this project on the uWSGI server
http=PORT run the embedded http server on port PORT
socket=ADDR bind the uwsgi server on address ADDR (this will disable the http server)
"""
+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)
+17
View File
@@ -0,0 +1,17 @@
# uWSGI - manage uWSGI application server
#
description "uWSGI"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --no-orphans avoid workers without master
# --die-on-term could be a good idea
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
+301 -274
View File
@@ -1,303 +1,330 @@
# Copyright 2009 Unbit S.a.s. <info@unbit.it>
# see the COPYRIGHT file
require 'rubygems'
require 'socket'
require 'rack'
require 'rack/content_length'
require 'rack/rewindable_input'
require 'stringio'
$stdout.sync = true
options = {}
require 'optparse'
options = {
:processes => 1,
:threads => 1,
:master => false,
:logging => true,
:static => true,
:config => nil,
:cachehack => false
}
opts = OptionParser.new do |opts|
opts.on("-p", "--processes=nproc", Integer, '') { |p| options[:processes] = p }
opts.on("-t", "--threads=nthreads", Integer, '') { |t| options[:threads] = t }
opts.on("-M", "--master", '') { options[:master] = true }
opts.on("-L", "--no-logging", '') { options[:logging] = false }
opts.on("-S", "--no-static", '') { options[:static] = false }
opts.on("-C", "--cache-hack", '') { options[:cachehack] = true }
opts.parse! ARGV
end
if ARGV[0]
options[:config] = ARGV[0]
end
def human_round(float)
(float * (10 ** 2)).round / (10 ** 2).to_f
end
$domain = ARGV.last.gsub('[','').gsub(']','')
$unbit_log_base = "[uRack/Unbit on #{$domain}]"
$limit_as = human_round(Process.getrlimit(Process::RLIMIT_AS)[1].to_f/1024/1024)
puts "#{$unbit_log_base} process address space limit is #{$limit_as} MB"
$uidsec_size = syscall(357,0,0)
puts "#{$unbit_log_base} need #{$uidsec_size} bytes to store uidsec_struct..."
$uidsec = '1' * $uidsec_size
puts "#{$unbit_log_base} uidsec_struct allocated."
options[:processes] = 1
options[:serve_file] = nil
options[:max_input_size] = 8
options[:unbit_debug] = false
options[:master] = true
options[:gc_freq] = nil
puts "[#{Time.new}] uRack: loading app [#{RAILS_ROOT}]..."
starttime = Time.now
require "config/environment"
require 'socket'
require 'rubygems'
require 'rack'
require 'rack/utils'
require 'rack/content_length'
$requests = 0
$workers = Array.new
$mywid = 0
module Rack
module Handler
class Unbit
class Tempfile < ::Tempfile
def _close
@tmpfile.close if @tmpfile
@data[1] = nil if @data
@tmpfile = nil
end
end
def self.run(app, options={})
master_pid = Process.pid
options[:processes] ||= 1
class RailsCachingHack
def initialize app
@app = app
end
server = UNIXServer.for_fd(0)
def stripuri(uri)
uri = uri.split('/')
uri.slice!(1)
val = uri.join('/')
end
def call env
env['PATH_INFO'] = stripuri(env['PATH_INFO']) if env['PATH_INFO']
env['REQUEST_URI'] = stripuri(env['REQUEST_URI']) if env['REQUEST_URI']
env['REQUEST_URI'] = '/' if env['REQUEST_URI'] == ''
@app.call env
end
end
$workers = Array.new
module Handler
class Unbit
if options[:master]
$0 = "uRack #{ARGV.last}"
pid = Process.fork
if pid.to_i > 0
puts "[#{Time.new}] uRack: spawned rack worker 1 (pid: #{pid})"
$workers[1] = pid ;
end
end
def self.run(app, options={})
server = UNIXServer.for_fd(0)
# the check on master pid is necessary
# without it the first worker will execute this part
if options[:processes] > 1 and Process.pid == master_pid
for p in 2..options[:processes]
pid = Process.fork
break if pid.to_i == 0
puts "[#{Time.new}] uRack: spawned rack worker #{p} (pid: #{pid})"
$workers[p] = pid ;
end
end
can_spawn = true
if options[:master]
$0 = 'uRack master'
$workers[0] = Process.pid
ulog("master process enabled (pid: #{$workers[0]})")
$workers[1] = Process.fork
if $workers[1].to_i > 0
ulog("spawned worker 1 (pid: #{$workers[1]})")
elsif $workers[1].to_i == 0
$0 = "uRack worker 1"
$mywid = 1
can_spawn = false
end
else
$0 = 'uRack worker 1'
$workers[0] = nil
$workers[1] = Process.pid
$mywid = 1
ulog("spawned worker 1 (pid: #{$workers[1]})")
end
# am i the master ?
if options[:master] and Process.pid == master_pid
Signal.trap('TERM') do
puts "[#{Time.new}] uRack: gracefully killing uRack"
for wid in 1..options[:processes]
Process.kill('TERM', $workers[wid]);
end
exit 0;
end
Signal.trap('QUIT') do
puts "[#{Time.new}] uRack: brutally killing uRack"
for wid in 1..options[:processes]
Process.kill('INT', $workers[wid]);
end
exit 0;
end
puts "[#{Time.new}] uRack: the master process manager is alive."
while 1
pid = Process.waitpid
puts "[#{Time.new}] uRack: worker died ! (pid: #{pid})"
newpid = Process.fork
break if newpid.to_i == 0
puts "[#{Time.new}] uRack: respawned rack worker (pid: #{newpid})"
for wid in 1..options[:processes]
if $workers[wid] == pid
$workers[wid] = newpid
break
end
end
end
end
if Process.pid != master_pid
$0 = $0.gsub(/^uRack/,'urack')
Signal.trap("TERM") do
puts "[#{Time.new}] uRack: grecefully killing process #{Process.pid}..."
if $in_request == 0
puts "[#{Time.new}] uRack: goodbye to process #{Process.pid}"
exit 0
end
$manage_next_request = nil
end
Signal.trap('INT') do
puts "[#{Time.new}] uRack: brutally killing process #{Process.pid}..."
exit 0
end
Signal.trap('PIPE') do
puts "[#{Time.new}] uRack: the webserver (or the client) has closed the connection with process #{Process.pid} !!!"
end
end
max_input_size = options[:max_input_size].to_i * 1024
requests = 0
null_post = StringIO.new('')
options[:app_name] ||= Dir.getwd
app = Rack::ContentLength.new(app)
$manage_next_request = true
if options[:gc_freq].to_i > 1
GC.disable
end
while $manage_next_request
$in_request = 0
client = server.accept
$in_request = 1
timed_out = false
ver, size, arg1 = client.recvfrom(4)[0].unpack('CvC')
vars = client.recvfrom(size)[0]
env = Hash.new
i = 0
while i < size
kl = vars[i, 2].unpack('v')[0]
i = i + 2
key = vars[i, kl]
i = i + kl
vl = vars[i, 2].unpack('v')[0]
i = i + 2
value = vars[i, vl]
i = i + vl
env[key] = value
end
rack_input = null_post
env.delete 'CONTENT_LENGTH' if env['CONTENT_LENGTH'] == ''
if env['CONTENT_LENGTH'].to_i > 0
cl = env['CONTENT_LENGTH'].to_i
if cl <= max_input_size
poststr = ''
while poststr.size < cl
poststr = poststr + client.recvfrom(cl-poststr.size)[0] ;
end
rack_input = StringIO.new(poststr)
else
rack_input = Tempfile.new('UnbitRack')
rack_input.chmod(0000)
bytes_read = 0
while bytes_read < cl
buf = client.recvfrom(4096)[0]
rack_input.write(buf)
bytes_read += buf.size
end
rack_input.rewind
end
end
env["SCRIPT_NAME"] = ""
env.update({"rack.version" => [0,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => "http"
})
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
begin
#puts env.inspect
$start_of_request = Time.new
status, headers, body = app.call(env)
$speed = Time.new - $start_of_request
client.print "#{env["HTTP_VERSION"]} #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}\r\n"
headers.each {|k,vs|
vs.split("\n").each { |v|
client.print "#{k}: #{v}\r\n"
}
}
client.print "\r\n"
client.flush
body.each {|part|
client.print part
client.flush
}
rescue Errno::EPIPE
puts "[#{Time.new}] uRack: the webserver (or the client) has closed the connection with process #{Process.pid} !!!"
timed_out = true
ensure
if rack_input.respond_to? :unlink
rack_input.unlink
end
unless rack_input.closed?
rack_input.close
end
client.close
requests = requests+1
# logging
$stderr.puts "[#{Time.new}] uRack: [#{options[:app_name]}] req: #{requests} ip: #{env['REMOTE_ADDR']} pid: #{Process.pid} as: #{human_round(syscall(356).to_f/1024/1024)} MB => #{env['REQUEST_METHOD']} #{env['REQUEST_URI']} in #{$speed} secs [#{status}]#{' TIMED OUT !!!' if timed_out}"
if syscall(357, $uidsec, 0) == $uidsec_size
if $uidsec[120..123].unpack('i')[0] > 0
$stderr.puts "[#{Time.new}] uRack: found a memory allocation error for request #{requests} (pid: #{Process.pid}). Better to kill myself..."
$manage_next_request = nil
end
end
$uidsec = '1' * $uidsec_size
if options[:unbit_debug]
current_as = human_round( (syscall(356).to_f/1024/1024) - $last_as )
$stderr.puts "#{$unbit_log_base} resource status after request #{requests}: AS for this request: #{current_as} MB | OBJ for this request: #{ObjectSpace.each_object {} - $last_obj} | OBJ total: #{ObjectSpace.each_object {}}"
$last_as = human_round(syscall(356).to_f/1024/1024) ;
$last_obj = ObjectSpace.each_object {}
end
if options[:gc_freq].to_i > 1
if requests % options[:gc_freq].to_i == 0
$stderr.puts "[#{Time.new}] uRack: [#{options[:app_name]}] calling GC for pid #{Process.pid} after #{requests} requests."
GC.enable ; GC.start ; GC.disable
end
end
end
end
puts "[#{Time.new}] uRack: goodbye to process #{Process.pid}"
if options[:processes] > 1 and can_spawn
for p in 2..options[:processes]
$workers[p] = Process.fork
if $workers[p].to_i == 0
$0 = "uRack worker #{p}"
$mywid = p
break
elsif $workers[p].to_i > 0
ulog("spawned worker #{p} (pid: #{$workers[p]})")
end
end
end
# am i the master ?
if options[:master] and Process.pid == $workers[0]
while 1
i_am_a_child = false
pid = Process.waitpid
for wid in 1..options[:processes]
if $workers[wid] == pid
ulog("worker #{wid} died ! (pid: #{pid})")
$workers[wid] = Process.fork
if $workers[wid].to_i == 0
$0 = "uRack worker #{wid}"
i_am_a_child = true
$mywid = wid
break
elsif $workers[wid].to_i > 0
ulog("respawned worker #{wid} (pid: #{$workers[wid]})")
end
end
end
break if i_am_a_child
end
end
if options[:threads] > 2
for t in 2..options[:threads]
wt = Thread.new do
ulog("spawning thread #{t} on worker #{$mywid}")
while client = server.accept
serve client, app, options
end
end
end
end
while client = server.accept
serve client, app, options
end
end
def self.serve(client, app, options)
speed = Time.now
head, sender = client.recvfrom(4)
unless head
client.close
return
end
mod1, size, mod2 = head.unpack('CvC')
if size == 0 or size.nil?
client.close
return
end
vars, sender = client.recvfrom(size)
if vars.length != size
client.close
return
end
env = Hash.new
i = 0
while i < size
kl = vars[i, 2].unpack('v')[0]
i = i + 2
key = vars[i, kl]
i = i + kl
vl = vars[i, 2].unpack('v')[0]
i = i + 2
value = vars[i, vl]
i = i + vl
env[key] = value
end
env.delete "HTTP_CONTENT_LENGTH"
env.delete "HTTP_CONTENT_TYPE"
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == ""
if env["CONTENT_LENGTH"].to_i > 4096
rack_input = Rack::RewindableInput::Tempfile.new('Rack_unbit_Input')
rack_input.chmod(0000)
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
rack_input.binmode
rack_input.unlink
remains = env["CONTENT_LENGTH"].to_i
while remains > 0
if remains >= 4096
buf, sender = client.recvfrom(4096)
else
buf, sender = client.recvfrom(remains)
end
if buf.length == 0
break
end
rack_input.write( buf )
remains -= buf.length
end
elsif env["CONTENT_LENGTH"].to_i > 0
rack_input = StringIO.new(client.recvfrom(env["CONTENT_LENGTH"].to_i)[0])
else
rack_input = StringIO.new('')
end
rack_input.rewind
env.update({"rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
})
app = Rack::ContentLength.new(app)
disconnected = false
begin
status, headers, body = app.call(env)
begin
send_headers client, env["HTTP_VERSION"] ,status, headers
send_body client, body
ensure
body.close if body.respond_to? :close
end
rescue Errno::EPIPE, Errno::ECONNRESET
disconnected = true
ensure
rack_input.close
client.close
end
$requests = $requests+1
ulog("req: #{$requests} ip: #{env['REMOTE_ADDR']} pid: #{Process.pid} as: #{human_round(syscall(356).to_f/1024/1024)} MB => #{env['REQUEST_METHOD']} #{env['REQUEST_URI']} in #{Time.now-speed} secs [#{status}]#{' DISCONNECTED !!!' if disconnected}") if options[:logging]
end
def self.send_headers(client, protocol, status, headers)
client.print "#{protocol} #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}\r\n"
headers.each { |k, vs|
vs.split("\n").each { |v|
client.print "#{k}: #{v}\r\n"
}
}
client.print "\r\n"
client.flush
end
def self.send_body(client, body)
body.each { |part|
client.print part
client.flush
}
end
end
end
end
def ulog(message)
$stderr.puts "[#{Time.new}] uRack: #{message}"
end
ulog("starting at #{Dir.getwd}")
limit_as = human_round(Process.getrlimit(Process::RLIMIT_AS)[1].to_f/1024/1024)
ulog("your process address space limit is #{limit_as} MB")
server = Rack::Handler.get('Unbit')
app = Rack::Builder.new {
if options[:serve_file]
puts "[#{Time.new}] uRack: file serving enabled."
use Rails::Rack::Static
starttime = Time.now
app = nil
if options[:config]
cfgfile = File.read(options[:config])
if cfgfile[/^#\\(.*)/]
opts.parse! $1.split(/\s+/)
end
if ActionController.const_defined?(:Dispatcher) && (ActionController::Dispatcher.instance_methods.include?(:call) || ActionController::Dispatcher.instance_methods.include?("call"))
run ActionController::Dispatcher.new
app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app", nil, options[:config]
else
# falling back to rails
if Dir.getwd =~ /\/public\/?$/
require '../config/environment'
else
require 'thin'
run Rack::Adapter::Rails.new(:environment => ENV['RAILS_ENV'])
require 'config/environment'
end
}.to_app
app = Rack::Builder.new {
if options[:cachehack]
use Rack::RailsCachingHack
end
if options[:static]
use Rails::Rack::Static
end
if ActionController.const_defined?(:Dispatcher) && (ActionController::Dispatcher.instance_methods.include?(:call) || ActionController::Dispatcher.instance_methods.include?("call"))
run ActionController::Dispatcher.new
else
require 'thin'
run Rack::Adapter::Rails.new(:environment => ENV['RAILS_ENV'])
end
}
end
$after_spawn_used_as = human_round(syscall(356).to_f/1024/1024)
$stderr.puts "#{$unbit_log_base} now you have #{$limit_as-$after_spawn_used_as} MB of address space available (used #{$after_spawn_used_as}MB after app startup)"
secs = Time.now-starttime
puts "[#{Time.new}] uRack: ready to serve requests after #{secs.to_i} secs (pid: #{Process.pid})"
ulog("your app is ready (in #{Time.now-starttime} seconds).")
$last_as = $after_spawn_used_as ;
$last_obj = ObjectSpace.each_object {}
server.run(app, options)
+30
View File
@@ -0,0 +1,30 @@
-module(uwsgi).
-export([encode/1,send/3]).
encode(Vars) ->
Body = lists:map(fun(X) -> Len = length(X), lists:append( binary_to_list(<<Len:16/little-unsigned-integer>>), X) end, Vars),
lists:flatten(Body).
response(Sock, Output) ->
case gen_tcp:recv(Sock,0) of
{ ok, Data } ->
response(Sock, lists:append(Output, binary_to_list(Data)));
{ error, closed } ->
gen_tcp:close(Sock),
Output
end.
send(Host, Port, Message) ->
{ ok, Sock } = gen_tcp:connect( Host, Port, [ binary, { active, false} ]),
Body = encode(Message),
Len = length(Body),
ok = gen_tcp:send(Sock, << 0, Len:16/little-unsigned-integer, 0>>),
ok = gen_tcp:send(Sock, Body),
response(Sock, []).
+27 -28
View File
@@ -6,7 +6,6 @@ import java.util.Enumeration;
import org.apache.catalina.util.IOTools;
public class uwsgi extends HttpServlet {
private String mountpoint = null;
public void init(ServletConfig config) throws ServletException {
@@ -22,34 +21,34 @@ public class uwsgi extends HttpServlet {
if (getServletConfig().getInitParameter("mountpoint") != null) {
mountpoint = getServletConfig().getInitParameter("mountpoint");
if (mountpoint.length() <= 1) {
mountpoint = null ;
mountpoint = null;
}
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
throws IOException, ServletException {
uWSGIHandler(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
throws IOException, ServletException {
uWSGIHandler(request, response);
}
private void uWSGIHandler(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
throws IOException, ServletException {
Socket client = new Socket("localhost",3017);
ByteArrayOutputStream uwsgi_request = new ByteArrayOutputStream() ;
ByteArrayOutputStream uwsgi_request = new ByteArrayOutputStream();
DataOutputStream wos = new DataOutputStream(uwsgi_request);
DataOutputStream os = new DataOutputStream(client.getOutputStream());
DataInputStream is = new DataInputStream( client.getInputStream() );
ServletOutputStream out = response.getOutputStream();
boolean hasBody = false;
@@ -104,14 +103,14 @@ public class uwsgi extends HttpServlet {
if (mountpoint != null) {
wos.writeShort(swapShort( (short) 11));
wos.writeBytes("SCRIPT_NAME");
wos.writeShort(swapShort( (short) mountpoint.length() ) ) ;
wos.writeBytes( mountpoint ) ;
wos.writeBytes("SCRIPT_NAME");
wos.writeShort(swapShort( (short) mountpoint.length() ) );
wos.writeBytes( mountpoint );
}
wos.writeShort(swapShort( (short) 9));
wos.writeBytes("PATH_INFO");
wos.writeBytes("PATH_INFO");
if (mountpoint != null) {
wos.writeShort(swapShort( (short) (request.getRequestURI().length() - mountpoint.length()) ) );
wos.writeBytes( request.getRequestURI().substring(mountpoint.length()) );
@@ -149,14 +148,14 @@ public class uwsgi extends HttpServlet {
hasBody = true;
}
// taken from CGI servlet
Enumeration headers = request.getHeaderNames();
String header = null;
while (headers.hasMoreElements()) {
header = null;
header = ((String) headers.nextElement()).toUpperCase();
header = null;
header = ((String) headers.nextElement()).toUpperCase();
wos.writeShort(swapShort( (short) ("HTTP_" + header.replace('-', '_')).length() ));
wos.writeBytes("HTTP_" + header.replace('-', '_'));
wos.writeShort(swapShort( (short) request.getHeader(header).length() ));
@@ -175,16 +174,16 @@ public class uwsgi extends HttpServlet {
IOTools.flow(request.getInputStream(), os);
}
boolean statusParsed = false ;
boolean statusParsed = false;
for(;;) {
String line = byte_readline(is) ;
String line = byte_readline(is);
if (line == "") {
break;
}
if (statusParsed == false) {
String[] status = line.split(" ",3);
response.setStatus( Integer.parseInt(status[1]) );
statusParsed = true ;
statusParsed = true;
}
else {
String[] keyval = line.split(": ",2);
@@ -200,7 +199,7 @@ public class uwsgi extends HttpServlet {
byte cb[] = new byte[4096];
int len = 0;
for(;;) {
len = is.read(cb,0,4096) ;
len = is.read(cb,0,4096);
if ( len > 0) {
out.write(cb,0,len);
}
@@ -208,7 +207,7 @@ public class uwsgi extends HttpServlet {
break;
}
}
}
@@ -218,19 +217,19 @@ public class uwsgi extends HttpServlet {
for(;;) {
byte b = is.readByte();
if (b == 10) {
break ;
break;
}
line.write(b) ;
line.write(b);
}
return line.toString("ASCII").replaceAll("\\n","").replaceAll("\\r","");
}
private short swapShort(short x) {
short tmp1 = (short) (x>>8) ;
short tmp2 = (short) (x<<8) ;
return (short) (tmp1 | tmp2) ;
short tmp1 = (short) (x>>8);
short tmp2 = (short) (x<<8);
return (short) (tmp1 | tmp2);
}
}
+65 -65
View File
@@ -2,8 +2,8 @@
*** uWSGI cgi client ***
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_client.c
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_client.c
*/
@@ -18,79 +18,79 @@ to compile:
#define UWSGI_SOCK "/tmp/uwsgi.sock"
int main() {
extern char **environ;
char *env ;
struct sockaddr_un s_addr ;
int uwsgi_socket ;
int res, cnt;
char *place_holder;
unsigned short len ;
char message[4096];
char *mptr;
extern char **environ;
char *env;
struct sockaddr_un s_addr;
int uwsgi_socket;
int res, cnt;
char *place_holder;
unsigned short len;
char message[4096];
char *mptr;
char *content_length;
memset(&s_addr, 0, sizeof(struct sockaddr_un)) ;
memset(&s_addr, 0, sizeof(struct sockaddr_un));
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
memset(message, 0, 4096);
memset(message, 0, 4096);
mptr = message+4;
mptr = message+4;
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len ;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1)) ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len ;
*environ++;
}
}
message[0] = 0;
len = (mptr-message)-4 ;
memcpy(message+1, &len, 2) ;
message[3] = 0 ;
res = send(uwsgi_socket, message, mptr-message, 0);
if ( (content_length = getenv("CONTENT_LENGTH")) != NULL) {
if (atoi(content_length) > 0) {
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0) ;
}
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1));
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len;
*environ++;
}
}
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res) ;
}
}
return 0;
message[0] = 0;
len = (mptr-message)-4;
memcpy(message+1, &len, 2);
message[3] = 0;
res = send(uwsgi_socket, message, mptr-message, 0);
if ( (content_length = getenv("CONTENT_LENGTH")) != NULL) {
if (atoi(content_length) > 0) {
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0);
}
}
}
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res);
}
}
return 0;
}
+64 -64
View File
@@ -2,8 +2,8 @@
*** uWSGI cgi client ***
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_dynamic_client.c
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_dynamic_client.c
*/
@@ -19,77 +19,77 @@ to compile:
#define UWSGI_SCRIPT "myapp_wsgi"
int main() {
extern char **environ;
char *env ;
struct sockaddr_un s_addr ;
int uwsgi_socket ;
int res, cnt;
char *place_holder;
unsigned short len ;
char message[4096];
char *mptr;
extern char **environ;
char *env;
struct sockaddr_un s_addr;
int uwsgi_socket;
int res, cnt;
char *place_holder;
memset(&s_addr, 0, sizeof(struct sockaddr_un)) ;
unsigned short len;
char message[4096];
char *mptr;
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
memset(&s_addr, 0, sizeof(struct sockaddr_un));
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
memset(message, 0, 4096);
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
mptr = message+4;
if (setenv("UWSGI_SCRIPT", UWSGI_SCRIPT, 1) != 0) {
perror("setenv()");
exit(1);
}
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len ;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1)) ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len ;
*environ++;
}
}
memset(message, 0, 4096);
message[0] = 0;
len = (mptr-message)-4 ;
memcpy(message+1, &len, 2) ;
message[3] = 0 ;
mptr = message+4;
if (setenv("UWSGI_SCRIPT", UWSGI_SCRIPT, 1) != 0) {
perror("setenv()");
exit(1);
}
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1));
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len;
*environ++;
}
}
res = send(uwsgi_socket, message, mptr-message, 0);
message[0] = 0;
len = (mptr-message)-4;
memcpy(message+1, &len, 2);
message[3] = 0;
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0) ;
}
res = send(uwsgi_socket, message, mptr-message, 0);
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0);
}
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res);
}
}
return 0;
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res) ;
}
}
return 0;
}
+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
}
-6
View File
@@ -1,6 +0,0 @@
Package: uwsgi
Version: 0.9.2
Maintainer: Unbit
Description: Fast, developer-friendly wsgi server
Architecture: i386
Depends: python2.5, libxml2
+2
View File
@@ -0,0 +1,2 @@
[uwsgi]
show-config = true
+133
View File
@@ -0,0 +1,133 @@
#!./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 hello2():
return "[RPC] 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))
print(uwsgi.call('helloworld'))
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)))
print(uwsgi.call('helloworld'))
uwsgi.signal(100)
time.sleep(1)
# spool a task after 5 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)
if uwsgi.i_am_the_spooler():
print("Hello from a thread in the spooler")
else:
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():
if uwsgi.i_am_the_spooler():
return
print("worker %d is waiting for signal 100..." % uwsgi.worker_id())
uwsgi.signal_wait(100)
print("worker %d received signal %d" % (uwsgi.worker_id(), 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, 5):
time.sleep(1)
print("[locked %d] waiting..." % uwsgi.worker_id())
print("done with locked function on worker %d" % uwsgi.worker_id())
print(uwsgi.call('helloworld'))
spool_filename = a_long_task.spool({'foo':'bar'}, hello='world')
print("spool filename = %s" % spool_filename)
an_infinite_task.spool(foo='bar', priority=3)
when = int(time.time())+5
print("scheduling a delayed task at %d" % when)
delayed_task.spool(foo2='bar2', at=when)
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()
+21
View File
@@ -56,9 +56,30 @@
</table>
</div>
<div class="module" style="width:860px">
<table>
<caption style="width:860px">spooler jobs</caption>
<thead>
<tr>
<th scope="row">job filename</th>
<th scope="row">environment</th>
</tr>
</thead>
<tbody>
{% for j in jobs %}
<tr>
<td align="left">{{j.file}}</td>
<td align="left">{{j.env}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if masterpid %}
<br/>
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
{% csrf_token %}
<input type="submit" value="gracefully reload uWSGI" name="_reload"/>
</form>
{% endif %}
+7
View File
@@ -14,12 +14,19 @@ def index(request):
w['load'] = (100 * (w['running_time']/1000))/total_load
w['last_spawn_str'] = time.ctime(w['last_spawn'])
jobs = []
if 'spooler' in uwsgi.opt:
spooler_jobs = uwsgi.spooler_jobs()
for j in spooler_jobs:
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
'started_on': time.ctime(uwsgi.started_on),
'buffer_size': uwsgi.buffer_size,
'total_requests': uwsgi.total_requests(),
'numproc': uwsgi.numproc,
'workers': workers,
'jobs': jobs,
}, RequestContext(request, {}))
index = staff_member_required(index)
+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)
+796
View File
@@ -0,0 +1,796 @@
#include "uwsgi.h"
#include <glob.h>
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;
uid_t uid;
gid_t gid;
};
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);
}
void emperor_stats() {
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
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);
c_ui = c_ui->ui_next;
}
}
struct uwsgi_instance *emperor_get_by_fd(int fd) {
struct uwsgi_instance *c_ui = ui;
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
if (c_ui->pipe[0] == fd) {
return c_ui;
}
}
return NULL;
}
struct uwsgi_instance *emperor_get(char *name) {
struct uwsgi_instance *c_ui = ui;
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
if (!strcmp(c_ui->name, name)) {
return c_ui;
}
}
return NULL;
}
void emperor_del(struct uwsgi_instance *c_ui) {
struct uwsgi_instance *parent_ui = c_ui->ui_prev;
struct uwsgi_instance *child_ui = c_ui->ui_next;
parent_ui->ui_next = child_ui;
if (child_ui) {
child_ui->ui_prev = parent_ui;
}
// this will destroy the whole uWSGI instance (and workers)
close(c_ui->pipe[0]);
if (c_ui->use_config) {
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);
}
void emperor_stop(struct uwsgi_instance *c_ui) {
// remove uWSGI instance
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("write()");
}
c_ui->status = 1;
uwsgi_log("stop the uwsgi instance %s\n", c_ui->name);
}
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
// reload the uWSGI instance
if (c_ui->use_config) {
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("write()");
}
}
else {
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
}
}
c_ui->respawns++;
c_ui->last_mod = mod;
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
struct uwsgi_instance *c_ui = ui;
struct uwsgi_instance *n_ui = NULL;
pid_t pid;
char **argv;
char *uef;
char **uenvs;
int counter;
char *colon = NULL;
int i;
usleep(uwsgi.emperor_throttle*1000);
if (uwsgi.emperor_tyrant) {
if (uid == 0 || gid == 0) {
uwsgi_log("[emperor-tyrant] invalid permissions for file %s\n", name);
return;
}
}
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
}
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
memset(n_ui, 0, sizeof(struct uwsgi_instance));
if (config) {
n_ui->use_config = 1;
n_ui->config = config;
n_ui->config_len = config_size;
}
c_ui->ui_next = n_ui;
#ifdef UWSGI_DEBUG
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->uid = uid;
n_ui->gid = gid;
n_ui->last_mod = born;
// start without loyalty
n_ui->last_loyal = born;
n_ui->loyal = 0;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
uwsgi_error("socketpair()");
goto clear;
}
event_queue_add_fd_read(emperor_queue, n_ui->pipe[0]);
if (n_ui->use_config) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
uwsgi_error("socketpair()");
goto clear;
}
}
// TODO pre-start hook
// a new uWSGI instance will start
pid = fork();
if (pid < 0) {
uwsgi_error("fork()")
}
else if (pid > 0) {
n_ui->pid = pid;
// close the right side of the pipe
close(n_ui->pipe[1]);
if (n_ui->use_config) {
close(n_ui->pipe_config[1]);
}
if (n_ui->use_config) {
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) <= 0) {
uwsgi_error("write()");
}
close(n_ui->pipe_config[0]);
}
return;
}
else {
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
if (setgid(gid)) {
uwsgi_error("setgid()");
exit(1);
}
if (setgroups(0, NULL)) {
uwsgi_error("setgroups()");
exit(1);
}
if (setuid(uid)) {
uwsgi_error("setuid()");
exit(1);
}
}
unsetenv("UWSGI_RELOADS");
unsetenv("NOTIFY_SOCKET");
uef = uwsgi_num2str(n_ui->pipe[1]);
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
}
free(uef);
if (n_ui->use_config) {
uef = uwsgi_num2str(n_ui->pipe_config[1]);
if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
}
free(uef);
}
uenvs = environ;
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
break;
}
free(oe);
uwsgi_log("putenv %s\n", ne);
if (putenv(ne)) {
uwsgi_error("putenv()");
}
// do not free ne as putenv will add it to the environ
uenvs = environ;
continue;
}
uenvs++;
}
// close the left side of the pipe
close(n_ui->pipe[0]);
if (n_ui->use_config) {
close(n_ui->pipe_config[0]);
}
counter = 4;
struct uwsgi_config_template *uct = uwsgi.vassals_templates;
while(uct) {
counter+=2;
uct = uct->next;
}
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"))
argv[1] = "--ini";
if (!strcmp(name + (strlen(name) - 4), ".yml"))
argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
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;
while(uct) {
argv[counter] = "--inherit";
argv[counter+1] = uct->filename;
counter+=2;
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()");
}
uwsgi_log("is the uwsgi binary in your system PATH ?\n");
// never here
exit(UWSGI_EXILE_CODE);
}
clear:
free(n_ui);
c_ui->ui_next = NULL;
}
void emperor_loop() {
// monitor a directory
struct uwsgi_instance ui_base;
struct uwsgi_instance *ui_current;
struct stat st;
pid_t diedpid;
int waitpid_status;
int has_children = 0;
int i_am_alone = 0;
int simple_mode = 0;
glob_t g;
int i;
struct dirent *de;
char *amqp_port;
int amqp_fd = -1;
char *amqp_routing_key;
void *events;
int nevents;
int interesting_fd;
char notification_message[64];
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));
emperor_queue = event_queue_init();
events = event_queue_alloc(64);
if (uwsgi.has_emperor) {
uwsgi_log("*** starting uWSGI sub-Emperor ***\n");
}
else {
uwsgi_log("*** starting uWSGI Emperor ***\n");
}
amqp_port = strchr(uwsgi.emperor_dir, ':');
if (amqp_port) {
if (uwsgi.emperor_amqp_vhost == NULL) uwsgi.emperor_amqp_vhost = "/";
if (uwsgi.emperor_amqp_username == NULL) uwsgi.emperor_amqp_username = "guest";
if (uwsgi.emperor_amqp_password == NULL) uwsgi.emperor_amqp_password = "guest";
reconnect:
while(amqp_fd == -1) {
uwsgi_log("connecting to AMQP server...\n");
amqp_fd = uwsgi_connect(uwsgi.emperor_dir, -1, 0);
if (amqp_fd < 0) {
sleep(1);
}
}
uwsgi_log("subscribing to queue...\n");
if (uwsgi_amqp_consume_queue(amqp_fd, uwsgi.emperor_amqp_vhost, uwsgi.emperor_amqp_username, uwsgi.emperor_amqp_password, "", "uwsgi.emperor", "fanout") < 0) {
close(amqp_fd);
amqp_fd = -1;
sleep(1);
goto reconnect;
}
event_queue_add_fd_read(emperor_queue, amqp_fd);
}
else {
if (!glob(uwsgi.emperor_dir, GLOB_MARK|GLOB_NOCHECK, NULL, &g)) {
if (g.gl_pathc == 1 && g.gl_pathv[0][strlen(g.gl_pathv[0]) - 1] == '/') {
simple_mode = 1;
if (chdir(uwsgi.emperor_dir)) {
uwsgi_error("chdir()");
exit(1);
}
}
}
else {
uwsgi_error("glob()");
exit(1);
}
emperor_absolute_dir = realpath(".", NULL);
}
ui = &ui_base;
int freq = 0 ;
for (;;) {
if (!i_am_alone) {
diedpid = waitpid(uwsgi.emperor_pid, &waitpid_status, WNOHANG);
if (diedpid < 0 || diedpid > 0) {
i_am_alone = 1;
}
}
nevents = event_queue_wait_multi(emperor_queue, freq, events, 64);
freq = 3;
for (i = 0; i<nevents;i++) {
interesting_fd = event_queue_interesting_fd(events, i);
if (amqp_fd > -1 && interesting_fd == amqp_fd ) {
uint64_t msgsize;
char *config = uwsgi_amqp_consume(amqp_fd, &msgsize, &amqp_routing_key);
if (!config) {
uwsgi_log("problem with RabbitMQ server, trying reconnection...\n");
event_queue_del_fd(emperor_queue, amqp_fd, event_queue_read());
close(amqp_fd);
amqp_fd = -1;
goto reconnect;
}
if (amqp_routing_key) {
uwsgi_log("AMQP routing_key = %s\n", amqp_routing_key);
char *config_file = uwsgi_concat2("emperor://", amqp_routing_key);
free(amqp_routing_key);
ui_current = emperor_get(config_file);
if (ui_current) {
// ignore event if i am not loyal
if (!ui_current->loyal) continue;
free(ui_current->config);
ui_current->config = config;
ui_current->config_len = msgsize;
if (!msgsize) {
// SAFE
emperor_del(ui_current);
}
else {
emperor_respawn(ui_current, time(NULL));
}
}
else {
if (msgsize > 0) {
emperor_add(config_file, time(NULL), config, msgsize, 0, 0);
}
}
free(config_file);
}
else {
if (msgsize) {
if (msgsize >= 0xff) { free(config); continue; }
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s\n", (int)msgsize, config);
#endif
char *config_file = uwsgi_concat2n(config, msgsize, "", 0);
free(config);
if (strncmp(config_file, "http://", 7)) {
if (stat(config_file, &st)) {
free(config_file);
continue;
}
if (!S_ISREG(st.st_mode)) {
free(config_file);
continue;
}
}
ui_current = emperor_get(config_file);
if (ui_current) {
// ignore event if i am not loyal
if (!ui_current->loyal) continue;
emperor_respawn(ui_current, time(NULL));
}
else {
emperor_add(config_file, time(NULL), NULL, 0, 0, 0);
}
free(config_file);
}
}
}
else {
ui_current = emperor_get_by_fd(interesting_fd);
if (ui_current) {
char byte;
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
emperor_del(ui_current);
}
else {
if (byte == 17) {
ui_current->loyal = 1;
uwsgi_log("*** vassal %s is now loyal ***\n", ui_current->name);
// 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, ui_current->uid, ui_current->gid);
free(zerg_name);
}
}
}
else {
uwsgi_log("unrecognized event on fd %d\n", interesting_fd);
event_queue_del_fd(emperor_queue, interesting_fd, event_queue_read());
close(interesting_fd);
}
}
}
if (amqp_fd == -1) {
if (simple_mode) {
DIR *dir = opendir(".");
while ((de = readdir(dir)) != NULL) {
if (!strcmp(de->d_name + (strlen(de->d_name) - 4), ".xml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".ini") ||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".yml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".yaml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 3), ".js")
) {
if (strlen(de->d_name) >= 0xff)
continue;
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
ui_current = emperor_get(de->d_name);
if (ui_current) {
// check if uid or gid are changed, in such case, sotp the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
emperor_stop(ui_current);
continue;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
}
closedir(dir);
}
else {
if (glob(uwsgi.emperor_dir, GLOB_MARK|GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("glob()");
continue;
}
for (i = 0; i < (int) g.gl_pathc; i++) {
if (!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".xml") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".ini") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".yml") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 3), ".js") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".yaml")
) {
if (strlen(g.gl_pathv[i]) >= 0xff)
continue;
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
ui_current = emperor_get(g.gl_pathv[i]);
if (ui_current) {
// check if uid or gid are changed, in such case, sotp the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
emperor_stop(ui_current);
continue;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
}
}
}
// check for removed instances
ui_current = ui;
has_children = 0;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
has_children++;
}
if (uwsgi.notify) {
if (snprintf(notification_message, 64, "The Emperor is governing %d vassals", has_children) >= 34) {
uwsgi_notify(notification_message);
}
}
if (has_children) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
else {
// vacuum
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
diedpid = 0;
}
if (diedpid < 0) {
uwsgi_error("waitpid()");
}
ui_current = ui;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
// check loyalty if not in simple/glob mode
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) && !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, ui_current->uid, ui_current->gid);
emperor_del(ui_current);
}
break;
}
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;
}
}
}
}
}
-702
View File
@@ -1,702 +0,0 @@
#ifdef UWSGI_ERLANG
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static void erlang_log(void);
PyObject *py_erlang_connect(PyObject * self, PyObject * args) {
char *erlang_node;
int fd;
if (!PyArg_ParseTuple(args, "s:erlang_connect", &erlang_node)) {
return NULL;
}
UWSGI_SET_BLOCKING;
fd = erl_connect(erlang_node);
UWSGI_UNSET_BLOCKING;
return PyInt_FromLong(fd);
}
PyObject *py_erlang_recv_message(PyObject * self, PyObject * args) {
int erfd;
struct pollfd erpoll;
ErlMessage emsg;
PyObject *pyer = NULL;
unsigned char erlang_buffer[8192];
int eret;
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
if (!PyArg_ParseTuple(args, "i|i:erlang_recv_message", &erfd, &timeout)) {
return NULL;
}
if (erfd < 0) {
goto clear;
}
erpoll.fd = erfd;
erpoll.events = POLLIN;
cycle:
memset(&emsg, 0, sizeof(ErlMessage));
UWSGI_SET_BLOCKING;
if (timeout > 0) {
eret = poll(&erpoll, 1, timeout * 1000);
if (eret < 0) {
uwsgi_error("poll()");
goto clear;
}
else if (eret == 0) {
goto clear;
}
}
if (erl_receive_msg(erfd, erlang_buffer, 8192, &emsg) == ERL_MSG) {
if (emsg.type == ERL_TICK) {
goto cycle;
}
if (emsg.msg) {
pyer = eterm_to_py(emsg.msg);
}
if (emsg.msg) {
erl_free_compound(emsg.msg);
}
if (emsg.to) {
erl_free_compound(emsg.to);
}
if (emsg.from) {
erl_free_compound(emsg.from);
}
if (!pyer) {
goto clear;
}
UWSGI_UNSET_BLOCKING;
return pyer;
}
clear:
UWSGI_UNSET_BLOCKING;
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_send_message(PyObject * self, PyObject * args) {
ETERM *pymessage;
ETERM *pid;
int erfd;
PyObject *ermessage, *erdest, *zero;
int er_number, er_serial, er_creation;
char *er_node;
if (!PyArg_ParseTuple(args, "iOO|i:erlang_send_message", &erfd, &erdest, &ermessage)) {
return NULL;
}
if (erfd < 0) {
goto clear;
}
if (!PyString_Check(erdest) && !PyDict_Check(erdest)) {
goto clear;
}
pymessage = py_to_eterm(ermessage);
if (!pymessage) {
goto clear;
}
if (PyString_Check(erdest)) {
if (!erl_reg_send(erfd, PyString_AsString(erdest), pymessage)) {
erl_err_msg("erl_reg_send()");
goto clear2;
}
}
else if (PyDict_Check(erdest)) {
zero = PyDict_GetItemString(erdest, "node");
if (!zero) {
goto clear2;
}
if (!PyString_Check(zero)) {
goto clear2;
}
er_node = PyString_AsString(zero);
zero = PyDict_GetItemString(erdest, "number");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_number = PyInt_AsLong(zero);
zero = PyDict_GetItemString(erdest, "serial");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_serial = PyInt_AsLong(zero);
zero = PyDict_GetItemString(erdest, "creation");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_creation = PyInt_AsLong(zero);
pid = erl_mk_pid((const char *) er_node, er_number, er_serial, er_creation);
if (!pid) {
goto clear2;
}
if (!erl_send(erfd, pid, pymessage)) {
erl_err_msg("erl_send()");
erl_free_term(pid);
goto clear2;
}
erl_free_term(pid);
}
else {
goto clear;
}
erl_free_compound(pymessage);
Py_INCREF(Py_True);
return Py_True;
clear2:
erl_free_compound(pymessage);
clear:
PyErr_Print();
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_rpc(PyObject * self, PyObject * args) {
int fd, timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
char *emod, *efun;
PyObject *eargs, *pyer = NULL;
ETERM *pyargs, *rex;
ErlMessage emsg;
int eret;
if (!PyArg_ParseTuple(args, "issO|i:erlang_rpc", &fd, &emod, &efun, &eargs, &timeout)) {
return NULL;
}
if (fd < 0) {
goto clear;
}
pyargs = py_to_eterm(eargs);
if (!pyargs) {
goto clear;
}
if (erl_rpc_to(fd, emod, efun, pyargs)) {
erl_err_msg("erl_rpc_to()");
goto clear2;
}
cycle:
memset(&emsg, 0, sizeof(ErlMessage));
UWSGI_SET_BLOCKING;
eret = erl_rpc_from(fd, timeout * 1000, &emsg);
if (eret == ERL_TICK) {
goto cycle;
}
else if (eret == ERL_MSG) {
if (emsg.msg) {
if (ERL_IS_TUPLE(emsg.msg)) {
rex = erl_element(1, emsg.msg);
if (!rex) {
goto clear2;
}
if (!strncmp("rex", ERL_ATOM_PTR(rex), ERL_ATOM_SIZE(rex))) {
erl_free_term(rex);
rex = erl_element(2, emsg.msg);
if (!rex) {
goto clear2;
}
pyer = eterm_to_py(rex);
erl_free_term(rex);
}
else {
erl_free_term(rex);
}
}
}
if (emsg.msg) {
erl_free_compound(emsg.msg);
}
if (emsg.to) {
erl_free_compound(emsg.to);
}
if (emsg.from) {
erl_free_compound(emsg.from);
}
if (!pyer) {
goto clear2;
}
erl_free_compound(pyargs);
UWSGI_UNSET_BLOCKING;
return pyer;
}
else {
erl_err_msg("erl_rpc_from()");
}
clear2:
UWSGI_UNSET_BLOCKING;
erl_free_compound(pyargs);
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_close(PyObject * self, PyObject * args) {
int fd;
if (!PyArg_ParseTuple(args, "i:erlang_close", &fd)) {
return NULL;
}
if (fd >= 0) {
erl_close_connection(fd);
}
Py_INCREF(Py_True);
return Py_True;
}
static PyMethodDef uwsgi_erlang_methods[] = {
{"erlang_connect", py_erlang_connect, METH_VARARGS, ""},
{"erlang_send_message", py_erlang_send_message, METH_VARARGS, ""},
{"erlang_recv_message", py_erlang_recv_message, METH_VARARGS, ""},
{"erlang_rpc", py_erlang_rpc, METH_VARARGS, ""},
{"erlang_close", py_erlang_close, METH_VARARGS, ""},
{NULL, NULL},
};
int init_erlang(char *nodename, char *cookie) {
struct sockaddr_in e_addr;
char *ip;
char *node;
int efd;
int rlen;
char *cookiefile;
char *cookiehome;
char cookievalue[128];
int cookiefd;
PyMethodDef *uwsgi_function;
ip = strchr(nodename, '@');
if (ip == NULL) {
fprintf(stderr, "*** invalid erlang node name ***\n");
return -1;
}
if (cookie == NULL) {
// get the cookie from the home
cookiehome = getenv("HOME");
if (!cookiehome) {
fprintf(stderr, "unable to get erlang cookie from your home.\n");
return -1;
}
cookiefile = malloc(strlen(cookiehome) + 1 + strlen(".erlang.cookie") + 1);
if (!cookiefile) {
uwsgi_error("malloc()");
}
cookiefile[0] = 0;
strcat(cookiefile, cookiehome);
strcat(cookiefile, "/.erlang.cookie");
cookiefd = open(cookiefile, O_RDONLY);
if (cookiefd < 0) {
uwsgi_error("open()");
free(cookiefile);
return -1;
}
memset(cookievalue, 0, 128);
if (read(cookiefd, cookievalue, 127) < 1) {
fprintf(stderr, "invalid cookie found in %s\n", cookiefile);
close(cookiefd);
free(cookiefile);
return -1;
}
cookie = cookievalue;
close(cookiefd);
free(cookiefile);
}
node = malloc((ip - nodename) + 1);
if (node == NULL) {
uwsgi_error("malloc()");
return -1;
}
memset(node, 0, (ip - nodename) + 1);
memcpy(node, nodename, ip - nodename);
erl_init(NULL, 0);
if (erl_connect_xinit(ip + 1, node, nodename, NULL, cookie, 0) == -1) {
fprintf(stderr, "*** unable to initialize erlang c-node ***\n");
return -1;
}
efd = socket(AF_INET, SOCK_STREAM, 0);
if (efd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&e_addr, 0, sizeof(struct sockaddr_in));
e_addr.sin_family = AF_INET;
e_addr.sin_addr.s_addr = inet_addr(ip + 1);
rlen = 1;
if (setsockopt(efd, SOL_SOCKET, SO_REUSEADDR, &rlen, sizeof(rlen))) {
uwsgi_error("setsockopt()");
close(efd);
return -1;
}
if (bind(efd, (struct sockaddr *) &e_addr, sizeof(struct sockaddr_in)) < 0) {
uwsgi_error("bind()");
close(efd);
return -1;
}
rlen = sizeof(struct sockaddr_in);
if (getsockname(efd, (struct sockaddr *) &e_addr, (socklen_t *) & rlen)) {
uwsgi_error("getsockname()");
close(efd);
return -1;
}
if (listen(efd, uwsgi.listen_queue)) {
uwsgi_error("listen()");
close(efd);
return -1;
}
if (erl_publish(ntohs(e_addr.sin_port)) < 0) {
fprintf(stderr, "*** unable to subscribe with EPMD ***\n");
close(efd);
return -1;
}
fprintf(stderr, "Erlang C-Node initialized on port %d you can access it with name %s\n", ntohs(e_addr.sin_port), nodename);
for (uwsgi_function = uwsgi_erlang_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(uwsgi.embedded_dict, uwsgi_function->ml_name, func);
Py_DECREF(func);
}
return efd;
}
ETERM *py_to_eterm(PyObject * pobj) {
int i;
int count;
PyObject *pobj2;
ETERM *eobj = NULL;
ETERM *eobj2 = NULL;
ETERM **eobj3;
if (pobj == NULL) {
return erl_mk_empty_list();
}
if (PyString_Check(pobj)) {
eobj = erl_mk_atom(PyString_AsString(pobj));
}
else if (PyInt_Check(pobj)) {
eobj = erl_mk_int(PyInt_AsLong(pobj));
}
else if (PyList_Check(pobj)) {
eobj = erl_mk_empty_list();
for (i = PyList_Size(pobj) - 1; i >= 0; i--) {
pobj2 = PyList_GetItem(pobj, i);
eobj2 = py_to_eterm(pobj2);
eobj = erl_cons(eobj2, eobj);
}
}
else if (PyDict_Check(pobj)) {
// a pid
char *er_node;
int er_number, er_serial, er_creation;
pobj2 = PyDict_GetItemString(pobj, "node");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyString_Check(pobj2)) {
goto clear;
}
er_node = PyString_AsString(pobj2);
pobj2 = PyDict_GetItemString(pobj, "number");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_number = PyInt_AsLong(pobj2);
pobj2 = PyDict_GetItemString(pobj, "serial");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_serial = PyInt_AsLong(pobj2);
pobj2 = PyDict_GetItemString(pobj, "creation");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_creation = PyInt_AsLong(pobj2);
eobj = erl_mk_pid(er_node, er_number, er_serial, er_creation);
}
else if (PyTuple_Check(pobj)) {
count = PyTuple_Size(pobj);
eobj3 = malloc(sizeof(ETERM *) * count);
for (i = 0; i < count; i++) {
pobj2 = PyTuple_GetItem(pobj, i);
if (!pobj2) {
break;
}
eobj3[i] = py_to_eterm(pobj2);
}
eobj = erl_mk_tuple(eobj3, count);
free(eobj3);
}
else {
fprintf(stderr, "UNMANAGED PYTHON TYPE: %s\n", pobj->ob_type->tp_name);
}
clear:
if (eobj == NULL) {
return erl_mk_empty_list();
}
return eobj;
}
PyObject *eterm_to_py(ETERM * obj) {
int i;
int count;
ETERM *obj2;
PyObject *eobj = NULL;
if (obj == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
switch (ERL_TYPE(obj)) {
case ERL_CONS:
case ERL_NIL:
count = erl_length(obj);
eobj = PyList_New(0);
for (i = 0; i < count; i++) {
obj2 = erl_hd(obj);
PyList_Append(eobj, eterm_to_py(obj2));
obj = erl_tl(obj);
}
break;
case ERL_TUPLE:
eobj = PyTuple_New(erl_size(obj));
for (i = 1; i <= erl_size(obj); i++) {
obj2 = erl_element(i, obj);
PyTuple_SetItem(eobj, i - 1, eterm_to_py(obj2));
}
break;
case ERL_ATOM:
eobj = PyString_FromStringAndSize(ERL_ATOM_PTR(obj), ERL_ATOM_SIZE(obj));
break;
case ERL_INTEGER:
eobj = PyInt_FromLong(ERL_INT_VALUE(obj));
break;
case ERL_BINARY:
fprintf(stderr, "FOUND A BINARY %.*s\n", ERL_BIN_SIZE(obj), ERL_BIN_PTR(obj));
break;
case ERL_PID:
eobj = PyDict_New();
if (PyDict_SetItemString(eobj, "node", PyString_FromString(ERL_PID_NODE(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "number", PyInt_FromLong(ERL_PID_NUMBER(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "serial", PyInt_FromLong(ERL_PID_SERIAL(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "creation", PyInt_FromLong(ERL_PID_CREATION(obj)))) {
PyErr_Print();
break;
}
default:
fprintf(stderr, "UNMANAGED ETERM TYPE: %d\n", ERL_TYPE(obj));
break;
}
if (eobj == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return eobj;
}
void erlang_loop(struct wsgi_request *wsgi_req) {
ErlConnect econn;
ErlMessage em;
ETERM *eresponse;
PyObject *callable = PyDict_GetItemString(uwsgi.embedded_dict, "erlang_func");
if (!callable) {
PyErr_Print();
fprintf(stderr, "- you have not defined a uwsgi.erlang_func callable, Erlang message manager will be disabled until you define it -\n");
}
PyObject *pargs = PyTuple_New(1);
if (!pargs) {
PyErr_Print();
fprintf(stderr, "- error preparing arg tuple for uwsgi.erlang_func callable, Erlang message manager will be disabled -\n");
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
UWSGI_CLEAR_STATUS;
wsgi_req->poll.fd = erl_accept(uwsgi.erlangfd, &econn);
if (wsgi_req->poll.fd >= 0) {
UWSGI_SET_ERLANGING;
for (;;) {
if (erl_receive_msg(wsgi_req->poll.fd, (unsigned char *) wsgi_req->buffer, uwsgi.buffer_size, &em) == ERL_MSG) {
if (em.type == ERL_TICK)
continue;
if (!callable) {
callable = PyDict_GetItemString(uwsgi.embedded_dict, "erlang_func");
}
if (!callable) {
fprintf(stderr, "- you still have not defined a uwsgi.erlang_func callable, Erlang message rejected -\n");
}
PyObject *zero = eterm_to_py(em.msg);
if (em.msg) {
erl_free_compound(em.msg);
}
if (em.to) {
erl_free_compound(em.to);
}
if (!zero) {
PyErr_Print();
continue;
}
if (PyTuple_SetItem(pargs, 0, zero)) {
PyErr_Print();
continue;
}
PyObject *erlang_result = PyEval_CallObject(callable, pargs);
//Py_DECREF(zero);
if (erlang_result) {
eresponse = py_to_eterm(erlang_result);
if (eresponse) {
erl_send(wsgi_req->poll.fd, em.from, eresponse);
erl_free_compound(eresponse);
}
Py_DECREF(erlang_result);
}
if (em.from) {
erl_free_compound(em.from);
}
uwsgi.workers[0].requests++;
uwsgi.workers[uwsgi.mywid].requests++;
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
erlang_log();
}
else {
break;
}
}
erl_close_connection(wsgi_req->poll.fd);
UWSGI_UNSET_ERLANGING;
}
}
}
static void erlang_log() {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
get_memusage();
}
else {
uwsgi.workers[uwsgi.mywid].rss_size = 0;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
}
fprintf(stderr, "[Erlang worker %d pid %d] request %llu done {rss: %llu vsz: %llu}\n", uwsgi.mywid, uwsgi.mypid, uwsgi.workers[uwsgi.mywid].requests, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].vsz_size);
}
#else
#warning "*** Erlang support is disabled ***"
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifdef UWSGI_EVDIS
#include "uwsgi.h"
void evdis_loop(struct uwsgi_server *uwsgi) {
// populate event list
int kfd = kqueue();
if (kfd < 0) {
uwsgi_error("kqueue()");
exit(1);
}
}
#else
#warning "*** Event Dispatcher support is disabled ***"
#endif
+864
View File
@@ -0,0 +1,864 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_USE_PORT
#include <port.h>
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int event_queue_init() {
int port = port_create();
if (port < 0) {
uwsgi_error("port_create()");
return -1;
}
return port;
}
int event_queue_del_fd(int eq, int fd, int event) {
if (port_dissociate(eq, PORT_SOURCE_FD, fd)) {
uwsgi_error("port_disassociate");
return -1;
}
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
if (pe[id].portev_events == POLLHUP || pe[id].portev_events == POLLERR) {
return 1;
}
return 0;
}
int event_queue_add_fd_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(port_event_t) * nevents);
}
int event_queue_interesting_fd(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
return (int) pe[id].portev_user;
}
return (int) pe[id].portev_object;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
uint_t nget = 1;
timespec_t ts;
port_event_t *pe;
if (timeout >= 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_getn(eq, events, nevents, &nget, &ts);
}
else {
ret = port_getn(eq, events, nevents, &nget, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
uwsgi_error("port_getn()");
return -1;
}
return 0;
}
pe = (port_event_t *) events;
return nget;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
port_event_t pe;
timespec_t ts;
if (timeout > 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_get(eq, &pe, &ts);
}
else {
ret = port_get(eq, &pe, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
uwsgi_error("port_get()");
return -1;
}
return 0;
}
if (pe.portev_source == PORT_SOURCE_FD) {
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
uwsgi_error("port_associate");
}
}
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
*interesting_fd = (int) pe.portev_user;
}
else {
*interesting_fd = (int) pe.portev_object;
}
return 1;
}
#endif
#ifdef UWSGI_EVENT_USE_EPOLL
#include <sys/epoll.h>
#define UWSGI_EVENT_IN EPOLLIN
#define UWSGI_EVENT_OUT EPOLLOUT
int event_queue_init() {
int epfd;
epfd = epoll_create(256);
if (epfd < 0) {
uwsgi_error("epoll_create()");
return -1;
}
return epfd;
}
int event_queue_add_fd_read(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_MOD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.data.fd = fd;
ee.events = event;
if (epoll_ctl(eq, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLOUT;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(struct epoll_event) * nevents);
}
int event_queue_interesting_fd(void *events, int id) {
struct epoll_event *ee = (struct epoll_event *) events;
return ee[id].data.fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct epoll_event *ee = (struct epoll_event *) events;
if (ee[id].events == EPOLLHUP || ee[id].events == EPOLLERR || (ee[id].events == (EPOLLERR|EPOLLHUP))) {
return 1;
}
return 0;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
if (timeout > 0) {
timeout = timeout*1000;
}
ret = epoll_wait(eq, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
if (errno != EINTR)
uwsgi_error("epoll_wait()");
}
return ret;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
struct epoll_event ee;
if (timeout > 0) {
timeout = timeout*1000;
}
ret = epoll_wait(eq, &ee, 1, timeout);
if (ret < 0) {
if (errno != EINTR)
uwsgi_error("epoll_wait()");
}
if (ret > 0) {
*interesting_fd = ee.data.fd;
}
return ret;
}
#endif
#ifdef UWSGI_EVENT_USE_KQUEUE
#define UWSGI_EVENT_IN EVFILT_READ
#define UWSGI_EVENT_OUT EVFILT_WRITE
int event_queue_init() {
int kfd = kqueue();
if (kfd < 0) {
uwsgi_error("kqueue()");
return -1;
}
return kfd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_WRITE, EV_DISABLE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct kevent kev;
EV_SET(&kev, fd, event, EV_DELETE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_add_fd_read(int eq, int fd) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(struct kevent) * nevents);
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
struct timespec ts;
if (timeout < 0) {
ret = kevent(eq, NULL, 0, events, nevents, NULL);
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout;
ret = kevent(eq, NULL, 0, (struct kevent *)events, nevents, &ts);
}
if (ret < 0) {
uwsgi_error("kevent()");
}
return ret;
}
int event_queue_interesting_fd(void *events, int id) {
struct kevent *ev = (struct kevent *) events;
return ev[id].ident;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct kevent *ev = (struct kevent *) events;
if ( ( (ev[id].flags == EV_ERROR) || (ev[id].flags == EV_EOF) || (ev[id].flags == (EV_EOF|EV_ERROR))) ) {
return 1;
}
return 0;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
struct timespec ts;
struct kevent ev;
if (timeout <= 0) {
ret = kevent(eq, NULL, 0, &ev, 1, NULL);
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout;
ret = kevent(eq, NULL, 0, &ev, 1, &ts);
}
if (ret < 0) {
uwsgi_error("kevent()");
}
if (ret > 0) {
*interesting_fd = ev.ident;
}
return ret;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_NONE
int event_queue_add_file_monitor(int eq, char *filename, int *id) { return -1;}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {return NULL;}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct file_obj fo;
struct stat st;
static int fmon_id = 0xffffee00;
if (stat(filename, &st)) {
uwsgi_error("stat()");
return -1;
}
fo.fo_name = filename;
fo.fo_atime = st.st_atim;
fo.fo_mtime = st.st_mtim;
fo.fo_ctime = st.st_ctim;
fmon_id++;
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) fmon_id)) {
uwsgi_error("port_associate()");
return -1;
}
*id = fmon_id;
uwsgi_log("added new file to monitor %s [%d]\n", filename, *id);
return *id;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
int i;
struct file_obj fo;
struct stat st;
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id) {
if (stat(ushared->files_monitored[i].filename, &st)) {
uwsgi_error("stat()");
return NULL;
}
fo.fo_name = ushared->files_monitored[i].filename;
fo.fo_atime = st.st_atim;
fo.fo_mtime = st.st_mtim;
fo.fo_ctime = st.st_ctim;
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)id)) {
uwsgi_error("port_associate()");
return NULL;
}
return &ushared->files_monitored[i];
}
}
}
return NULL;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct kevent kev;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(filename);
return -1;
}
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE|NOTE_DELETE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_RENAME|NOTE_REVOKE, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
*id = fd;
uwsgi_log("added new file to monitor %s\n", filename);
return fd;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
int i;
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id) {
return &ushared->files_monitored[i];
}
}
}
return NULL;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#include <sys/inotify.h>
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
int ifd = -1;
int i;
int add_to_queue = 0;
for (i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
ifd = ushared->files_monitored[0].fd;
break;
}
}
if (ifd == -1) {
ifd = inotify_init();
if (ifd < 0) {
uwsgi_error("inotify_init()");
return -1;
}
add_to_queue = 1;
}
*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);
}
else {
return ifd;
}
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
ssize_t rlen = 0;
struct inotify_event ie, *bie, *iie;
int i,j;
int items = 0;
unsigned int isize = sizeof(struct inotify_event);
struct uwsgi_fmon *uf = NULL;
if (ioctl(id, FIONREAD, &isize) < 0) {
uwsgi_error("ioctl()");
return NULL;
}
if (isize > sizeof(struct inotify_event)) {
bie = uwsgi_malloc(isize);
rlen = read(id, bie, isize);
}
else {
rlen = read(id, &ie, sizeof(struct inotify_event));
bie = &ie;
}
if (rlen < 0) {
uwsgi_error("read()");
}
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++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id && ushared->files_monitored[i].id == iie->wd) {
uf = &ushared->files_monitored[i];
}
}
}
}
if (items > 1) {
free(bie);
}
return uf;
}
return NULL;
}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
#ifndef UWSGI_EVENT_TIMER_USE_TIMERFD_NOINC
#include <sys/timerfd.h>
#endif
#ifndef TFD_CLOEXEC
// timerfd support
enum
{
TFD_CLOEXEC = 02000000,
#define TFD_CLOEXEC TFD_CLOEXEC
TFD_NONBLOCK = 04000
#define TFD_NONBLOCK TFD_NONBLOCK
};
/* Bits to be set in the FLAGS parameter of `timerfd_settime'. */
enum
{
TFD_TIMER_ABSTIME = 1 << 0
#define TFD_TIMER_ABSTIME TFD_TIMER_ABSTIME
};
static int timerfd_create (clockid_t __clock_id, int __flags) {
#ifdef __amd64__
return syscall(283, __clock_id, __flags);
#elif defined(__i386__)
return syscall(322, __clock_id, __flags);
#endif
}
static int timerfd_settime (int __ufd, int __flags,
__const struct itimerspec *__utmr,
struct itimerspec *__otmr) {
#ifdef __amd64__
return syscall(286, __ufd, __flags, __utmr, __otmr);
#elif defined(__i386__)
return syscall(325, __ufd, __flags, __utmr, __otmr);
#endif
}
#endif
int event_queue_add_timer(int eq, int *id, int sec) {
struct itimerspec it;
int tfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
if (tfd < 0) {
uwsgi_error("timerfd_create()");
return -1;
}
it.it_value.tv_sec = sec;
it.it_value.tv_nsec = 0;
it.it_interval.tv_sec = sec;
it.it_interval.tv_nsec = 0;
if (timerfd_settime(tfd, 0, &it, NULL)) {
uwsgi_error("timerfd_settime()");
close(tfd);
return -1;
}
*id = tfd;
return event_queue_add_fd_read(eq, tfd);
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
ssize_t rlen;
uint64_t counter;
struct uwsgi_timer *ut = NULL;
for(i=0;i<ushared->timers_cnt;i++) {
if (ushared->timers[i].registered) {
if (ushared->timers[i].id == id) {
ut = &ushared->timers[i];
}
}
}
rlen = read(id, &counter, sizeof(uint64_t));
if (rlen < 0) {
uwsgi_error("read()");
}
return ut;
}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_NONE
int event_queue_add_timer(int eq, int *id, int sec) { return -1; }
struct uwsgi_timer *event_queue_ack_timer(int id) { return NULL;}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_PORT
int event_queue_add_timer(int eq, int *id, int sec) {
static int timer_id = 0xffffff00;
port_notify_t pnotif;
struct sigevent sigev;
itimerspec_t it;
timer_t tid;
timer_id++;
pnotif.portnfy_port = eq;
pnotif.portnfy_user = (void *) timer_id;
sigev.sigev_notify = SIGEV_PORT;
sigev.sigev_value.sival_ptr = &pnotif;
if (timer_create(CLOCK_REALTIME, &sigev, &tid) < 0) {
uwsgi_error("timer_create()");
return -1;
}
it.it_value.tv_sec = sec;
it.it_value.tv_nsec = 0;
it.it_interval.tv_sec = sec;
it.it_interval.tv_nsec = 0;
if (timer_settime(tid, 0, &it, NULL) < 0) {
uwsgi_error("timer_settime()");
return -1;
}
*id = timer_id;
return *id;
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
struct uwsgi_timer *ut = NULL;
for(i=0;i<uwsgi.shared->timers_cnt;i++) {
if (uwsgi.shared->timers[i].registered) {
if (uwsgi.shared->timers[i].id == id) {
ut = &uwsgi.shared->timers[i];
}
}
}
return ut;
}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_KQUEUE
int event_queue_add_timer(int eq, int *id, int sec) {
static int timer_id = 0xffffff00;
struct kevent kev;
*id = timer_id ;
timer_id++;
EV_SET(&kev, *id, EVFILT_TIMER, EV_ADD, 0, sec*1000, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return *id;
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
struct uwsgi_timer *ut = NULL;
for(i=0;i<uwsgi.shared->timers_cnt;i++) {
if (uwsgi.shared->timers[i].registered) {
if (uwsgi.shared->timers[i].id == id) {
ut = &uwsgi.shared->timers[i];
}
}
}
return ut;
}
#endif
inline int event_queue_read() {
return UWSGI_EVENT_IN;
}
inline int event_queue_write() {
return UWSGI_EVENT_OUT;
}
+47
View File
@@ -0,0 +1,47 @@
require 'fiber'
class SuspendingBody
def each
for i in 1..3
yield "number: #{i}\n"
UWSGI.async_sleep(1)
puts "sleep..."
Fiber.yield
end
fd = UWSGI.async_connect("81.174.68.52:80")
UWSGI.wait_fd_write(fd, 3)
Fiber.yield
io = IO.new(fd)
puts "connected"
io.syswrite("GET /uwsgi/export/1081%3A362d695b2f25/plugins/fiber/fiber.c HTTP/1.0\r\n")
io.syswrite("Host: projects.unbit.it\r\n")
io.syswrite("\r\n")
UWSGI.wait_fd_read(fd, 3)
Fiber.yield
puts "data available"
begin
while body = io.sysread(fd)
yield body
Fiber.yield
end
rescue
end
io.close
end
end
class RackFoo
def call(env)
[200, { 'Content-Type' => 'text/plain'}, SuspendingBody.new]
end
end
run RackFoo.new
+8
View File
@@ -0,0 +1,8 @@
uwsgi:
plugins: rack
socket: 127.0.0.1:3031
rack: fibers.ru
post-buffering: 4096
async: 10
loop: fiber
+34
View File
@@ -0,0 +1,34 @@
#ifdef __linux__
#include <sys/inotify.h>
int uwsgi_file_monitor_new() {
int inotify_fd;
inotify_fd = inotify_init();
if (inotify_fd < 0) {
uwsgi_error("inotify_init()");
return -1;
}
return inotify_fd;
}
int uwsgi_file_monitor_add(int fd, char *what) {
int inotify_watch_fd;
inotify_watch_fd = inotify_add_watch(fd, what, IN_ALL_EVENTS);
if (inotify_watch_fd < 0) {
uwsgi_error("inotify_add_watch()");
return -1;
}
return inotify_watch_fd;
}
#endif
+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()
+133
View File
@@ -0,0 +1,133 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_gateway *register_fat_gateway(char *name, void (*loop)(void)) {
struct uwsgi_gateway *ug;
int num=1,i;
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<uwsgi.gateways_cnt;i++) {
if (!strcmp(name, uwsgi.gateways[i].name)) {
num++;
}
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = 0;
ug->name = name;
ug->loop = loop;
ug->num = num;
uwsgi.gateways_cnt++;
return ug;
}
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
pid_t gw_pid;
pid_t orig_pid = getpid();
struct uwsgi_gateway *ug;
int num=1,i;
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<uwsgi.gateways_cnt;i++) {
if (!strcmp(name, uwsgi.gateways[i].name)) {
num++;
}
}
gw_pid = fork();
if (gw_pid < 0) {
uwsgi_error("fork()");
return NULL;
}
if (!uwsgi.master_process) {
if (gw_pid > 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
if (!uwsgi.sockets) {
// wait for child end
//waitpid(-1, &i, 0);
}
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = orig_pid;
}
else {
if (gw_pid == 0) {
if (uwsgi.master_as_root) uwsgi_as_root();
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = gw_pid;
}
ug->name = name;
ug->loop = loop;
ug->num = num;
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
uwsgi.gateways_cnt++;
return ug;
}
void gateway_respawn(int id) {
pid_t gw_pid;
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
gw_pid = fork();
if (gw_pid < 0) {
uwsgi_error("fork()");
return;
}
if (gw_pid == 0) {
if (uwsgi.master_as_root) uwsgi_as_root();
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
ug->loop();
// never here !!! (i hope)
exit(1);
}
ug->pid = 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);
}
}
+9
View File
@@ -0,0 +1,9 @@
// http:3:GET / HTTP/1.1:192.168.173.10:80,192.168.173.11:80,192.168.173.12:80,192.168.173.13:80
/*
write(arg1);
wait_for_fd()
get_data() == 200
*/
View File
View File
View File
View File
+1
View File
@@ -0,0 +1 @@
// uwsgi:3::192.168.173.1:3031,192.168.173.2:3031,192.168.173.3:3031,192.168.173.4:3031
+27
View File
@@ -0,0 +1,27 @@
[uwsgi]
master = true
processes = 4
threads = 8
; initialize 4 sockets with 4 different protocols
socket = :3031
socket = :3032
socket = :3033
socket = :3034
socket-protocol = 0,uwsgi
socket-protocol = 1,http
socket-protocol = 2,fastcgi
socket-protocol = 3,uwsgidump
; add a cache with 1000 items of 96k
cache = 1000
cache-blocksize = 98304
log-micros = true
module = heavytest
mount = /cc=uwsgicc/__init__.py
+14
View File
@@ -0,0 +1,14 @@
import uwsgi
import werkzeug.testapp
uwsgi.cache_set("/cache/get", "HTTP 1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>I am the uWSGI cache</h1>")
def app001(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return "PATH_INFO=%s" % env['PATH_INFO']
def app002(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return "requests: %d" % uwsgi.total_requests()
uwsgi.applications = { '':werkzeug.testapp.test_app, '/app001':app001, '/app002':app002 }
+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>"
+7 -14
View File
@@ -6,20 +6,18 @@ import rrdtool
s_freq = 10
# this is a cron emulator done with the Spooler :)
def rrdtool_updater(env):
uwsgi.set_spooler_frequency(s_freq)
rrdtool.update('../test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.send_to_spooler({})
# this task will be executed every s_freq seconds
def rrdtool_updater(sig, sec):
rrdtool.update('test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.spooler = rrdtool_updater
uwsgi.register_timer(0, s_freq, uwsgi.KIND_WORKER, rrdtool_updater)
def hello_world(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain')])
yield 'Hello world !'
return 'Hello world !'
def graph(env, start_response):
@@ -27,12 +25,7 @@ def graph(env, start_response):
now = int(time.time())
graph_range = (3600*24)
rrdtool.graph('uwsgi_graph.png', '--start', str(now - graph_range), '--end', str(now), 'DEF:urequests=test.rrd:requests:AVERAGE', 'LINE2:urequests#00FF00')
fd = open('uwsgi_graph.png', 'r')
# send file to browser
return env['wsgi.file_wrapper'](fd, 4096)
# start the simil-cron
uwsgi.send_to_spooler({})
# send file to client
uwsgi.sendfile('uwsgi_graph.png')
uwsgi.applications = {'/': hello_world, '/graph':graph}
+160
View File
@@ -0,0 +1,160 @@
#ifdef UWSGI_INI
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
/*
ini file must be read ALL into memory.
This memory must not be freed for all the server lifecycle
*/
void ini_rstrip(char *line) {
off_t i;
for(i = strlen(line)-1;i>=0; i--) {
if (line[i] == ' ' || line[i] == '\t') {
line[i] = 0;
continue;
}
break;
}
}
char *ini_lstrip(char *line) {
off_t i;
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
if (line[i] == ' ' || line[i] == '\t') {
ptr++;
continue;
}
break;
}
return ptr;
}
char *ini_get_key(char *key) {
off_t i;
char *ptr = key;
for(i=0;i< (int) strlen(key);i++) {
ptr++;
if (key[i] == '=') {
key[i] = 0;
return ptr;
}
}
return ptr;
}
char *ini_get_line(char *ini, off_t size) {
off_t i;
char *ptr = ini;
for(i=0;i<size;i++) {
ptr++;
if (ini[i] == '\n') {
ini[i] = 0;
return ptr;
}
}
// check if it is a stupid file without \n at the end
if (ptr > ini) {
return ptr;
}
return NULL;
}
void uwsgi_ini_config(char *file, char *magic_table[]) {
int len = 0;
char *ini;
char *ini_line;
char *section = "";
char *key;
char *val;
int lines = 1;
char *section_asked = "uwsgi";
char *colon;
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, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
section_asked = colon+1;
}
}
if (file[0] != 0) {
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
}
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
while(len) {
ini_line = ini_get_line(ini, len);
if (ini_line == NULL) {
break;
}
lines++;
// skip empty line
key = ini_lstrip(ini);
ini_rstrip(key);
if (key[0] != 0) {
if (key[0] == '[') {
section = key+1;
section[strlen(section)-1] = 0;
}
else if (key[0] == ';' || key[0] == '#') {
// this is a comment
}
else {
// val is always valid, but (obviously) can be ignored
val = ini_get_key(key);
if (!strcmp(section, section_asked)) {
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
add_exported_option((char *)key, val, 0);
}
}
}
len -= (ini_line - ini);
ini += (ini_line - ini);
}
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>
+111
View File
@@ -0,0 +1,111 @@
#ifdef UWSGI_JSON
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#include <jansson.h>
/*
I really love the jansson library...
*/
void uwsgi_json_config(char *file, char *magic_table[]) {
int len = 0;
char *json_data;
const char *key;
json_t *root;
json_error_t error;
json_t *config;
json_t *config_value, *config_array_item;
void *config_iter;
char *object_asked = "uwsgi";
char *colon;
int i;
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, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
object_asked = colon+1;
}
}
uwsgi_log("[uWSGI] getting JSON configuration from %s\n", file);
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);
exit(1);
}
config = json_object_get(root, object_asked);
if (!json_is_object(config)) {
uwsgi_log("you must define a object named %s in your JSON data\n", object_asked);
exit(1);
}
config_iter = json_object_iter(config);
while(config_iter) {
key = json_object_iter_key(config_iter);
config_value = json_object_iter_value(config_iter);
if (json_is_string(config_value)) {
add_exported_option((char *)key, (char *) json_string_value(config_value), 0);
}
else if (json_is_true(config_value)) {
add_exported_option((char *)key, (char *) "1", 0);
}
else if (json_is_false(config_value) || json_is_null(config_value)) {
add_exported_option((char *)key, (char *) "0", 0);
}
else if (json_is_integer(config_value)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_value)), 0);
}
else if (json_is_array(config_value)) {
for(i=0;i<(int)json_array_size(config_value);i++) {
config_array_item = json_array_get(config_value, i);
if (json_is_string(config_array_item)) {
add_exported_option((char *)key, (char *) json_string_value(config_array_item), 0);
}
else if (json_is_true(config_array_item)) {
add_exported_option((char *)key, (char *) "1", 0);
}
else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
add_exported_option((char *)key, (char *) "0", 0);
}
else if (json_is_integer(config_array_item)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
}
}
}
config_iter = json_object_iter_next(config, config_iter);
}
}
#endif
+393
View File
@@ -0,0 +1,393 @@
#ifdef UWSGI_LDAP
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#include <ldap.h>
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
#ifndef ldap_unbind_ext_s
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
int i;
for(i=0;i< (int) strlen(ldapname);i++) {
if (isupper( (int)ldapname[i])) {
*ptr++ = '-';
*ptr++ = tolower( (int) ldapname[i]);
}
else {
*ptr++ = ldapname[i];
}
}
*ptr++= 0;
}
int calc_ldap_name(char *name) {
int i;
int counter = 0;
for(i=0;i< (int)strlen(name);i++) {
if (isupper( (int) name[i])) {
counter++;
}
}
return strlen(name) + counter;
}
struct uwsgi_ldap_entry {
int num;
char names[1024];
int has_arg;
};
void uwsgi_name_to_ldap(char *src, char *dst) {
int i;
char *ptr = dst;
memset(dst, 0, 1024);
strcat(dst, " 'uWSGI");
ptr+= 7;
for(i=0;i< (int)strlen(src);i++) {
if (src[i] == '-') {
i++;
*ptr++= toupper( (int) src[i]);
}
else {
*ptr++= src[i];
}
}
strcat(dst, "'");
}
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (uwsgi_list_has_str(ule->names, name+1)) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct option *aopt, *lopt;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
static int counter = 30000000;
*count = 0;
lopt = uwsgi.long_options;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
while( (aopt = lopt) ) {
if (!aopt->name)
break;
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry) goto next;
if (aopt->flag) {
entry = &ule[*count] ;
entry->num = counter;
strcpy(entry->names, ldap_name);
counter++;
*count = *count+1;
}
else {
entry = get_ldap_by_num(ule, aopt->val, *count);
if (entry) {
strcat(entry->names, ldap_name);
}
else {
entry = &ule[*count] ;
entry->num = aopt->val;
strcpy(entry->names, ldap_name);
*count = *count+1;
}
}
entry->has_arg = aopt->has_arg;
next:
lopt++;
}
return ule;
}
void uwsgi_ldap_schema_dump_ldif() {
int i;
int items;
uwsgi_log("\n");
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
uwsgi_log("objectClass: olcSchemaConfig\n");
uwsgi_log("cn: uwsgi\n");
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
entry = &ule[i];
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for(i=0;i<items;i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGInull ))\n");
uwsgi_log("\n");
exit(0);
}
void uwsgi_ldap_schema_dump() {
int i;
int items;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for(i=0;i<items;i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGInull ))\n");
exit(0);
}
void uwsgi_ldap_config() {
LDAP *ldp;
LDAPMessage *results, *entry;
BerElement *ber;
struct berval **bervalues;
char *attr;
char *uwsgi_attr;
char *url = "ldap:///";
char *url_slash;
int desired_version = LDAP_VERSION3;
int ret;
LDAPURLDesc *ldap_url;
if (uwsgi.ldap) {
url = uwsgi.ldap;
}
if (!ldap_is_ldap_url(url)) {
uwsgi_log("invalid LDAP url.\n");
exit(1);
}
if (ldap_url_parse(url, &ldap_url) != LDAP_SUCCESS) {
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
url_slash = strchr(url, '/');
url_slash = strchr(url_slash + 1, '/');
url_slash = strchr(url_slash + 1, '/');
if (url_slash) {
url_slash[0] = 0;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP URL: %s\n", url);
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
#endif
#if LDAP_API_VERSION >= 3000
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ( (ldp = ldap_init( ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
if ( (ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP connection initialized %p\n", ldp);
#endif
free(ldap_url);
if (ldap_count_entries(ldp, results) < 1) {
uwsgi_log("no LDAP entry found\n");
exit(1);
}
entry = ldap_first_entry(ldp, results);
int found = 0;
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr,"uWSGI",5)) {
found = 1;
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
if (!uwsgi_attr) {
uwsgi_error("malloc()");
exit(1);
}
ldap2uwsgi(attr+5, uwsgi_attr);
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP attribute: %s = --%s\n", attr, uwsgi_attr);
#endif
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_attr/uwsgi_val;
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
if (!uwsgi_val) {
uwsgi_error("malloc()");
exit(1);
}
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
add_exported_option((char*) uwsgi_attr, uwsgi_val, 0);
free(bervalues);
}
else {
free(uwsgi_attr);
}
}
free(attr);
}
if (!found) {
uwsgi_log("no uWSGI LDAP entry found\n");
exit(1);
}
free(ber);
free(results);
ldap_unbind_ext_s(ldp, NULL, NULL);
}
#endif
+806
View File
@@ -0,0 +1,806 @@
#include "../uwsgi.h"
#define AMQP_CONNECTION_HEADER "AMQP\0\0\x09\x01"
#ifdef __BIG_ENDIAN__
#define ntohll(x) x
#else
#define ntohll(x) ( ( (uint64_t)(ntohl( (uint32_t)((x << 32) >> 32) )) << 32) | ntohl( ((uint32_t)(x >> 32)) ) )
#endif
#define htonll(x) ntohll(x)
#define amqp_send(a, b, c) if (send(a, b, c, 0) < 0) { uwsgi_error("send()"); return -1; }
struct amqp_frame_header {
char type;
uint16_t channel;
uint32_t size;
} __attribute__((__packed__));
struct amqp_frame_method {
uint16_t class_id;
uint16_t method_id;
} __attribute__((__packed__));
static char *amqp_simple_get_frame(int, struct amqp_frame_header *);
static char *amqp_get_method(int, uint16_t, uint16_t, uint32_t *);
/*
static char *amqp_get_longstr(char *ptr, char *watermark) {
uint32_t longstr_size;
if (ptr+4 > watermark) return NULL;
memcpy(&longstr_size, ptr, 4);
longstr_size = ntohl(longstr_size);
if (ptr+4+longstr_size > watermark) return NULL;
return ptr+4+longstr_size;
}
*/
static char *amqp_get_str(char *ptr, char *watermark) {
uint8_t str_size;
// over engeneering...
if (ptr+1 > watermark) return NULL;
str_size = *ptr;
if (ptr+1+str_size > watermark) return NULL;
return ptr+1+str_size;
}
/*
static char *amqp_get_table(char *ptr, char *watermark) {
uint32_t table_size;
if (ptr+4 > watermark) return NULL;
memcpy(&table_size, ptr, 4);
table_size = ntohl(table_size);
if (ptr+4+table_size > watermark) return NULL;
return ptr+4+table_size;
}
*/
static char *amqp_get_short(char *ptr, char *watermark, uint16_t *sv) {
uint16_t tmp_short;
if (ptr+2 > watermark) return NULL;
memcpy(&tmp_short, ptr, 2);
*sv = ntohs(tmp_short);
return ptr+2;
}
static char *amqp_get_long(char *ptr, char *watermark, uint32_t *lv) {
uint32_t tmp_long;
if (ptr+4 > watermark) return NULL;
memcpy(&tmp_long, ptr, 4);
*lv = ntohl(tmp_long);
return ptr+4;
}
static char *amqp_get_longlong(char *ptr, char *watermark, uint64_t *llv) {
uint64_t tmp_longlong;
if (ptr+8 > watermark) return NULL;
memcpy(&tmp_longlong, ptr, 8);
*llv = ntohll(tmp_longlong);
return ptr+8;
}
static int amqp_send_ack(int fd, uint64_t delivery_tag) {
uint32_t size = 4 + 8 + 1;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 60 method 80
amqp_send(fd, "\x00\x3C\x00\x50", 4);
// set delivery_tag
delivery_tag = htonll(delivery_tag);
amqp_send(fd, &delivery_tag, 8);
// empty bits
amqp_send(fd, "\0", 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
uint32_t size;
struct amqp_frame_header fh;
uint64_t delivery_tag;
uint64_t current_size = 0;
char *ptr;
char *watermark;
uint16_t sv;
char *frame = amqp_get_method(fd, 60, 60, &size);
if (!frame) return NULL;
ptr = frame+4;
watermark = frame+size;
// consumer_tag
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
// delivery_tag (needed for ack)
ptr = amqp_get_longlong(ptr, watermark, &delivery_tag); if (!ptr) goto clear;
// redelivered
if (ptr+1 > watermark) goto clear;
ptr++;
// exchange
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
// routing_key
if (ptr+1 > watermark) goto clear;
uint8_t rk_size = (uint8_t) *ptr;
ptr++;
if (ptr+rk_size > watermark) goto clear;
if (rk_size > 0) {
char *rkey = uwsgi_concat2n(ptr, rk_size, "", 0);
ptr+=rk_size;
*routing_key = rkey;
}
else {
*routing_key = NULL;
}
char *header = amqp_simple_get_frame(fd, &fh);
if (!header) goto clear;
if (fh.type != 2) goto clear2;
ptr = header;
watermark = ptr+fh.size;
// header class_id
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
// header weight
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
// message size;
ptr = amqp_get_longlong(ptr, watermark, msgsize); if (!ptr) goto clear2;
free(frame);
free(header);
char *fullbody = uwsgi_malloc(*msgsize);
char *message;
while(current_size < *msgsize) {
message = amqp_simple_get_frame(fd, &fh);
if (!message) goto clear;
if (fh.type != 3) {
free(message);
goto clear3;
}
if (fh.size+current_size > *msgsize) {
free(message);
goto clear3;
}
memcpy(fullbody+current_size, message, fh.size);
current_size+=fh.size;
free(message);
}
if (amqp_send_ack(fd, delivery_tag) < 0) {
goto clear3;
}
return fullbody;
clear3:
free(fullbody);
return NULL;
clear2:
free(header);
clear:
free(frame);
return NULL;
}
static int amqp_send_exchange_declare( int fd, char *exchange, char *exchange_type) {
uint32_t size = 4 + 2 + (1 +strlen(exchange)) + (1 +strlen(exchange_type)) + 1 + 4;
uint8_t shortsize = strlen(exchange) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 40 method 10
amqp_send(fd, "\x00\x28\x00\x0A", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set exchange name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange, shortsize);
// set exchange type
shortsize = strlen(exchange_type);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange_type, shortsize);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_bind( int fd, char *queue, char *exchange) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + (1 +strlen(exchange)) + 1 + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 50 method 20
amqp_send(fd, "\x00\x32\x00\x14", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// set exchange name
shortsize = strlen(exchange);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange, shortsize);
// set empty routing-key
amqp_send(fd, "\0", 1);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_consume( int fd, char *queue) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 60 method 20
amqp_send(fd, "\x00\x3C\x00\x14", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// set tag name
amqp_send(fd, "\0", 1);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_wait_connection_start(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 10, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_exchange_declare_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 40, 11, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_basic_consume_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 60, 21, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_channel_open_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 20, 11, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_queue_bind_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 50, 21, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static char *amqp_wait_queue_declare_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 50, 11, &size);
char *queue = NULL;
char *ptr;
char *watermark;
if (frame) {
ptr = frame+4;
watermark = frame+size;
ptr = amqp_get_str(ptr, watermark); if (!ptr) { free(frame); return NULL; }
queue = uwsgi_concat2n(frame+5, *(frame+4), "", 0);
free(frame);
return queue;
}
return NULL;
}
static int amqp_wait_connection_open_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 41, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_connection_tune(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 30, &size);
uint16_t sv;
uint32_t lv;
char *watermark ;
char *ptr;
if (frame) {
ptr = frame+4;
watermark = frame+size;
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP max channels: %d\n", sv);
ptr = amqp_get_long(ptr, watermark, &lv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP max frame size: %d\n", lv);
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP heartbeath: %d\n", sv);
free(frame);
return 0;
}
return -1;
}
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
char *ptr = (char *) fh;
size_t len = 0, rlen;
while(len < 7) {
rlen = recv(fd, ptr, 7-len, 0);
if (rlen <= 0) {
uwsgi_error("recv()");
return NULL;
}
len += rlen;
ptr += rlen;
}
fh->channel = ntohs(fh->channel);
fh->size = ntohl(fh->size);
len = 0;
char *frame = malloc(fh->size+1);
ptr = frame;
while(len < fh->size+1) {
rlen = recv(fd, ptr, (fh->size+1)-len, 0);
if (rlen <= 0) {
uwsgi_error("recv()");
return NULL;
}
len += rlen;
ptr += rlen;
}
return frame;
}
static char *amqp_get_method(int fd, uint16_t class_id, uint16_t method_id, uint32_t *size) {
struct amqp_frame_header fh;
struct amqp_frame_method *fm;
char *frame = amqp_simple_get_frame(fd, &fh);
if (!frame) return NULL;
if (fh.type != 1) goto clear;
fm = (struct amqp_frame_method *) frame;
fm->class_id = ntohs(fm->class_id);
fm->method_id = ntohs(fm->method_id);
if (fm->class_id != class_id) goto clear;
if (fm->method_id != method_id) goto clear;
*size = fh.size;
return frame;
clear:
free(frame);
return NULL;
}
static int amqp_send_channel_open(int fd, uint16_t id) {
uint32_t size = 4 + 1;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 20 method 10
amqp_send(fd, "\x00\x14\x00\x0A", 4);
amqp_send(fd, "\0", 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int amqp_send_connection_open(int fd, char *vhost) {
uint8_t shortsize = strlen(vhost);
uint32_t size = 4 + 1 +strlen(vhost) + 2;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 28
amqp_send(fd, "\x00\x0A\x00\x28", 4);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, vhost, strlen(vhost));
shortsize = 0;
amqp_send(fd, &shortsize, 1);
amqp_send(fd, &shortsize, 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int amqp_send_connection_tune_ok(int fd, uint16_t max_chan, uint32_t max_frame_size, uint16_t heartbeat) {
uint32_t size = 4 + 2 + 4 + 2;
size = htonl(size);
max_chan = htons(max_chan);
max_frame_size = htonl(max_frame_size);
heartbeat = htons(heartbeat);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 15
amqp_send(fd, "\x00\x0A\x00\x1F", 4);
amqp_send(fd, &max_chan, 2);
amqp_send(fd, &max_frame_size, 4);
amqp_send(fd, &heartbeat, 2);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_declare(int fd, char *queue) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 50 method 10
amqp_send(fd, "\x00\x32\x00\x0A", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static char *amqp_get_queue(int fd, char *queue) {
if (amqp_send_queue_declare(fd, queue) < 0) {
return NULL;
}
return amqp_wait_queue_declare_ok(fd);
}
static int amqp_send_connection_start_ok(int fd, char *mech, char *sasl_response, int sasl_response_size, char *locale) {
uint32_t size = 4 + 4 + (1 +strlen(mech)) + (4 + sasl_response_size) + (1 + strlen(locale));
uint8_t shortsize ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 11
amqp_send(fd, "\x00\x0A\x00\x0B", 4);
// send empty client properties
amqp_send(fd, "\0\0\0\0", 4);
// send mechanism short string
shortsize = strlen(mech);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, mech, strlen(mech));
// send sasl response
size = htonl(sasl_response_size);
amqp_send(fd, &size, 4);
amqp_send(fd, sasl_response, sasl_response_size);
// send locale
shortsize = strlen(locale);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, locale, strlen(locale));
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int uwsgi_amqp_consume_queue(int fd, char *vhost, char *username, char *password, char *queue, char *exchange, char *exchange_type) {
char *auth = uwsgi_concat4n("\0",1, username, strlen(username), "\0",1, password, strlen(password));
if (send(fd, AMQP_CONNECTION_HEADER, 8, 0) < 0) {
uwsgi_error("send()");
return -1;
}
if (amqp_wait_connection_start(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.start\n");
return -1;
}
uwsgi_log("sending Connection.start-ok\n");
if (amqp_send_connection_start_ok(fd, "PLAIN", auth, strlen(username)+strlen(password)+2, "en_US") < 0) {
free(auth);
uwsgi_log("AMQP error sending Connection.start-ok\n");
return -1;
}
free(auth);
if (amqp_wait_connection_tune(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.tune\n");
return -1;
}
uwsgi_log("sending Connection.tune-ok\n");
if (amqp_send_connection_tune_ok(fd, 0, 0xffff, 0) < 0) {
uwsgi_log("AMQP error sending Connection.tune-ok\n");
return -1;
}
uwsgi_log("sending Connection.open\n");
if (amqp_send_connection_open(fd, vhost) < 0) {
uwsgi_log("AMQP error sending Connection.open\n");
return -1;
}
if (amqp_wait_connection_open_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.open-ok\n");
return -1;
}
uwsgi_log("sending Channel.open\n");
if (amqp_send_channel_open(fd, 1) < 0) {
uwsgi_log("AMQP error sending Channel.open\n");
return -1;
}
if (amqp_wait_channel_open_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Channel.open-ok\n");
return -1;
}
queue = amqp_get_queue(fd, queue);
if (!queue) {
uwsgi_log("AMQP error sending Queue.declare\n");
return -1;
}
if (exchange) {
if (amqp_send_exchange_declare(fd, exchange, exchange_type) < 0) {
uwsgi_log("AMQP error sending Exchange.declare\n");
free(queue);
return -1;
}
if (amqp_wait_exchange_declare_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Exchange.declare-ok\n");
free(queue);
return -1;
}
if (amqp_send_queue_bind(fd, queue, exchange) < 0) {
uwsgi_log("AMQP error sending Queue.bind\n");
free(queue);
return -1;
}
if (amqp_wait_queue_bind_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Queue.bind-ok\n");
free(queue);
return -1;
}
}
if (amqp_send_queue_consume(fd, queue) < 0) {
uwsgi_log("AMQP error sending Basic.consume\n");
free(queue);
return -1;
}
if (amqp_wait_basic_consume_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Basic.consume-ok\n");
free(queue);
return -1;
}
free(queue);
uwsgi_log("AMQP subscription done, waiting for events...\n");
return 0;
}
+149
View File
@@ -0,0 +1,149 @@
#include "../uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifndef CLONE_NEWUTS
#define CLONE_NEWUTS 0x04000000
#endif
#ifndef CLONE_NEWPID
#define CLONE_NEWPID 0x20000000
#endif
#ifndef CLONE_NEWIPC
#define CLONE_NEWIPC 0x08000000
#endif
#ifndef CLONE_NEWNET
#define CLONE_NEWNET 0x40000000
#endif
void linux_namespace_start(void *argv) {
for (;;) {
char stack[PTHREAD_STACK_MIN];
int waitpid_status;
uwsgi_log("*** jailing uWSGI in %s ***\n", uwsgi.ns);
int clone_flags = SIGCHLD | CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS;
if (uwsgi.ns_net) {
clone_flags |= CLONE_NEWNET;
}
pid_t pid = clone(uwsgi_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
if (pid == -1) {
uwsgi_error("clone()");
exit(1);
}
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
pid = waitpid(pid, &waitpid_status, 0);
if (pid < 0) {
uwsgi_error("waitpid()");
exit(1);
}
// in Linux this is reliable
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == 1) {
exit(1);
}
uwsgi_log("pid %d ended. Respawning...\n", (int) pid);
}
// never here
}
void linux_namespace_jail() {
char *ns_tmp_mountpoint = NULL, *ns_tmp_mountpoint2 = NULL;
if (getpid() != 1) {
uwsgi_log("your kernel does not support linux pid namespace\n");
exit(1);
}
char *ns_hostname = strchr(uwsgi.ns, ':');
if (ns_hostname) {
ns_hostname[0] = 0;
ns_hostname++;
if (sethostname(ns_hostname, strlen(ns_hostname))) {
uwsgi_error("sethostname()");
}
}
FILE *procmounts;
char line[1024];
int unmounted = 1;
char *delim0, *delim1;
if (chdir(uwsgi.ns)) {
uwsgi_error("chdir()");
exit(1);
}
if (strcmp(uwsgi.ns, "/")) {
ns_tmp_mountpoint = uwsgi_concat2(uwsgi.ns, "/.uwsgi_ns_tmp_mountpoint");
mkdir(ns_tmp_mountpoint, S_IRWXU);
ns_tmp_mountpoint2 = uwsgi_concat2(ns_tmp_mountpoint, "/.uwsgi_ns_tmp_mountpoint");
mkdir(ns_tmp_mountpoint2, S_IRWXU);
if (mount(uwsgi.ns, ns_tmp_mountpoint, "none", MS_BIND, NULL)) {
uwsgi_error("mount()");
}
if (chdir(ns_tmp_mountpoint)) {
uwsgi_error("chdir()");
}
if (pivot_root(".", ns_tmp_mountpoint2)) {
uwsgi_error("pivot_root()");
exit(1);
}
if (chdir("/")) {
uwsgi_error("chdir()");
exit(1);
}
}
uwsgi_log("remounting /proc\n");
if (mount("proc", "/proc", "proc", 0, NULL)) {
uwsgi_error("mount()");
}
while (unmounted) {
unmounted = 0;
procmounts = fopen("/proc/self/mounts", "r");
while (fgets(line, 1024, procmounts) != NULL) {
delim0 = strchr(line, ' ');
delim0++;
delim1 = strchr(delim0, ' ');
*delim1 = 0;
if (!strcmp(delim0, "/") || !strcmp(delim0, "/proc"))
continue;
if (!umount(delim0)) {
unmounted++;
}
}
fclose(procmounts);
}
if (rmdir("/.uwsgi_ns_tmp_mountpoint/.uwsgi_ns_tmp_mountpoint")) {
uwsgi_error("rmdir()");
}
if (rmdir("/.uwsgi_ns_tmp_mountpoint")) {
uwsgi_error("rmdir()");
}
if (strcmp(uwsgi.ns, "/")) {
free(ns_tmp_mountpoint2);
free(ns_tmp_mountpoint);
}
}
+382
View File
@@ -0,0 +1,382 @@
#include "../uwsgi.h"
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#ifdef CLONE_NEWNET
#define NLMSG_TAIL(nmsg) \
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
#ifndef VETH_INFO_PEER
# define VETH_INFO_PEER 1
#endif
struct uwsgi_nl_req {
struct nlmsghdr nlmsg;
struct ifinfomsg ifinfomsg;
};
struct uwsgi_nl_ipreq {
struct nlmsghdr nlmsg;
struct ifaddrmsg ifaddrmsg;
};
struct uwsgi_nl_rtreq {
struct nlmsghdr nlmsg;
struct rtmsg rtmsg;
};
int uwsgi_nl_send(struct nlmsghdr *);
struct nlmsghdr *uwsgi_netlink_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
unr->ifinfomsg.ifi_family = AF_UNSPEC;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
nlmsg->nlmsg_type = RTM_NEWLINK;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
return nlmsg;
}
struct nlmsghdr *uwsgi_netlink_ip_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
uni->ifaddrmsg.ifa_family = AF_INET;
uni->ifaddrmsg.ifa_scope = 0;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
nlmsg->nlmsg_type = RTM_NEWADDR;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
return nlmsg;
}
struct nlmsghdr *uwsgi_netlink_rt_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
unr->rtmsg.rtm_family = AF_INET;
unr->rtmsg.rtm_table = RT_TABLE_MAIN;
unr->rtmsg.rtm_protocol = RTPROT_STATIC;
unr->rtmsg.rtm_scope = RT_SCOPE_UNIVERSE;
unr->rtmsg.rtm_type = RTN_UNICAST;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
nlmsg->nlmsg_type = RTM_NEWROUTE;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
return nlmsg;
}
int uwsgi_netlink_rt(char *src, char *dst, int dst_prefix, char *gw) {
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
struct rtattr *rta;
struct in_addr ia;
struct in_addr oa;
struct in_addr ga;
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
if (inet_pton(AF_INET, src, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
if (inet_pton(AF_INET, dst, &oa) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
if (inet_pton(AF_INET, gw, &ga) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_PREFSRC;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_DST;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &oa.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_GATEWAY;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ga.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
unr->rtmsg.rtm_src_len = 0;
unr->rtmsg.rtm_dst_len = dst_prefix;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_gw(char *iface, char *ip) {
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
struct rtattr *rta;
struct in_addr ia;
uint32_t zero = 0;
int index = if_nametoindex(iface);
if (!index) return -1;
if (inet_pton(AF_INET, ip, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_GATEWAY;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_DST;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &zero, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_OIF;
rta->rta_len = RTA_LENGTH(sizeof(int));
memcpy(RTA_DATA(rta), &index, sizeof(int));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_ip(char *iface, char *ip, int prefix) {
struct nlmsghdr *nlmsg = uwsgi_netlink_ip_alloc();
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
struct rtattr *rta;
struct in_addr ia;
int index = if_nametoindex(iface);
if (!index) return -1;
uni->ifaddrmsg.ifa_index = index;
uni->ifaddrmsg.ifa_prefixlen = prefix;
if (inet_pton(AF_INET, ip, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFA_LOCAL;
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFA_ADDRESS;
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_veth_attach(char *veth1, pid_t pid) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
struct rtattr *rta;
int index = if_nametoindex(veth1);
if (!index) return -1;
unr->ifinfomsg.ifi_index = index;
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_NET_NS_PID;
rta->rta_len = RTA_LENGTH(sizeof(pid_t));
memcpy(RTA_DATA(rta), &pid, sizeof(pid_t));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_ifup(char *iface) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
int index = if_nametoindex(iface);
if (!index) return -1;
unr->ifinfomsg.ifi_index = index;
unr->ifinfomsg.ifi_change |= IFF_UP;
unr->ifinfomsg.ifi_flags |= IFF_UP;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_del(char *iface) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
int index = if_nametoindex(iface);
if (!index) return -1;
nlmsg->nlmsg_type = RTM_DELLINK;
unr->ifinfomsg.ifi_index = index;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_veth(char *veth0, char *veth1) {
struct rtattr *rta, *rta0, *rta1, *rta2;
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
nlmsg->nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
// IFLA_LINKINFO
rta0 = NLMSG_TAIL(nlmsg);
rta0->rta_type = IFLA_LINKINFO;
rta0->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta0->rta_len);
// IFLA_INFO_KIND
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_INFO_KIND;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), "veth", 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
// IFLA_INFO_DATA
rta1 = NLMSG_TAIL(nlmsg);
rta1->rta_type = IFLA_INFO_DATA;
rta1->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta1->rta_len);
// VETH_INFO_PEER
rta2 = NLMSG_TAIL(nlmsg);
rta2->rta_type = VETH_INFO_PEER;
rta2->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta2->rta_len);
nlmsg->nlmsg_len += sizeof(struct ifinfomsg);
// IFLA_IFNAME
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_IFNAME;
rta->rta_len = RTA_LENGTH(strlen(veth1));
memcpy(RTA_DATA(rta), veth1, strlen(veth1));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta2->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta2;
rta1->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta1;
rta0->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta0;
// IFLA_IFNAME
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_IFNAME;
rta->rta_len = RTA_LENGTH(strlen(veth0));
memcpy(RTA_DATA(rta), veth0, strlen(veth0));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_nl_send(struct nlmsghdr *nlmsg) {
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = (void*)nlmsg,
.iov_len = nlmsg->nlmsg_len,
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
int ret;
int nlfd;
memset(&nladdr, 0, sizeof(struct sockaddr_nl));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (nlfd < 0) {
uwsgi_error("socket()");
free(nlmsg);
return -1;
}
ret = sendmsg(nlfd, &msg, 0);
if (ret < 0) {
uwsgi_error("sendmsg()");
free(nlmsg);
close(nlfd);
return -1;
}
ret = recvmsg(nlfd, &msg, 0);
if (ret < 0) {
uwsgi_error("recvmsg()");
free(nlmsg);
close(nlfd);
return -1;
}
if (nlmsg->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlmsg);
ret = err->error;
}
free(nlmsg);
close(nlfd);
return ret;
}
#endif
+309
View File
@@ -0,0 +1,309 @@
/*
*** uWSGI, stripped down version of Linux rbtree ***
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
(C) 2002 David Woodhouse <dwmw2@infradead.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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;
struct rb_node *parent = rb_parent(node);
if ((node->rb_right = right->rb_left))
rb_set_parent(right->rb_left, node);
right->rb_left = node;
rb_set_parent(right, parent);
if (parent)
{
if (node == parent->rb_left)
parent->rb_left = right;
else
parent->rb_right = right;
}
else
root->rb_node = right;
rb_set_parent(node, right);
}
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{
struct rb_node *left = node->rb_left;
struct rb_node *parent = rb_parent(node);
if ((node->rb_left = left->rb_right))
rb_set_parent(left->rb_right, node);
left->rb_right = node;
rb_set_parent(left, parent);
if (parent)
{
if (node == parent->rb_right)
parent->rb_right = left;
else
parent->rb_left = left;
}
else
root->rb_node = left;
rb_set_parent(node, left);
}
void rb_insert_color(struct rb_node *node, struct rb_root *root)
{
struct rb_node *parent, *gparent;
while ((parent = rb_parent(node)) && rb_is_red(parent))
{
gparent = rb_parent(parent);
if (parent == gparent->rb_left)
{
{
register struct rb_node *uncle = gparent->rb_right;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_right == node)
{
register struct rb_node *tmp;
__rb_rotate_left(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_right(gparent, root);
} else {
{
register struct rb_node *uncle = gparent->rb_left;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_left == node)
{
register struct rb_node *tmp;
__rb_rotate_right(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_left(gparent, root);
}
}
rb_set_black(root->rb_node);
}
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
struct rb_root *root)
{
struct rb_node *other;
while ((!node || rb_is_black(node)) && node != root->rb_node)
{
if (parent->rb_left == node)
{
other = parent->rb_right;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_left(parent, root);
other = parent->rb_right;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_right || rb_is_black(other->rb_right))
{
rb_set_black(other->rb_left);
rb_set_red(other);
__rb_rotate_right(other, root);
other = parent->rb_right;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_right);
__rb_rotate_left(parent, root);
node = root->rb_node;
break;
}
}
else
{
other = parent->rb_left;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_right(parent, root);
other = parent->rb_left;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_left || rb_is_black(other->rb_left))
{
rb_set_black(other->rb_right);
rb_set_red(other);
__rb_rotate_left(other, root);
other = parent->rb_left;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_left);
__rb_rotate_right(parent, root);
node = root->rb_node;
break;
}
}
}
if (node)
rb_set_black(node);
}
void rb_erase(struct rb_node *node, struct rb_root *root)
{
struct rb_node *child, *parent;
int color;
if (!node->rb_left)
child = node->rb_right;
else if (!node->rb_right)
child = node->rb_left;
else
{
struct rb_node *old = node, *left;
node = node->rb_right;
while ((left = node->rb_left) != NULL)
node = left;
if (rb_parent(old)) {
if (rb_parent(old)->rb_left == old)
rb_parent(old)->rb_left = node;
else
rb_parent(old)->rb_right = node;
} else
root->rb_node = node;
child = node->rb_right;
parent = rb_parent(node);
color = rb_color(node);
if (parent == old) {
parent = node;
} else {
if (child)
rb_set_parent(child, parent);
parent->rb_left = child;
node->rb_right = old->rb_right;
rb_set_parent(old->rb_right, node);
}
node->rb_parent_color = old->rb_parent_color;
node->rb_left = old->rb_left;
rb_set_parent(old->rb_left, node);
goto color;
}
parent = rb_parent(node);
color = rb_color(node);
if (child)
rb_set_parent(child, parent);
if (parent)
{
if (parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
}
else
root->rb_node = child;
color:
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;
}
+56
View File
@@ -0,0 +1,56 @@
/*
*** uWSGI, stripped down version of Linux rbtree ***
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
struct rb_node
{
unsigned long rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
/* The alignment might seem pointless, but allegedly CRIS needs it */
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))
#define rb_is_black(r) rb_color(r)
#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)
void rb_insert_color(struct rb_node *, struct rb_root *);
void rb_erase(struct rb_node *, struct rb_root *);
#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
+29
View File
@@ -0,0 +1,29 @@
/* function written by Ben Taylor (found in the qemu-devel list) */
#include "../uwsgi.h"
time_t timegm(struct tm *t) {
time_t tl, tb;
struct tm *tg;
tl = mktime (t);
if (tl == -1) {
t->tm_hour--;
tl = mktime (t);
if (tl == -1)
return -1; /* can't deal with output from strptime */
tl += 3600;
}
tg = gmtime (&tl);
tg->tm_isdst = 0;
tb = mktime (tg);
if (tb == -1) {
tg->tm_hour--;
tb = mktime (tg);
if (tb == -1)
return -1; /* can't deal with output from gmtime */
tb += 3600;
}
return (tl - (tb - tl));
}
+234 -228
View File
@@ -38,7 +38,7 @@
#ifdef __linux__
#include <endian.h>
#elif __sun__
#elif __apple__
#elif __APPLE__
#include <libkern/OSByteOrder.h>
#else
#include <machine/endian.h>
@@ -47,7 +47,7 @@
#ifdef __BIG_ENDIAN__
static uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
#endif
@@ -64,7 +64,7 @@ typedef struct __attribute__((packed)) {
uint8_t modifier1;
uint16_t pktsize;
uint8_t modifier2;
} uwsgi_header ;
} uwsgi_header;
typedef struct {
array *extensions;
@@ -394,7 +394,7 @@ static int uwsgi_establish_connection(server *srv, handler_ctx *hctx) {
static void uwsgi_add_var(buffer *b, char * key, uint16_t keylen, char *val, uint16_t vallen) {
#ifdef __BIG_ENDIAN__
uint16_t uwlen ;
uint16_t uwlen;
uwlen = uwsgi_swap16(keylen);
buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, key, keylen);
@@ -405,19 +405,19 @@ static void uwsgi_add_var(buffer *b, char * key, uint16_t keylen, char *val, uin
buffer_append_memory(b, (char *) &vallen, 2); buffer_append_memory(b, val, vallen);
#endif
}
static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
size_t i;
char buf[32];
uwsgi_header *uh ;
uwsgi_header *uh;
const char *s;
#ifdef HAVE_IPV6
char b2[INET6_ADDRSTRLEN + 1];
#endif
connection *con = hctx->remote_conn;
server_socket *srv_sock = con->srv_socket;
@@ -436,53 +436,59 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
if (!buffer_is_empty(con->uri.query)) {
uwsgi_add_var(b, "QUERY_STRING", 12, con->uri.query->ptr, con->uri.query->used-1);
} else {
} else {
uwsgi_add_var(b, "QUERY_STRING", 12, "", 0);
}
}
s = get_http_version_name(con->request.http_version);
uwsgi_add_var(b, "SERVER_PROTOCOL", 15, (char *) s, strlen(s));
if (con->server_name->used) {
size_t len = con->server_name->used - 1;
char *colon = strchr(con->server_name->ptr, ':');
if (colon) len = colon - con->server_name->ptr;
size_t len = con->server_name->used - 1;
char *colon = strchr(con->server_name->ptr, ':');
if (colon) len = colon - con->server_name->ptr;
uwsgi_add_var(b, "SERVER_NAME", 11, con->server_name->ptr, len);
} else {
} else {
#ifdef HAVE_IPV6
s = inet_ntop(srv_sock->addr.plain.sa_family,
srv_sock->addr.plain.sa_family == AF_INET6 ?
(const void *) &(srv_sock->addr.ipv6.sin6_addr) :
(const void *) &(srv_sock->addr.ipv4.sin_addr),
b2, sizeof(b2)-1);
s = inet_ntop(srv_sock->addr.plain.sa_family,
srv_sock->addr.plain.sa_family == AF_INET6 ?
(const void *) &(srv_sock->addr.ipv6.sin6_addr) :
(const void *) &(srv_sock->addr.ipv4.sin_addr),
b2, sizeof(b2)-1);
#else
s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
#endif
uwsgi_add_var(b, "SERVER_NAME", 11, (char *)s, strlen(s));
}
}
LI_ltostr(buf,
#ifdef HAVE_IPV6
ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
#else
ntohs(srv_sock->addr.ipv4.sin_port)
ntohs(srv_sock->addr.ipv4.sin_port)
#endif
);
);
uwsgi_add_var(b, "SERVER_PORT", 11, buf, strlen(buf));
uwsgi_add_var(b, "REQUEST_URI", 11, con->request.orig_uri->ptr, con->request.orig_uri->used-1);
LI_ltostr(buf,
#ifdef HAVE_IPV6
ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
#else
ntohs(con->dst_addr.ipv4.sin_port)
ntohs(con->dst_addr.ipv4.sin_port)
#endif
);
);
uwsgi_add_var(b, "REMOTE_PORT", 11, buf, strlen(buf));
if (!buffer_is_empty(con->authed_user)) {
uwsgi_add_var(b, "REMOTE_USER", 11,
CONST_BUF_LEN(con->authed_user));
}
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
uwsgi_add_var(b, "REMOTE_ADDR", 11, (char *)s, strlen(s));
@@ -490,18 +496,18 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
if (hctx->path_info_offset > 1) {
uwsgi_add_var(b, "SCRIPT_NAME", 11, con->uri.path->ptr, hctx->path_info_offset);
if (strlen(con->uri.path->ptr + hctx->path_info_offset) > 0) {
uwsgi_add_var(b, "PATH_INFO", 9, con->request.orig_uri->ptr + hctx->path_info_offset, strlen(con->request.orig_uri->ptr + hctx->path_info_offset));
uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr + hctx->path_info_offset, strlen(con->uri.path->ptr + hctx->path_info_offset));
}
else {
uwsgi_add_var(b, "PATH_INFO", 9, "/", 1);
}
}
else {
uwsgi_add_var(b, "SCRIPT_NAME", 11, "", 0) ;
uwsgi_add_var(b, "PATH_INFO", 9, con->request.orig_uri->ptr, con->request.orig_uri->used-1) ;
uwsgi_add_var(b, "SCRIPT_NAME", 11, "", 0);
uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr, strlen(con->uri.path->ptr));
}
for (i = 0; i < con->request.headers->used; i++) {
data_string *ds;
ds = (data_string *)con->request.headers->data[i];
@@ -518,7 +524,7 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
}
for (j = 0; j < ds->key->used - 1; j++) {
srv->tmp_buf->ptr[srv->tmp_buf->used++] = light_isalpha(ds->key->ptr[j]) ? ds->key->ptr[j] & ~32 : '_';
}
}
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
uwsgi_add_var(b, srv->tmp_buf->ptr, srv->tmp_buf->used-1, ds->value->ptr, ds->value->used-1);
}
@@ -540,19 +546,19 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
}
}
uh = (uwsgi_header *) b->ptr ;
uh->modifier1 = (uint8_t) 0 ;
uh = (uwsgi_header *) b->ptr;
uh->modifier1 = (uint8_t) 0;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16((uint16_t) b->used - 4) ;
uh->pktsize = uwsgi_swap16((uint16_t) b->used - 4);
#else
uh->pktsize = b->used - 4 ;
uh->pktsize = b->used - 4;
#endif
uh->modifier2 = (uint8_t) 0 ;
uh->modifier2 = (uint8_t) 0;
b->used++; /* fix size */
hctx->wb->bytes_in += b->used -1 ;
hctx->wb->bytes_in += b->used -1;
/* body */
if (con->request.content_length) {
@@ -570,37 +576,37 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
* */
switch (req_c->type) {
case FILE_CHUNK:
weHave = req_c->file.length - req_c->offset;
case FILE_CHUNK:
weHave = req_c->file.length - req_c->offset;
if (weHave > weWant) weHave = weWant;
if (weHave > weWant) weHave = weWant;
chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
req_c->offset += weHave;
req_cq->bytes_out += weHave;
req_c->offset += weHave;
req_cq->bytes_out += weHave;
hctx->wb->bytes_in += weHave;
hctx->wb->bytes_in += weHave;
break;
case MEM_CHUNK:
/* append to the buffer */
weHave = req_c->mem->used - 1 - req_c->offset;
break;
case MEM_CHUNK:
/* append to the buffer */
weHave = req_c->mem->used - 1 - req_c->offset;
if (weHave > weWant) weHave = weWant;
if (weHave > weWant) weHave = weWant;
b = chunkqueue_get_append_buffer(hctx->wb);
buffer_append_memory(b, req_c->mem->ptr + req_c->offset, weHave);
b->used++; /* add virtual \0 */
b = chunkqueue_get_append_buffer(hctx->wb);
buffer_append_memory(b, req_c->mem->ptr + req_c->offset, weHave);
b->used++; /* add virtual \0 */
req_c->offset += weHave;
req_cq->bytes_out += weHave;
req_c->offset += weHave;
req_cq->bytes_out += weHave;
hctx->wb->bytes_in += weHave;
hctx->wb->bytes_in += weHave;
break;
default:
break;
break;
default:
break;
}
offset += weHave;
@@ -671,29 +677,29 @@ static int uwsgi_response_parse(server *srv, connection *con, plugin_data *p, bu
copy_header = 1;
switch(key_len) {
case 4:
if (0 == strncasecmp(key, "Date", key_len)) {
con->parsed_response |= HTTP_DATE;
}
break;
case 8:
if (0 == strncasecmp(key, "Location", key_len)) {
con->parsed_response |= HTTP_LOCATION;
}
break;
case 10:
if (0 == strncasecmp(key, "Connection", key_len)) {
copy_header = 0;
}
break;
case 14:
if (0 == strncasecmp(key, "Content-Length", key_len)) {
con->response.content_length = strtol(value, NULL, 10);
con->parsed_response |= HTTP_CONTENT_LENGTH;
}
break;
default:
break;
case 4:
if (0 == strncasecmp(key, "Date", key_len)) {
con->parsed_response |= HTTP_DATE;
}
break;
case 8:
if (0 == strncasecmp(key, "Location", key_len)) {
con->parsed_response |= HTTP_LOCATION;
}
break;
case 10:
if (0 == strncasecmp(key, "Connection", key_len)) {
copy_header = 0;
}
break;
case 14:
if (0 == strncasecmp(key, "Content-Length", key_len)) {
con->response.content_length = strtol(value, NULL, 10);
con->parsed_response |= HTTP_CONTENT_LENGTH;
}
break;
default:
break;
}
if (copy_header) {
@@ -731,7 +737,7 @@ static int uwsgi_demux_response(server *srv, handler_ctx *hctx) {
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "sd",
"uwsgi - have to read:", b);
"uwsgi - have to read:", b);
}
if (b > 0) {
@@ -785,7 +791,7 @@ static int uwsgi_demux_response(server *srv, handler_ctx *hctx) {
/* enable chunked-transfer-encoding */
if (con->request.http_version == HTTP_VERSION_1_1 &&
!(con->parsed_response & HTTP_CONTENT_LENGTH)) {
!(con->parsed_response & HTTP_CONTENT_LENGTH)) {
con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
}
@@ -824,127 +830,127 @@ static handler_t uwsgi_write_request(server *srv, handler_ctx *hctx) {
int ret;
if (!host ||
(!host->host->used || !host->port)) return -1;
(!host->host->used || !host->port)) return -1;
switch(hctx->state) {
case UWSGI_STATE_INIT:
case UWSGI_STATE_INIT:
#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON)
if (strstr(host->host->ptr,":")) {
if (-1 == (hctx->fd = socket(AF_INET6, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
} else
if (strstr(host->host->ptr,":")) {
if (-1 == (hctx->fd = socket(AF_INET6, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
} else
#endif
{
if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
}
hctx->fde_ndx = -1;
{
if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
}
hctx->fde_ndx = -1;
srv->cur_fds++;
srv->cur_fds++;
fdevent_register(srv->ev, hctx->fd, uwsgi_handle_fdevent, hctx);
fdevent_register(srv->ev, hctx->fd, uwsgi_handle_fdevent, hctx);
if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
return HANDLER_ERROR;
}
/* fall through */
case UWSGI_STATE_CONNECT:
/* try to finish the connect() */
if (hctx->state == UWSGI_STATE_INIT) {
/* first round */
switch (uwsgi_establish_connection(srv, hctx)) {
case 1:
uwsgi_set_state(srv, hctx, UWSGI_STATE_CONNECT);
/* connection is in progress, wait for an event and call getsockopt() below */
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_WAIT_FOR_EVENT;
case -1:
/* if ECONNREFUSED choose another connection -> FIXME */
hctx->fde_ndx = -1;
if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
return HANDLER_ERROR;
default:
/* everything is ok, go on */
break;
}
} else {
int socket_error;
socklen_t socket_error_len = sizeof(socket_error);
/* we don't need it anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
/* fall through */
case UWSGI_STATE_CONNECT:
/* try to finish the connect() */
if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"getsockopt failed:", strerror(errno));
if (hctx->state == UWSGI_STATE_INIT) {
/* first round */
switch (uwsgi_establish_connection(srv, hctx)) {
case 1:
uwsgi_set_state(srv, hctx, UWSGI_STATE_CONNECT);
return HANDLER_ERROR;
/* connection is in progress, wait for an event and call getsockopt() below */
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_WAIT_FOR_EVENT;
case -1:
/* if ECONNREFUSED choose another connection -> FIXME */
hctx->fde_ndx = -1;
return HANDLER_ERROR;
default:
/* everything is ok, go on */
break;
}
} else {
int socket_error;
socklen_t socket_error_len = sizeof(socket_error);
/* we don't need it anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
/* try to finish the connect() */
if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"getsockopt failed:", strerror(errno));
return HANDLER_ERROR;
}
if (socket_error != 0) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"establishing connection failed:", strerror(socket_error),
"port:", hctx->host->port);
return HANDLER_ERROR;
}
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "s", "uwsgi - connect - delayed success");
}
}
if (socket_error != 0) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"establishing connection failed:", strerror(socket_error),
"port:", hctx->host->port);
return HANDLER_ERROR;
}
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "s", "uwsgi - connect - delayed success");
}
}
uwsgi_set_state(srv, hctx, UWSGI_STATE_PREPARE_WRITE);
/* fall through */
case UWSGI_STATE_PREPARE_WRITE:
uwsgi_create_env(srv, hctx);
uwsgi_set_state(srv, hctx, UWSGI_STATE_PREPARE_WRITE);
/* fall through */
case UWSGI_STATE_PREPARE_WRITE:
uwsgi_create_env(srv, hctx);
uwsgi_set_state(srv, hctx, UWSGI_STATE_WRITE);
uwsgi_set_state(srv, hctx, UWSGI_STATE_WRITE);
/* fall through */
case UWSGI_STATE_WRITE:;
ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
/* fall through */
case UWSGI_STATE_WRITE:;
ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
chunkqueue_remove_finished_chunks(hctx->wb);
chunkqueue_remove_finished_chunks(hctx->wb);
if (-1 == ret) { /* error on our side */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
if (-1 == ret) { /* error on our side */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
return HANDLER_WAIT_FOR_EVENT;
} else if (-2 == ret) { /* remote close */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed, remote connection close:", strerror(errno), errno);
return HANDLER_WAIT_FOR_EVENT;
} else if (-2 == ret) { /* remote close */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed, remote connection close:", strerror(errno), errno);
return HANDLER_WAIT_FOR_EVENT;
}
return HANDLER_WAIT_FOR_EVENT;
}
if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
uwsgi_set_state(srv, hctx, UWSGI_STATE_READ);
if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
uwsgi_set_state(srv, hctx, UWSGI_STATE_READ);
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
} else {
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
} else {
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_WAIT_FOR_EVENT;
}
return HANDLER_WAIT_FOR_EVENT;
}
return HANDLER_WAIT_FOR_EVENT;
case UWSGI_STATE_READ:
/* waiting for a response */
return HANDLER_WAIT_FOR_EVENT;
default:
log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
return HANDLER_ERROR;
return HANDLER_WAIT_FOR_EVENT;
case UWSGI_STATE_READ:
/* waiting for a response */
return HANDLER_WAIT_FOR_EVENT;
default:
log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
return HANDLER_ERROR;
}
return HANDLER_GO_ON;
@@ -1000,36 +1006,36 @@ SUBREQUEST_FUNC(mod_uwsgi_handle_subrequest) {
/* ok, create the request */
switch(uwsgi_write_request(srv, hctx)) {
case HANDLER_ERROR:
log_error_write(srv, __FILE__, __LINE__, "sbdd", "uwsgi-server disabled:",
host->host,
host->port,
hctx->fd);
case HANDLER_ERROR:
log_error_write(srv, __FILE__, __LINE__, "sbdd", "uwsgi-server disabled:",
host->host,
host->port,
hctx->fd);
/* disable this server */
host->is_disabled = 1;
host->disable_ts = srv->cur_ts;
/* disable this server */
host->is_disabled = 1;
host->disable_ts = srv->cur_ts;
uwsgi_connection_close(srv, hctx);
uwsgi_connection_close(srv, hctx);
/* reset the enviroment and restart the sub-request */
buffer_reset(con->physical.path);
con->mode = DIRECT;
/* reset the enviroment and restart the sub-request */
buffer_reset(con->physical.path);
con->mode = DIRECT;
joblist_append(srv, con);
joblist_append(srv, con);
/* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
* and hope that the childs will be restarted
*
*/
/* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
* and hope that the childs will be restarted
*
*/
return HANDLER_WAIT_FOR_FD;
case HANDLER_WAIT_FOR_EVENT:
return HANDLER_WAIT_FOR_EVENT;
case HANDLER_WAIT_FOR_FD:
return HANDLER_WAIT_FOR_FD;
default:
break;
return HANDLER_WAIT_FOR_FD;
case HANDLER_WAIT_FOR_EVENT:
return HANDLER_WAIT_FOR_EVENT;
case HANDLER_WAIT_FOR_FD:
return HANDLER_WAIT_FOR_FD;
default:
break;
}
if (con->file_started == 1) {
@@ -1047,7 +1053,7 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
if ((revents & FDEVENT_IN) &&
hctx->state == UWSGI_STATE_READ) {
hctx->state == UWSGI_STATE_READ) {
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "sd",
@@ -1055,29 +1061,29 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
}
switch (uwsgi_demux_response(srv, hctx)) {
case 0:
break;
case 1:
hctx->host->usage--;
case 0:
break;
case 1:
hctx->host->usage--;
/* we are done */
uwsgi_connection_close(srv, hctx);
/* we are done */
uwsgi_connection_close(srv, hctx);
joblist_append(srv, con);
return HANDLER_FINISHED;
case -1:
if (con->file_started == 0) {
/* nothing has been send out yet, send a 500 */
connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
con->http_status = 500;
con->mode = DIRECT;
} else {
/* response might have been already started, kill the connection */
connection_set_state(srv, con, CON_STATE_ERROR);
}
joblist_append(srv, con);
return HANDLER_FINISHED;
case -1:
if (con->file_started == 0) {
/* nothing has been send out yet, send a 500 */
connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
con->http_status = 500;
con->mode = DIRECT;
} else {
/* response might have been already started, kill the connection */
connection_set_state(srv, con, CON_STATE_ERROR);
}
joblist_append(srv, con);
return HANDLER_FINISHED;
joblist_append(srv, con);
return HANDLER_FINISHED;
}
}
@@ -1088,7 +1094,7 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
}
if (hctx->state == UWSGI_STATE_CONNECT ||
hctx->state == UWSGI_STATE_WRITE) {
hctx->state == UWSGI_STATE_WRITE) {
/* we are allowed to send something out
*
* 1. in a unfinished connect() call
@@ -1189,7 +1195,7 @@ static handler_t mod_uwsgi_check_extension(server *srv, connection *con, void *p
/* check extension in the form "/uwsgi_pattern" */
if (*(ext->key->ptr) == '/') {
if (strncmp(fn->ptr, ext->key->ptr, ct_len) == 0) {
path_info_offset = ct_len ;
path_info_offset = ct_len;
extension = ext;
break;
}
@@ -1314,7 +1320,7 @@ TRIGGER_FUNC(mod_uwsgi_trigger) {
data_uwsgi *host = (data_uwsgi *)extension->value->data[n];
if (!host->is_disabled ||
srv->cur_ts - host->disable_ts < 5) continue;
srv->cur_ts - host->disable_ts < 5) continue;
log_error_write(srv, __FILE__, __LINE__, "sbd",
"uwsgi - re-enabled:",
+196
View File
@@ -0,0 +1,196 @@
#include "uwsgi.h"
#ifdef UWSGI_LOCK_USE_MUTEX
#define UWSGI_LOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
void uwsgi_lock_init(void *lock) {
if (pthread_mutexattr_init((pthread_mutexattr_t *) lock)) {
uwsgi_log("unable to allocate mutexattr structure\n");
exit(1);
}
if (pthread_mutexattr_setpshared((pthread_mutexattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share mutex\n");
exit(1);
}
if (pthread_mutex_init((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t), (pthread_mutexattr_t *) lock)) {
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
}
void uwsgi_rlock(void *lock) {
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
}
void uwsgi_wlock(void *lock) {
pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
}
void uwsgi_rwunlock(void *lock) {
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
}
void uwsgi_lock(void *lock) {
pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
void uwsgi_unlock(void *lock) {
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
void uwsgi_rwlock_init(void *lock) {
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
uwsgi_log("unable to allocate rwlock structure\n");
exit(1);
}
if (pthread_rwlockattr_setpshared((pthread_rwlockattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share rwlock\n");
exit(1);
}
if (pthread_rwlock_init((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t), (pthread_rwlockattr_t *) lock)) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
}
#endif
#ifdef UWSGI_LOCK_USE_UMTX
#include <machine/atomic.h>
#include <sys/umtx.h>
#define UWSGI_LOCK_SIZE sizeof(struct umtx)
#define UWSGI_RWLOCK_SIZE sizeof(struct umtx)
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
void uwsgi_lock_init(void *lock) {
umtx_init((struct umtx*) lock);
}
void uwsgi_lock(void *lock) {
umtx_lock(lock, 1);
}
void uwsgi_unlock(void *lock) {
umtx_unlock(lock, 1);
}
#endif
#ifdef UWSGI_LOCK_USE_OSX_SPINLOCK
#define UWSGI_LOCK_SIZE sizeof(OSSpinLock)
#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock)
void uwsgi_lock_init(void *lock) {
memset(lock, 0, sizeof(OSSpinLock));
}
void uwsgi_lock(void *lock) {
OSSpinLockLock((OSSpinLock *) lock);
}
void uwsgi_unlock(void *lock) {
OSSpinLockUnlock((OSSpinLock *) lock);
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
#endif
#ifdef UWSGI_LOCK_USE_FLOCK
#define UWSGI_LOCK_SIZE 8
#define UWSGI_RWLOCK_SIZE 8
void uwsgi_lock_init(void *lock) {
FILE *tf = tmpfile();
int fd;
if (!tf) {
uwsgi_error_open("temp lock file");
exit(1);
}
fd = fileno(tf);
memcpy(lock, &fd, sizeof(int));
}
void uwsgi_lock(void *lock) {
int fd;
memcpy(&fd, lock, sizeof(int));
if (flock(fd, LOCK_EX)) { uwsgi_error("flock()"); }
}
void uwsgi_unlock(void *lock) {
int fd;
memcpy(&fd, lock, sizeof(int));
if (flock(fd, LOCK_UN)) { uwsgi_error("flock()"); }
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
#endif
void *uwsgi_mmap_shared_lock() {
void *addr = NULL;
addr = mmap(NULL, UWSGI_LOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (addr == NULL) {
uwsgi_error("mmap()");
exit(1);
}
return addr;
}
void *uwsgi_mmap_shared_rwlock() {
void *addr = NULL;
addr = mmap(NULL, UWSGI_RWLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (addr == NULL) {
uwsgi_error("mmap()");
exit(1);
}
return addr;
}
+108 -44
View File
@@ -1,3 +1,4 @@
#define _NO_UWSGI_RB
#include "uwsgi.h"
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
@@ -12,32 +13,51 @@
#define _FILE_OFFSET_BITS 64
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#endif
extern struct uwsgi_server uwsgi;
void log_request(struct wsgi_request *wsgi_req) {
// optimize this (please)
char *time_request;
time_t microseconds, microseconds2;
static char *empty = "";
char *first_part = empty;
int rlen;
int app_req = -1;
char *msg2 = " ";
char *via = msg2;
char mempkt[4096];
char logpkt[4096];
struct iovec logvec[4];
int logvecpos = 0;
const char *msecs = "msecs";
const char *micros = "micros";
long int rt;
char *tsize = (char *) msecs;
#ifdef UWSGI_SENDFILE
char *msg1 = " via sendfile() ";
#endif
struct uwsgi_app *wi;
if (wsgi_req->do_not_log) return ;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi.wsgi_apps[wsgi_req->app_id];
wi = &uwsgi_apps[wsgi_req->app_id];
if (wi->requests > 0) {
app_req = wi->requests;
}
}
via = msg2;
if (wsgi_req->sendfile_fd > -1) {
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
via = msg1;
}
#endif
@@ -46,44 +66,67 @@ void log_request(struct wsgi_request *wsgi_req) {
microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
rt = (long int) (microseconds - microseconds2);
if (uwsgi.log_micros) {
tsize = (char *) micros;
}
else {
rt /= 1000;
}
if (uwsgi.vhost) {
logvec[logvecpos].iov_base = wsgi_req->host;
logvec[logvecpos].iov_len = wsgi_req->host_len;
logvecpos++;
logvec[logvecpos].iov_base = " ";
logvec[logvecpos].iov_len = 1;
logvecpos++;
}
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
#ifndef UNBIT
if (uwsgi.synclog) {
snprintf(uwsgi.sync_page, uwsgi.page_size, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
first_part = uwsgi.sync_page;
}
else {
fprintf(stderr, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
}
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ",
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
#else
fprintf(stderr, "{address space usage: %lld bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ",
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
#endif
logvec[logvecpos].iov_base = mempkt;
logvec[logvecpos].iov_len = rlen;
logvecpos++;
}
fprintf(stderr, "%s[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld msecs%s(%.*s %d) %d headers in %d bytes (%d async switches on async core %d)\n",
first_part,
uwsgi.mypid,
wsgi_req->app_id,
app_req,
uwsgi.workers[0].requests,
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
wsgi_req->remote_user_len, wsgi_req->remote_user,
wsgi_req->var_cnt,
wsgi_req->uh.pktsize,
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(uint64_t) wsgi_req->response_size,
(long int) (microseconds - microseconds2) / 1000,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
wsgi_req->status,
wsgi_req->header_cnt,
wsgi_req->headers_size,
wsgi_req->async_switches, wsgi_req->async_id);
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n",
(int) uwsgi.mypid,
wsgi_req->app_id,
app_req,
(unsigned long long ) uwsgi.workers[0].requests,
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
wsgi_req->remote_user_len, wsgi_req->remote_user,
wsgi_req->var_cnt,
wsgi_req->uh.pktsize,
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(unsigned long long) wsgi_req->response_size,
rt, tsize,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
wsgi_req->status,
wsgi_req->header_cnt,
(unsigned long long) wsgi_req->headers_size,
wsgi_req->switches, wsgi_req->async_id);
logvec[logvecpos].iov_base = logpkt;
logvec[logvecpos].iov_len = rlen;
// do not check for errors
rlen = writev(2, logvec, logvecpos+1);
}
void get_memusage() {
@@ -95,27 +138,27 @@ void get_memusage() {
int i;
procfile = fopen("/proc/self/stat", "r");
if (procfile) {
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", &uwsgi.workers[uwsgi.mywid].vsz_size, &uwsgi.workers[uwsgi.mywid].rss_size);
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &uwsgi.workers[uwsgi.mywid].rss_size);
if (i != 2) {
fprintf(stderr, "warning: invalid record in /proc/self/stat\n");
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
}
fclose(procfile);
}
uwsgi.workers[uwsgi.mywid].rss_size = uwsgi.workers[uwsgi.mywid].rss_size * uwsgi.page_size;
#elif defined (__sun__)
psinfo_t info;
int procfd ;
int procfd;
procfd = open("/proc/self/psinfo", O_RDONLY);
if (procfd >= 0) {
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024 ;
uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024 ;
uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024;
uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024;
}
close(procfd);
}
#elif defined( __APPLE__)
#elif defined(__APPLE__)
/* darwin documentation says that the value are in pages, but they are bytes !!! */
struct task_basic_info t_info;
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
@@ -128,7 +171,13 @@ void get_memusage() {
kvm_t *kv;
int cnt;
#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
if (kv) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
@@ -138,18 +187,33 @@ void get_memusage() {
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
}
#elif defined(__NetBSD__)
#elif defined(__NetBSD__) || defined(__OpenBSD__)
struct kinfo_proc2 *kproc2;
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
if (kproc2 && cnt > 0) {
#ifdef __OpenBSD__
uwsgi.workers[uwsgi.mywid].vsz_size = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
#else
uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
#endif
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
}
#endif
kvm_close(kv);
}
#elif defined(__HAIKU__)
area_info ai;
int32 cookie;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
uwsgi.workers[uwsgi.mywid].vsz_size += ai.ram_size;
if ( (ai.protection & B_WRITE_AREA) != 0) {
uwsgi.workers[uwsgi.mywid].rss_size += ai.ram_size;
}
}
#endif
}
+241
View File
@@ -0,0 +1,241 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct wsgi_request *threaded_current_wsgi_req() {
return pthread_getspecific(uwsgi.tur_key);
}
struct wsgi_request *simple_current_wsgi_req() {
return uwsgi.wsgi_req;
}
void uwsgi_register_loop(char *name, void *loop) {
if (uwsgi.loops_cnt >= MAX_LOOPS) {
uwsgi_log("you can define %d loops at max\n", MAX_LOOPS);
exit(1);
}
uwsgi.loops[uwsgi.loops_cnt].name = name;
uwsgi.loops[uwsgi.loops_cnt].loop = loop;
uwsgi.loops_cnt++;
}
void *uwsgi_get_loop(char *name) {
int i;
for (i = 0; i < uwsgi.loops_cnt; i++) {
if (!strcmp(name, uwsgi.loops[i].name)) {
return uwsgi.loops[i].loop;
}
}
return NULL;
}
void *simple_loop(void *arg1) {
long core_id = (long) arg1;
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
int i;
#ifdef UWSGI_THREADING
//PyThreadState *pts;
sigset_t smask;
if (uwsgi.threads > 1) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
}
}
#endif
// initialize the main event queue to monitor sockets
int main_queue = event_queue_init();
uwsgi_add_sockets_to_queue(main_queue);
if (uwsgi.signal_socket > -1) {
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(main_queue, wsgi_req)) {
continue;
}
if (wsgi_req_recv(wsgi_req)) {
uwsgi_destroy_request(wsgi_req);
continue;
}
uwsgi_close_request(wsgi_req);
}
// 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;
}
#ifdef UWSGI_ZEROMQ
void *zeromq_loop(void *arg1) {
sigset_t smask;
int i;
long core_id = (long) arg1;
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
uwsgi.zeromq_recv_flag = 0;
zmq_pollitem_t zmq_poll_items[3];
char uwsgi_signal;
if (uwsgi.threads > 1) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
if (tmp_zmq_pull == NULL) {
uwsgi_error("zmq_socket()");
exit(1);
}
if (zmq_connect(tmp_zmq_pull, uwsgi.zmq_receiver) < 0) {
uwsgi_error("zmq_connect()");
exit(1);
}
pthread_setspecific(uwsgi.zmq_pull, tmp_zmq_pull);
}
}
if (uwsgi.signal_socket > -1) {
zmq_poll_items[0].socket = pthread_getspecific(uwsgi.zmq_pull);
zmq_poll_items[0].fd = -1;
zmq_poll_items[0].events = ZMQ_POLLIN;
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;
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
wsgi_req_setup(wsgi_req, core_id, NULL);
uwsgi.edge_triggered = 1;
wsgi_req->socket = uwsgi.zmq_socket;
if (uwsgi.signal_socket > -1) {
if (zmq_poll(zmq_poll_items, 3, -1) < 0) {
uwsgi_error("zmq_poll()");
continue;
}
if (zmq_poll_items[1].revents & ZMQ_POLLIN) {
if (read(uwsgi.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[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);
}
}
else {
wsgi_req->poll.fd = wsgi_req->socket->proto_accept(wsgi_req, uwsgi.zmq_socket->fd);
}
if (wsgi_req->poll.fd >= 0) {
wsgi_req_recv(wsgi_req);
}
uwsgi_close_request(wsgi_req);
}
// end of the loop
return NULL;
}
#endif
+1381
View File
File diff suppressed because it is too large Load Diff
+259
View File
@@ -0,0 +1,259 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void master_check_cluster_nodes() {
int i;
for (i = 0; i < MAX_CLUSTER_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;
}
}
}
}
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;
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]);
}
}
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;
}
}
+22
View File
@@ -0,0 +1,22 @@
<unbit>
<pippo/>
<pluto>
ciao
ciao
</pluto>
<uwsgi id="unbit.it">
<http>:3333</http>
<module>trac.web.main:dispatch_request</module>
<pluto>ciao</pluto>
<env>TRAC_ENV=/root/uwsgi/utrac</env>
</uwsgi>
<uwsgi id="projects.unbit.it">
<http>:4444</http>
<module>trac.web.main:dispatch_request</module>
</uwsgi>
</unbit>
+26
View File
@@ -0,0 +1,26 @@
import uwsgi
import os
def application(env, start_response):
boundary = 'uwsgi_mjpeg_frame'
start_response('200 Ok', [
('Cache-Control', 'no-cache'),
('Cache-Control', 'private'),
('Pragma', 'no-cache'),
('Content-Type', 'multipart/x-mixed-replace; boundary=' + boundary),
]
)
yield "--%s\n" % boundary
while 1:
yield "Content-Type: image/jpeg\r\n\r\n"
uwsgi.sendfile('screenshot.jpg')
yield "--%s\n" % boundary
#os.system('./isightcapture -w 640 -h 480 screenshot.jpg')
#os.system('screencapture -m -T 1 screenshot.jpg')
+23
View File
@@ -0,0 +1,23 @@
use Mojolicious::Lite;
# /
get '/' => 'index';
# /*
get '/:groovy' => sub {
my $self = shift;
$self->render_text($self->param('groovy'), layout => 'funky');
};
app->start('psgi');
__DATA__
@@ index.html.ep
% layout 'funky';
Yea baby!
@@ layouts/funky.html.ep
<!doctype html><html>
<head><title>Funky!</title></head>
<body><%= content %></body>
</html>
+23
View File
@@ -0,0 +1,23 @@
main = Server(
uuid="f400bf85-4538-4f7a-8908-67e313d515c2",
access_log="/logs/access.log",
error_log="/logs/error.log",
chroot="./",
default_host="192.168.173.18",
name="test",
pid_file="/run/mongrel2.pid",
port=6767,
hosts = [
Host(name="192.168.173.18", routes={
'/': Handler(send_spec='tcp://192.168.173.18:9999',
send_ident='54c6755b-9628-40a4-9a2d-cc82a816345e',
recv_spec='tcp://192.168.173.18:9998', recv_ident='')
})
]
)
settings = {'upload.temp_store':'tmp/mongrel2.upload.XXXXXX'}
servers = [main]
uwsgi = { 'socket':':3031', 'master':'true'}

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