Compare commits

...
672 Commits
Author SHA1 Message Date
roberto@debian32 bb1ef28d69 updated decorators with @farm([name]) 2011-10-23 19:59:53 +02:00
roberto@debian32 1d5b05265d initial farm implementation 2011-10-23 19:18:31 +02:00
roberto@debian32 d9fef3c30e a little hack for psgi loader waiting for a truly agnostic init_uwsgi_app 2011-10-23 12:14:53 +02:00
roberto@debian32 e5dfb9efc3 improved get_memusage 2011-10-23 12:04:02 +02:00
roberto@debian32 02bab15e86 perl threading improvements 2011-10-23 11:49:25 +02:00
roberto@debian32 6f4ddead09 Added tag 1.0-rc2 for changeset 7a4e021ea7ba 2011-10-23 08:37:03 +02:00
roberto@gambit b361248ff6 fixed add_exported_opts 2011-10-23 08:35:15 +02:00
roberto@debian32 e9c42ceaa5 support for multiple values in options 2011-10-22 18:32:32 +02:00
roberto@debian32 5d7029744a PATH_INFO is correctly escaped in http modes 2011-10-22 09:35:01 +02:00
roberto@gambit 1084a3afa8 fixed mule patch loading 2011-10-20 10:38:59 +02:00
roberto@gambit ed254bffee fixed mule process name 2011-10-20 10:20:44 +02:00
roberto@djangocloud 733784d7dd another procname fix... 2011-10-19 16:13:10 +10:00
roberto@djangocloud cb5b26bcb4 another bunch of procname fixes 2011-10-19 14:26:07 +10:00
roberto@djangocloud 0065152bb1 daemons throttling subsystem 2011-10-18 18:53:22 +10:00
roberto@djangocloud 03266203fd another fix for environ 2011-10-18 18:30:13 +10:00
roberto@djangocloud 4a5f68f9d8 fixed environ 2011-10-18 18:12:39 +10:00
roberto@djangocloud 83e31a1c27 another setprocname fix 2011-10-18 16:20:33 +10:00
roberto@djangocloud 0efed5ef9c various emperor procname fixes 2011-10-18 16:15:06 +10:00
roberto@djangocloud cdfef1281d fixed another spooler compilation bug 2011-10-18 15:12:59 +10:00
roberto@debian32 e00907e142 --spooler-harakiri 2011-10-17 19:07:12 +02:00
roberto@app1 6dcbcf39e3 fixed compilation when spooler is disabled 2011-10-17 03:16:55 -05:00
roberto@debian32 044579a8e0 more verbose annihilation report 2011-10-16 11:16:13 +02:00
roberto@debian32 d2b52b4663 added uwsgi.setprocname() 2011-10-16 10:37:26 +02:00
roberto@debian32 7f75b2c02c added --procname and --procname-master 2011-10-16 10:18:45 +02:00
roberto@freebsd64 24a3f671e5 freebsd setproctitle 2011-10-16 10:06:08 +02:00
roberto@debian32 875100e3c8 check for mules before nuke 2011-10-16 09:58:37 +02:00
roberto@mrspurr 34bc7c0cfd check for procname 2011-10-16 09:54:35 +02:00
roberto@debian32 b39a10ff7c procname initial management 2011-10-16 09:45:41 +02:00
roberto@debian32 02331904de uWSGI 1.0-rc1 2011-10-15 08:47:00 +02:00
roberto@debian32 d1a4ae694e --locks 2011-10-15 08:32:32 +02:00
roberto@debian32 7a5ffc1124 --spooler-chdir 2011-10-14 19:20:05 +02:00
roberto@debian32 19c5bfb42c fixed a spooler signal bug spotted by Gabriele Giaccari 2011-10-14 18:32:17 +02:00
roberto@debian32 893bf3686b fixed a wrong typecast 2011-10-14 10:58:02 +02:00
roberto@debian32 e54fa9bcd4 added --emperor-stats 2011-10-13 07:53:32 +02:00
roberto@debian32 c1eb5ab0fe prepare for emperor-stats 2011-10-12 06:51:49 +02:00
roberto@mrspurr 461914dde4 completed --evil-reload options 2011-10-12 06:48:52 +02:00
roberto@debian32 85662578e4 implemented --mule-harakiri 2011-10-12 01:48:30 +02:00
roberto@debian32 a59c0ae795 setlinebuf in syslog mode 2011-10-12 00:54:18 +02:00
roberto@debian32 3a860155ee added --evil-reload-on-as and --evil-reload-on-rss 2011-10-11 20:39:00 +02:00
roberto@debian32 27553c2967 prepare for --evil-reload-... options 2011-10-11 20:18:31 +02:00
roberto@colossus 9a8ac9af3c added uwsgi.mule_id() 2011-10-11 07:31:41 +02:00
roberto@debian32 2f5daffe99 use hggit for better github sync 2011-10-09 09:11:54 +02:00
roberto@debian32 75cd31dce4 better spooler error reporting 2011-10-07 03:30:16 +02:00
roberto@colossus f7150d1b41 fixed mule socketpair 2011-10-06 18:37:24 +02:00
roberto@debian32 d6a6b65338 added --log-x-forwarded-for 2011-10-06 06:42:31 +02:00
roberto@freebsd64 979f6027b4 ignore SIGPIPE by default 2011-10-05 20:45:55 +02:00
roberto@freebsd64 7dc059c75b completed new freebsd64 sendfiel async support 2011-10-05 20:34:25 +02:00
roberto@freebsd64 b639b5974f better freebsd sendfile support 2011-10-05 20:19:12 +02:00
roberto@netbsd64 0de08c553c fixed a potential overflow 2011-10-05 21:16:28 +02:00
roberto@freebsd64 80788ac695 freebsd event fix 2011-10-05 19:01:29 +02:00
roberto@freebsd64 1494c621c1 non-linux fix 2011-10-05 18:43:53 +02:00
roberto@debian32 605e5b5173 export listen_queue size in stats 2011-10-05 17:24:46 +02:00
roberto@debian32 4cf2213051 added --log-truncate --log-reopen --log-maxsize --log-backupname 2011-10-05 11:58:15 +02:00
roberto@debian32 3aa36668e5 better error reporting 2011-10-04 20:28:08 +02:00
roberto@debian32 1c0b5b42e9 support for multiple --touch-reload options 2011-10-04 19:40:09 +02:00
roberto@openindiana64 702dc44fad fixed openindiana build on 64bit 2011-10-03 15:46:04 +02:00
roberto@solrisexpress 2cae07aa52 fixed 64bit compilation 2011-10-03 09:37:32 +00:00
roberto@ebian32 b5616ff25c completed mule signal handling 2011-10-03 08:36:21 +02:00
roberto@debian32 b7b7521975 refactored fds closing and socketpair 2011-10-03 08:29:19 +02:00
roberto@debian32 dce3263ee3 added mule messaging subsystem 2011-10-03 07:45:18 +02:00
roberto@debian32 9796e05ca1 added support for X_FORWARDED_SSL in http parser 2011-10-03 06:38:14 +02:00
roberto@debian32 5cc0d459ec struct uwsgi_server is becoming huge, better to add some comment 2011-10-02 20:45:03 +02:00
roberto@debian32 531a850a71 first almost-working commit for uWSGI mules 2011-10-02 20:05:31 +02:00
roberto@debian32 4c36280287 support --manage-script-name in http socket mode 2011-09-30 12:32:31 +02:00
roberto@debian32 70be8eb55e restored setup.py 2011-09-30 10:55:12 +02:00
roberto@debian32 f8b757b21e print argv in setup.py 2011-09-30 10:39:22 +02:00
roberto@debian32 3a63d352bb print envs in setup.py 2011-09-30 10:36:30 +02:00
roberto@sirius 60467705c5 fixed a stupid bug 2011-09-30 10:31:00 +02:00
roberto@debian32 eada0c09e0 refactored placeholder management 2011-09-30 10:21:26 +02:00
roberto@debian32 8e851aa6a1 fixed egg 2011-09-30 09:56:51 +02:00
roberto@debian32 eaf7bb967d added a check for http (3) 2011-09-30 09:43:42 +02:00
roberto@debian32 7be45c77b1 added a check for http (2) 2011-09-30 09:42:19 +02:00
roberto@debian32 5e2b460dc8 added a check for http (2) 2011-09-30 09:24:33 +02:00
roberto@debian32 16143e698f added a check for http 2011-09-30 09:21:12 +02:00
roberto@debian32 4259946e3b second little typecast fix 2011-09-30 08:51:18 +02:00
roberto@debian32 0a750d76ee little typecast fix 2011-09-30 08:50:00 +02:00
roberto@debian32 e4a9f5f0dd merge 2011-09-28 20:21:11 +02:00
roberto@debian32 d5b7698f89 added --stats 2011-09-28 20:20:40 +02:00
roberto@sirius a481e8508e added .gitignore 2011-09-28 17:23:22 +02:00
roberto@debian32 a53b57497b close bug #47 2011-09-28 07:27:43 +02:00
roberto@debian32 d871357b2d added uwsgi_req_error 2011-09-25 16:16:08 +02:00
roberto@debian32 2d57db55f4 removed a useless error checking 2011-09-25 14:06:06 +02:00
roberto@debian32 bae45ce03a error checking in uwsgi proto writer 2011-09-25 14:01:06 +02:00
roberto@debian32 44cc4336f1 added posix capability support 2011-09-25 13:41:10 +02:00
roberto@debian32 44f6e214fd improved uwsgi.queue_last 2011-09-25 10:44:19 +02:00
roberto@debian32 3e46f81d2b use PyLong_FromUnsignedLongLong 2011-09-25 06:42:23 +02:00
roberto@debian32 e4532b9a50 added memory usage in uwsgicc 2011-09-24 09:07:34 +02:00
roberto@debian32 2694be562c fixed respawn_count 2011-09-24 08:28:19 +02:00
roberto@debian32 fadb9edd7f added running time and avg_rt to uwsgicc 2011-09-24 08:24:51 +02:00
roberto@debian32 d85e0790de added response_time and running_time statistics 2011-09-24 06:40:30 +02:00
roberto@debian32 bc46c4d704 python3 fix 2011-09-23 08:36:28 +02:00
roberto@centos64 a73a010188 fixed build system for older gcc releases 2011-09-23 08:33:15 +02:00
roberto@debian3 4e8c8ef317 improved screen support 2011-09-21 06:09:05 +02:00
roberto@debian32 e402e7805d no need to set pty, screen is much metter 2011-09-21 05:27:58 +02:00
roberto@debian32 302b8f026b --cheaper improvement 2011-09-19 10:15:24 +02:00
roberto@debian32 630054b72a better wakeup of workers 2011-09-19 07:53:51 +02:00
roberto@debian32 a05f459b2b preliminary cheaper implementation 2011-09-19 07:13:45 +02:00
roberto@debian32 207979580a added uwsgi.extract 2011-09-18 07:04:36 +02:00
roberto@debian32 f69526f8bf parse plugin-specific options 2011-09-18 06:57:19 +02:00
roberto@debian32 e249d567a1 --fastrouter-cheap 2011-09-16 15:14:08 +02:00
roberto@debian32 a23ba653da better shared sockets support 2011-09-16 07:46:45 +02:00
roberto@debian32 0644d53572 set pty to raw mode 2011-09-13 08:35:50 +02:00
roberto@debian32 f58f51294d fixed sendfile typecasting 2011-09-11 07:41:42 +02:00
roberto@debian32 86194eb93e GC in symzipimporter is useless 2011-09-11 07:33:23 +02:00
roberto@debian32 0a89f375e6 added charles as contributor 2011-09-11 06:55:27 +02:00
roberto@debian32 6282178b3c fixed python optimize flag 2011-09-11 06:42:45 +02:00
roberto@debian32 8e14d68022 merge 2011-09-10 17:28:40 +02:00
roberto@debian32 e86bd0c070 preliminary support for detachable pyshell 2011-09-10 17:28:01 +02:00
roberto@mrspurr bf991f8892 report gb objects in welcome.py 2011-09-10 11:03:39 +02:00
roberto@mrspurr b341678d20 another symzip fix 2011-09-10 10:58:37 +02:00
roberto@mrspurr 5f59365d88 symzip GC fix 2011-09-10 10:54:27 +02:00
roberto@debian32 5130a7bb33 moved the old 'j' to 'J' option 2011-09-09 20:36:00 +02:00
roberto@dexter cc84a596d6 better iso99 check 2011-09-09 18:44:18 +02:00
roberto@longshot e67bed431a a fix for older gcc 2011-09-09 18:43:08 +02:00
roberto@dexter 72613a9f48 mime type optimization 2011-09-09 18:35:29 +02:00
roberto@sirius c048ea0615 better mimetype file check 2011-09-09 18:14:53 +02:00
roberto@dexter 957ca1b7ed added mime types support in static file serving 2011-09-09 17:06:35 +02:00
roberto@ebian32 d80a6df039 fixed a threading bug 2011-09-09 10:00:09 +02:00
roberto@mrspurr 94f9bd9d91 added Corey as contributor 2011-09-09 08:53:37 +02:00
roberto@mrspurr b480efe672 fixed script_name handling 2011-09-09 08:42:31 +02:00
roberto@mrspurr 4fc306d979 added a new debug entry 2011-09-09 08:32:20 +02:00
roberto@mrspurr 56abccbdeb another fix for urack.rb 2011-09-08 19:59:37 +02:00
roberto@mrspuur f218af0735 clang fixes 2011-09-08 19:45:46 +02:00
roberto@mrspurr 9b69c62780 automagic bundler in urack.rb 2011-09-08 13:44:50 +02:00
roberto@dexter eb5d67e07f 1.0 is better than 1.0.0 2011-09-07 16:09:45 +02:00
roberto@sirius e7391987b1 fixed sandboxviolation on osx 2011-09-07 12:33:12 +02:00
roberto@sirius 02cbe15575 test3 2011-09-07 12:32:02 +02:00
roberto@sirius a5a657f0d4 a second test 2011-09-07 12:29:24 +02:00
roberto@sirius 67567c86e0 a test 2011-09-07 12:27:47 +02:00
roberto@dexter 445d02da45 make easy_install happy 2011-09-06 17:58:02 +02:00
roberto@debian32 4a05df41ce subscription logging 2011-09-05 16:26:25 +02:00
roberto@debian32 5c0c2f6b45 yaml fix 2011-09-05 08:12:12 +02:00
roberto@debian32 0ab55fef46 added support for regexp in UWSGI_APPID 2011-09-04 21:33:30 +02:00
roberto@debian32 dd344bfe38 fixed a bug in multiapp mode 2011-09-04 18:01:04 +02:00
roberto@debian32 e92a889bcc refactored UWSGI_PY_READLINE_BUFSIZE 2011-09-03 07:15:51 +02:00
roberto@debian32 419d656a83 1.0.0-dev cycle started 2011-08-31 14:27:21 +02:00
roberto@debian32 3c3d58bfe9 pypyuwsgi.py 2011-08-31 14:01:46 +02:00
roberto@debian32 1989099cc5 preliminary pypy support 2011-08-31 13:18:32 +02:00
roberto@sirius 1446e3f0a9 allows pyuwsgi in osx 2011-08-31 12:09:56 +02:00
roberto@debian32 00fc31289d a pyuwsgi fix 2011-08-31 12:06:26 +02:00
roberto@sirius 2c463ad6af a test for libless pyuwsgi 2011-08-31 12:02:19 +02:00
roberto@sirius e641ae05c4 pyuwsgi 2011-08-31 11:42:22 +02:00
roberto@debian32 a13e0075ee fixed virtualhosting in fully-dynamic mode 2011-08-31 07:55:34 +02:00
roberto@debian32 e617a7b88e added an example for the new fd-based config 2011-08-30 12:08:22 +02:00
roberto@debian32 cbdeb4caad --stop and --reload, open by fifo and fd 2011-08-30 10:51:50 +02:00
roberto@sirius 59314d692f uWSGI 0.9.9 2011-08-29 17:32:08 +02:00
roberto@sirius 3dfa56b279 Added tag 0.9.9 for changeset 376ffd8f1906 2011-08-29 17:26:31 +02:00
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
226 changed files with 24409 additions and 6895 deletions
+4
View File
@@ -0,0 +1,4 @@
syntax: glob
*.o
*.pyc
+21
View File
@@ -13,3 +13,24 @@ ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
+16
View File
@@ -0,0 +1,16 @@
- 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
Corey Farwell
Charles Duffy
+234
View File
@@ -1,5 +1,239 @@
*** 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>)
+3
View File
@@ -1,2 +1,5 @@
all:
python uwsgiconfig.py --build
clean:
python uwsgiconfig.py --clean
+76 -52
View File
@@ -51,7 +51,6 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
#include <fcntl.h>
#define MAX_VARS 64
#define DEFAULT_SOCK "/tmp/uwsgi.sock"
typedef struct {
@@ -73,6 +72,7 @@ typedef struct {
char script_name[256];
char scheme[9];
int cgi_mode ;
int max_vars;
} uwsgi_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
@@ -83,8 +83,18 @@ static uint16_t uwsgi_swap16(uint16_t x) {
}
#endif
static int uwsgi_add_var(struct iovec *vec, int i, char *key, char *value, uint16_t *pkt_size) {
static int uwsgi_add_var(struct iovec *vec, int i, request_rec *r, char *key, char *value, uint16_t *pkt_size) {
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
#if APR_IS_BIGENDIAN
if (i+6 > c->max_vars) {
#else
if (i+4 > c->max_vars) {
#endif
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: max number of uwsgi variables reached. consider increasing it with uWSGImaxVars directive");
return i;
}
#if APR_IS_BIGENDIAN
char *ptr;
@@ -150,6 +160,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;
@@ -315,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->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
if (c->scheme[0] != 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
}
if (c->script_name[0] == '/') {
if (c->script_name[1] == 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
}
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);
@@ -388,7 +385,7 @@ static int uwsgi_handler(request_rec *r) {
*cp = toupper(*cp);
}
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, penv, h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, penv, h[i].val, &pkt_size) ;
}
}
}
@@ -397,7 +394,7 @@ static int uwsgi_handler(request_rec *r) {
headers = apr_table_elts(r->subprocess_env);
h = (apr_table_entry_t*) headers->elts;
for (i = 0; i < headers->nelts; ++i) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, h[i].key, h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, h[i].key, h[i].val, &pkt_size) ;
}
@@ -418,11 +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;
}
@@ -434,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;
}
}
@@ -458,6 +458,7 @@ static int uwsgi_handler(request_rec *r) {
if (cnt == 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
@@ -467,6 +468,7 @@ static int uwsgi_handler(request_rec *r) {
if (errno != ECONNRESET) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else {
@@ -489,6 +491,7 @@ static int uwsgi_handler(request_rec *r) {
if (r->connection->aborted) {
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
@@ -508,6 +511,7 @@ static int uwsgi_handler(request_rec *r) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -521,6 +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;
}
}
@@ -528,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) ;
}
@@ -564,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 ;
@@ -707,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}
};
+96 -26
View File
@@ -2,6 +2,10 @@
extern struct uwsgi_server uwsgi;
struct wsgi_request *find_wsgi_req_proto_by_fd(int fd) {
return uwsgi.async_proto_fd_table[fd];
}
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
return uwsgi.async_waiting_fd_table[fd];
}
@@ -195,14 +199,23 @@ void *async_loop(void *arg1) {
int interesting_fd, i;
struct uwsgi_rb_timer *min_timeout;
int timeout;
int is_a_new_connection;
int proto_parser_status;
time_t now, last_now = 0;
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
void *events = event_queue_alloc(64);
struct uwsgi_socket *uwsgi_sock;
uwsgi.async_runqueue = NULL;
uwsgi.async_runqueue_cnt = 0;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
}
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
@@ -235,49 +248,105 @@ void *async_loop(void *arg1) {
async_expire_timeouts();
}
for(i=0;i<uwsgi.async_nevents;i++) {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
// new request coming in
if (interesting_fd == uwsgi.sockets[0].fd) {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
uwsgi_log("async queue is full !!!\n");
continue;
}
is_a_new_connection = 0;
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
// 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
continue;
}
#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.sockets[0].arg) < 0) {
uwsgi_error("fcntl()");
continue;
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 (wsgi_req_simple_recv(uwsgi.wsgi_req)) {
if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
runqueue_push(uwsgi.wsgi_req);
}
break;
}
uwsgi_sock = uwsgi_sock->next;
}
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;
}
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
}
else {
// app event
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
// unknown fd, remove it (for safety)
@@ -320,10 +389,11 @@ void *async_loop(void *arg1) {
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) {
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
+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"))
+3
View File
@@ -0,0 +1,3 @@
import uwsgi
print uwsgi.extract("data://0")
+1
View File
@@ -0,0 +1 @@
object file for embedded files will be put here
+12 -1
View File
@@ -2,6 +2,9 @@
xml = true
ini = true
yaml = true
json = auto
sqlite3 = auto
zeromq = auto
snmp = true
sctp = false
spooler = true
@@ -18,16 +21,24 @@ 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, nagios, rpc, fastrouter, http, ugreen
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 = 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
+4 -32
View File
@@ -1,33 +1,5 @@
[uwsgi]
xml = true
ini = 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 = true
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins = python, ping, rack
bin_name = uwsgi
plugin_dir = .
embedded_plugins =
[python]
paste = true
web3 = true
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
-4
View File
@@ -1,7 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,lua
[python]
paste = true
web3 = true
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = symcall
as_shared_library = true
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = pyuwsgi.so
embedded_plugins = pyuwsgi,python,ping,cache,nagios,rpc,ugreen
as_shared_library = true
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = rack, ping, nagios, rpc
embedded_plugins = rack, ping, cache, nagios, rpc, fastrouter, http, ugreen
+13 -1
View File
@@ -2,6 +2,9 @@
xml = true
ini = true
yaml = true
json = true
sqlite3 = true
zeromq = false
snmp = false
sctp = false
spooler = true
@@ -10,14 +13,23 @@ udp = true
multicast = false
threading = true
sendfile = true
nagios = false
minterpreters = true
async = true
evdis = false
ldap = true
pcre = false
debug = false
unbit = true
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
plugins =
bin_name = /opt/unbit/bin/uwsgi
append_version = unbit
plugin_dir = /opt/unbit/uwsgi_plugins
embedded_plugins =
locking = auto
event = auto
timer = auto
filemonitor = auto
+2
View File
@@ -1,4 +1,6 @@
[uwsgi]
inherit = unbit
json = false
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
+226 -92
View File
@@ -2,6 +2,98 @@
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;
@@ -39,19 +131,19 @@ struct uwsgi_subscriber_name *uwsgi_get_subscriber(struct uwsgi_dict *udict, cha
return ret;
}
void uwsgi_add_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *address, uint64_t address_len) {
void uwsgi_add_subscriber(struct uwsgi_dict *udict, struct uwsgi_subscribe_req *usr) {
char *ptr;
uint64_t vallen = 0;
struct uwsgi_subscriber *usub, nusub;
int found = 0;
int i;
ptr = uwsgi_dict_get(udict, key, keylen, &vallen);
ptr = uwsgi_dict_get(udict, usr->key, usr->keylen, &vallen);
if (ptr && vallen) {
usub = (struct uwsgi_subscriber *) ptr;
for(i=0;i<(int)usub->nodes;i++) {
if (!uwsgi_strncmp(usub->names[i].name, usub->names[i].len, address, address_len)) {
if (!uwsgi_strncmp(usub->names[i].name, usub->names[i].len, usr->address, usr->address_len)) {
found = 1;
break;
}
@@ -65,19 +157,29 @@ void uwsgi_add_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen,
break;
}
}
usub->names[found].len = address_len;
memcpy(usub->names[found].name, address, address_len);
usub->names[found].len = usr->address_len;
usub->names[found].modifier1 = usr->modifier1;
usub->names[found].modifier2 = usr->modifier2;
memcpy(usub->names[found].name, usr->address, usr->address_len);
if (found == (int) usub->nodes) {
usub->nodes++;
}
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
udict->count++;
}
return;
}
else {
nusub.nodes = 1;
nusub.current = 0;
memcpy(nusub.names[0].name, address, address_len);
uwsgi_dict_set(udict, key, keylen, (char *) &nusub, sizeof(struct uwsgi_subscriber));
memcpy(nusub.names[0].name, usr->address, usr->address_len);
nusub.names[0].len = 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));
uwsgi_log("[uwsgi-subscription] new pool: %.*s\n", usr->keylen, usr->key);
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
udict->count++;
}
}
@@ -416,6 +518,16 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
uci->prev = last_index;
}
}
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = &uwsgi.cache_items[index] ;
if (expires) {
expires += time(NULL);
uci->expires = expires;
}
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
uci->valsize = vallen;
ret = 0;
}
end:
return ret;
@@ -487,102 +599,124 @@ end:
}
/* THIS PART IS HEAVILY OPTIMIZED: PERFORMANCE NOT ELEGANCE !!! */
void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
void *cache_thread_loop(void *fd_ptr) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) data;
uint64_t tmp_vallen = 0;
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;
if (vallen > 0) {
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && tmp_vallen > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen);
}
ctl_poll.events = POLLIN;
}
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && vallen > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen);
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;
}
else {
wsgi_req->response_size = write(wsgi_req->poll.fd, "HTTP/1.0 404 Not Found\r\n\r\n<h1>Not Found</h1>", 44);
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()");
}
}
}
}
int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uint64_t vallen = 0;
char *value;
char *argv[3];
uint8_t argc = 0;
switch(wsgi_req->uh.modifier2) {
case 0:
// get
if (wsgi_req->uh.pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh.pktsize = vallen;
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
wsgi_req->response_size += write(wsgi_req->poll.fd, value, vallen);
}
}
break;
case 1:
// set
if (wsgi_req->uh.pktsize > 0) {
argc = 3;
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
if (argc > 1) {
uwsgi_cache_set(argv[0], strlen(argv[0]), argv[1], strlen(argv[1]), 0, 0);
}
}
}
break;
case 2:
// del
if (wsgi_req->uh.pktsize > 0) {
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
}
break;
case 3:
case 4:
// dict
if (wsgi_req->uh.pktsize > 0) {
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh.pktsize, cache_command, (void *) wsgi_req);
}
break;
case 5:
// get (uwsgi + stream)
if (wsgi_req->uh.pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
wsgi_req->response_size += write(wsgi_req->poll.fd, value, vallen);
}
else {
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
}
}
break;
clear:
close(ctl_poll.fd);
}
return 0;
return NULL;
}
struct uwsgi_plugin uwsgi_cache_plugin = {
int uwsgi_cache_server(char *socket, int threads) {
.name = "cache",
.modifier1 = 111,
.request = uwsgi_cache_request,
int *fd = uwsgi_malloc(sizeof(int));
int i;
pthread_t thread_id;
char *tcp_port = strchr(socket, ':');
if (tcp_port) {
*fd = bind_to_tcp(socket, uwsgi.listen_queue, tcp_port);
}
else {
*fd = bind_to_unix(socket, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
};
pthread_mutex_init(&uwsgi.cache_server_lock, NULL);
if (threads < 1) threads = 1;
uwsgi_log("*** cache-optimized server enabled on fd %d (%d threads) ***\n", *fd, threads);
for(i=0;i<threads;i++) {
pthread_create(&thread_id, NULL, cache_thread_loop, (void *) fd);
}
return *fd;
}
+25
View File
@@ -0,0 +1,25 @@
require 'stringio'
hello = proc do |signum|
puts "Hello i am signal #{signum}"
end
file_changed = proc do |signum|
puts "/tmp has been modified"
end
UWSGI.register_signal(17, '', hello)
UWSGI.register_signal(30, '', file_changed)
UWSGI.add_rb_timer(17 , 2)
UWSGI.add_timer(17 , 1)
UWSGI.add_file_monitor(30 , '/tmp')
puts UWSGI.signal_registered(1)
puts UWSGI.signal_registered(17)
run lambda { |env|
puts env.inspect
UWSGI.signal(17)
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World!\n")]
}
+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)
+3 -1
View File
@@ -12,4 +12,6 @@ env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --no-orphans avoid workers without master
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -m simple_app --logto $LOGTO -M -p 4
# --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
+4
View File
@@ -1,5 +1,9 @@
require 'rubygems'
require 'socket'
begin
require 'bundler/setup'
rescue LoadError
end
require 'rack'
require 'rack/content_length'
require 'rack/rewindable_input'
+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
}
+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()
+4 -3
View File
@@ -14,10 +14,11 @@ def index(request):
w['load'] = (100 * (w['running_time']/1000))/total_load
w['last_spawn_str'] = time.ctime(w['last_spawn'])
spooler_jobs = uwsgi.spooler_jobs()
jobs = []
for j in spooler_jobs:
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
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),
+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)
+642 -99
View File
@@ -5,29 +5,98 @@
extern struct uwsgi_server uwsgi;
extern char **environ;
int emperor_queue;
char *emperor_absolute_dir;
void emperor_send_stats(int);
struct uwsgi_instance {
struct uwsgi_instance *ui_prev;
struct uwsgi_instance *ui_next;
struct uwsgi_instance *ui_prev;
struct uwsgi_instance *ui_next;
char name[0xff];
pid_t pid ;
char name[0xff];
pid_t pid;
int status;
time_t born;
time_t last_mod;
int status;
time_t born;
time_t last_mod;
time_t last_loyal;
uint64_t respawns;
uint64_t respawns;
int use_config;
int pipe[2];
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) {
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
if (!strcmp(c_ui->name, name)) {
@@ -50,8 +119,25 @@ void emperor_del(struct uwsgi_instance *c_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);
}
@@ -71,44 +157,93 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
// reload the uWSGI instance
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
}
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->respawns++;
c_ui->last_mod = mod;
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(char *name, time_t born) {
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[4];
char *uef ;
pid_t pid;
char **vassal_argv;
char *uef;
char **uenvs;
int counter;
char *colon = NULL;
int i;
while(c_ui->ui_next) {
c_ui = c_ui->ui_next;
}
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) {
@@ -118,11 +253,40 @@ void emperor_add(char *name, time_t born) {
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)) {
@@ -131,10 +295,19 @@ void emperor_add(char *name, time_t born) {
}
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) {
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
char *ne = uwsgi_concat2("UWSGI_", *uenvs+13);
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
@@ -156,24 +329,78 @@ void emperor_add(char *name, time_t born) {
// 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;
}
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
argv[0] = uwsgi.binary_path;
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";
argv[2] = name;
argv[3] = NULL;
vassal_argv[0] = uwsgi.binary_path;
if (uwsgi.emperor_broodlord) {
colon = strchr(name, ':');
if (colon) {
colon[0] = 0;
}
}
if (!strcmp(name + (strlen(name) - 4), ".xml"))
vassal_argv[1] = "--xml";
if (!strcmp(name + (strlen(name) - 4), ".ini"))
vassal_argv[1] = "--ini";
if (!strcmp(name + (strlen(name) - 4), ".yml"))
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 3), ".js"))
vassal_argv[1] = "--json";
if (colon) {
colon[0] = ':';
}
vassal_argv[2] = name;
counter = 3;
uct = uwsgi.vassals_templates;
while(uct) {
vassal_argv[counter] = "--inherit";
vassal_argv[counter+1] = uct->filename;
counter+=2;
uct = uct->next;
}
vassal_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)) {
if (execvp(vassal_argv[0], vassal_argv)) {
uwsgi_error("execvp()");
}
uwsgi_log("is the uwsgi binary in your system PATH ?\n");
// never here
exit(1);
exit(UWSGI_EXILE_CODE);
}
clear:
clear:
free(n_ui);
c_ui->ui_next = NULL;
@@ -196,28 +423,101 @@ void emperor_loop() {
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];
uwsgi.emperor_stats_fd = -1;
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));
uwsgi_log("*** starting uWSGI Emperor ***\n");
if (!glob(uwsgi.emperor_dir, GLOB_MARK, 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);
}
}
emperor_queue = event_queue_init();
events = event_queue_alloc(64);
if (uwsgi.has_emperor) {
uwsgi_log("*** starting uWSGI sub-Emperor ***\n");
}
else {
uwsgi_error("glob()");
exit(1);
uwsgi_log("*** starting uWSGI Emperor ***\n");
}
if (uwsgi.emperor_stats) {
char *tcp_port = strchr(uwsgi.emperor_stats, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
uwsgi.emperor_stats_fd = bind_to_tcp(uwsgi.emperor_stats, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
uwsgi.emperor_stats_fd = bind_to_unix(uwsgi.emperor_stats, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
event_queue_add_fd_read(emperor_queue, uwsgi.emperor_stats_fd);
uwsgi_log("*** Emperor stats server enabled on %s fd: %d ***\n", uwsgi.emperor_stats, uwsgi.emperor_stats_fd);
}
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;
for(;;) {
int freq = 0 ;
for (;;) {
if (!i_am_alone) {
@@ -227,122 +527,365 @@ void emperor_loop() {
}
}
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 if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1) {
if (interesting_fd == uwsgi.emperor_stats_fd) {
emperor_send_stats(uwsgi.emperor_stats_fd);
}
}
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")
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 (strlen(de->d_name) >= 0xff)
continue;
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
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);
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, NULL, &g)) {
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])-5), ".yaml")
) {
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 (strlen(g.gl_pathv[i]) >= 0xff)
continue;
if (stat(g.gl_pathv[i], &st)) continue;
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode)) continue;
if (!S_ISREG(st.st_mode))
continue;
ui_current = emperor_get(g.gl_pathv[i]);
ui_current = emperor_get(g.gl_pathv[i]);
if (ui_current) {
// 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);
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;
}
}
}
else {
emperor_add(g.gl_pathv[i], st.st_mtime);
}
}
// 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;
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;
if (ui_current->pid == diedpid) {
if (ui_current->status == 0) {
// respawn an accidentally dead instance
emperor_add(ui_current->name, ui_current->last_mod);
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;
}
}
else if (ui_current->status == 1) {
emperor_del(ui_current);
break;
}
else if (stat(ui_current->name, &st)) {
emperor_stop(ui_current);
}
}
}
sleep(3);
}
}
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
void emperor_send_stats(int fd) {
struct sockaddr_un client_src;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
stats_send("\"emperor\": \"%s\",\n", uwsgi.emperor_dir);
fprintf(output,"\"emperor_tyrant\": %d,\n", uwsgi.emperor_tyrant);
fprintf(output, "\"vassals\": [\n");
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
fprintf(output,"\t{");
stats_send("\"id\": \"%s\", ", c_ui->name);
fprintf(output,"\"pid\": %d, ", (int) c_ui->pid);
stats_send_llu( "\"born\": %llu, ", c_ui->born);
stats_send_llu( "\"last_mod\": %llu, ", c_ui->last_mod);
fprintf(output,"\"loyal\": %d, ", c_ui->loyal);
fprintf(output,"\"zerg\": %d, ", c_ui->zerg);
fprintf(output,"\"uid\": %d, ", (int)c_ui->uid);
fprintf(output,"\"gid\": %d, ", (int)c_ui->gid);
stats_send_llu( "\"respawns\": %llu ", c_ui->respawns);
c_ui = c_ui->ui_next;
if (c_ui) {
fprintf(output,"},\n");
}
else {
fprintf(output,"}\n");
}
}
fprintf(output,"]}\n");
fclose(output);
}
+19 -7
View File
@@ -81,7 +81,7 @@ void *event_queue_alloc(int 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 (long) pe[id].portev_user;
}
return (int) pe[id].portev_object;
@@ -149,7 +149,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
*interesting_fd = (int) pe.portev_user;
*interesting_fd = (long) pe.portev_user;
}
else {
*interesting_fd = (int) pe.portev_object;
@@ -327,11 +327,13 @@ int event_queue_fd_write_to_read(int eq, int fd) {
struct kevent kev;
#ifndef __FreeBSD__
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;
}
#endif
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
@@ -476,7 +478,7 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
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)) {
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) (long) fmon_id)) {
uwsgi_error("port_associate()");
return -1;
}
@@ -506,7 +508,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
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)) {
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)(long)id)) {
uwsgi_error("port_associate()");
return NULL;
}
@@ -591,7 +593,9 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
*id = inotify_add_watch(ifd, filename, IN_ATTRIB|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MODIFY|IN_MOVE_SELF|IN_MOVED_FROM|IN_MOVED_TO);
#ifdef UWSGI_DEBUG
uwsgi_log("added watch %d for filename %s\n", *id, filename);
#endif
if (add_to_queue) {
return event_queue_add_fd_read(eq, ifd);
@@ -630,7 +634,9 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
}
else {
items = isize/(sizeof(struct inotify_event));
#ifdef UWSGI_DEBUG
uwsgi_log("inotify returned %d items\n", items);
#endif
for(j=0;j<items;j++) {
iie = &bie[j];
for(i=0;i<ushared->files_monitored_cnt;i++) {
@@ -683,13 +689,21 @@ enum
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
@@ -761,7 +775,7 @@ int event_queue_add_timer(int eq, int *id, int sec) {
timer_id++;
pnotif.portnfy_port = eq;
pnotif.portnfy_user = (void *) timer_id;
pnotif.portnfy_user = (void *) (long) timer_id;
sigev.sigev_notify = SIGEV_PORT;
sigev.sigev_value.sival_ptr = &pnotif;
@@ -816,8 +830,6 @@ int event_queue_add_timer(int eq, int *id, int sec) {
*id = timer_id ;
timer_id++;
uwsgi_log("registering timer %d\n", sec);
EV_SET(&kev, *id, EVFILT_TIMER, EV_ADD, 0, sec*1000, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
+7
View File
@@ -0,0 +1,7 @@
use POSIX;
open CONFIG,'welcome.ini';
dup2(fileno(CONFIG), 17);
exec './uwsgi','--ini','fd://17';
+27 -1
View File
@@ -2,10 +2,36 @@ require 'fiber'
class SuspendingBody
def each
for i in 1..10
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
+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()
+15 -4
View File
@@ -47,7 +47,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
}
}
gw_pid = fork();
gw_pid = uwsgi_fork(name);
if (gw_pid < 0) {
uwsgi_error("fork()");
return NULL;
@@ -60,6 +60,11 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
uwsgi_error("prctl()");
}
#endif
if (!uwsgi.sockets) {
// wait for child end
//waitpid(-1, &i, 0);
}
loop();
// never here !!! (i hope)
exit(1);
@@ -85,7 +90,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
ug->loop = loop;
ug->num = num;
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
uwsgi.gateways_cnt++;
@@ -98,7 +103,7 @@ void gateway_respawn(int id) {
pid_t gw_pid;
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
gw_pid = fork();
gw_pid = uwsgi_fork(ug->name);
if (gw_pid < 0) {
uwsgi_error("fork()");
return;
@@ -117,6 +122,12 @@ void gateway_respawn(int id) {
}
ug->pid = gw_pid;
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
ug->respawns++;
if (ug->respawns == 1) {
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
else {
uwsgi_log( "respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
}
+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>"
+21 -2
View File
@@ -67,6 +67,11 @@ char *ini_get_line(char *ini, off_t size) {
}
}
// check if it is a stupid file without \n at the end
if (ptr > ini) {
return ptr;
}
return NULL;
}
@@ -87,7 +92,14 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
char *section_asked = "uwsgi";
char *colon;
colon = uwsgi_get_last_char(file, ':');
if (uwsgi_check_scheme(file)) {
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) {
@@ -95,7 +107,9 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
}
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
if (file[0] != 0) {
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
}
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
@@ -136,6 +150,11 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
if (colon) {
colon[0] = ':';
}
}
#endif
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>it.unbit.uwsgi.emperor</string>
<key>ProgramArguments</key>
<array>
<string>/Users/roberta/uwsgi/uwsgi</string>
<string>--emperor</string>
<string>/Users/*/Library/uwsgi/*.{xml,ini,yml,yaml,js}</string>
</array>
</dict>
</plist>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>it.unbit.uwsgi</string>
<key>ProgramArguments</key>
<array>
<string>/Users/roberta/uwsgi/uwsgi</string>
<string>--socket</string>
<string>:3032</string>
<string>--module</string>
<string>welcome</string>
<string>--master</string>
<string>--die-on-term</string>
</array>
</dict>
</plist>
+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_check_scheme(file)) {
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
+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
+26 -1
View File
@@ -19,12 +19,22 @@
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
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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;
@@ -282,3 +292,18 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
#ifdef __clang__
void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#else
inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#endif
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
+8 -20
View File
@@ -18,7 +18,7 @@
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
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -37,7 +37,6 @@ struct rb_root
struct rb_node *rb_node;
};
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(r) (!rb_color(r))
@@ -45,24 +44,13 @@ struct rb_root
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
void rb_insert_color(struct rb_node *, struct rb_root *);
void rb_erase(struct rb_node *, struct rb_root *);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
#ifdef __clang__
void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
#else
inline void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
#endif
+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));
}
+7 -10
View File
@@ -46,6 +46,7 @@ void uwsgi_lock(void *lock) {
void uwsgi_unlock(void *lock) {
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
void uwsgi_rwlock_init(void *lock) {
@@ -134,21 +135,17 @@ void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
#define UWSGI_LOCK_SIZE 8
#define UWSGI_RWLOCK_SIZE 8
static int lock_counter = 0;
void uwsgi_lock_init(void *lock) {
char filename[17];
FILE *tf = tmpfile();
int fd;
if (snprintf(filename, 17, ".uwsgiflock%d", lock_counter) < 0) {
uwsgi_log("unable to create lock %d\n", lock_counter);
}
int fd = open(filename, O_CREAT|O_RDWR|O_TRUNC);
if (fd < 0) {
uwsgi_error_open(filename);
if (!tf) {
uwsgi_error_open("temp lock file");
exit(1);
}
fd = fileno(tf);
memcpy(lock, &fd, sizeof(int));
}
+27 -18
View File
@@ -47,8 +47,10 @@ void log_request(struct wsgi_request *wsgi_req) {
struct uwsgi_app *wi;
if (wsgi_req->do_not_log) return ;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi.apps[wsgi_req->app_id];
wi = &uwsgi_apps[wsgi_req->app_id];
if (wi->requests > 0) {
app_req = wi->requests;
}
@@ -127,22 +129,22 @@ void log_request(struct wsgi_request *wsgi_req) {
rlen = writev(2, logvec, logvecpos+1);
}
void get_memusage() {
void get_memusage(uint64_t *rss, uint64_t *vsz) {
#ifdef UNBIT
uwsgi.workers[uwsgi.mywid].vsz_size = syscall(356);
*vsz = syscall(356);
#elif defined(__linux__)
FILE *procfile;
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", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &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 *) vsz, (unsigned long long *) rss);
if (i != 2) {
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;
*rss = *rss * uwsgi.page_size;
#elif defined (__sun__)
psinfo_t info;
int procfd;
@@ -150,8 +152,8 @@ void get_memusage() {
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;
*rss = (uint64_t) info.pr_rssize * 1024;
*vsz = (uint64_t) info.pr_size * 1024;
}
close(procfd);
}
@@ -162,22 +164,28 @@ void get_memusage() {
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size;
uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size;
*rss = t_info.resident_size;
*vsz = t_info.virtual_size;
}
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
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__)
struct kinfo_proc *kproc;
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
if (kproc && cnt > 0) {
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
*vsz = kproc->ki_size;
*rss = kproc->ki_rssize * uwsgi.page_size;
}
#elif defined(__NetBSD__) || defined(__OpenBSD__)
struct kinfo_proc2 *kproc2;
@@ -185,11 +193,11 @@ void get_memusage() {
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;
*vsz = (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;
*vsz = kproc2->p_vm_msize * uwsgi.page_size;
#endif
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
*rss = kproc2->p_vm_rssize * uwsgi.page_size;
}
#endif
@@ -199,13 +207,14 @@ void get_memusage() {
area_info ai;
int32 cookie;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
*vsz = 0;
*rss = 0;
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
uwsgi.workers[uwsgi.mywid].vsz_size += ai.ram_size;
*vsz += ai.ram_size;
if ( (ai.protection & B_WRITE_AREA) != 0) {
uwsgi.workers[uwsgi.mywid].rss_size += ai.ram_size;
*rss += ai.ram_size;
}
}
#endif
}
+171 -19
View File
@@ -2,12 +2,16 @@
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; }
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);
@@ -21,8 +25,8 @@ void uwsgi_register_loop(char *name, void *loop) {
void *uwsgi_get_loop(char *name) {
int i;
for(i=0;i<uwsgi.loops_cnt;i++) {
for (i = 0; i < uwsgi.loops_cnt; i++) {
if (!strcmp(name, uwsgi.loops[i].name)) {
return uwsgi.loops[i].loop;
}
@@ -44,46 +48,194 @@ void *simple_loop(void *arg1) {
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++) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
/*
pts = PyThreadState_New(uwsgi.main_thread->interp);
pthread_setspecific(uwsgi.ut_save_key, (void *) pts);
*/
}
}
#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);
UWSGI_CLEAR_STATUS;
wsgi_req_setup(wsgi_req, core_id);
if (wsgi_req_accept(wsgi_req)) {
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);
}
pthread_exit(NULL);
//never here
// 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
+747 -231
View File
File diff suppressed because it is too large Load Diff
+406
View File
@@ -0,0 +1,406 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void worker_wakeup() {}
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;
}
}
}
}
void uwsgi_fixup_fds(int wid, int muleid) {
int i;
// 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.workers[i].signal_pipe[0] != -1) close(uwsgi.workers[i].signal_pipe[0]);
if (i != wid) {
if (uwsgi.workers[i].signal_pipe[1] != -1) close(uwsgi.workers[i].signal_pipe[1]);
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.shared->spooler_pid != getpid()) {
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
if (uwsgi.shared->spooler_signal_pipe[1] != -1) close (uwsgi.shared->spooler_signal_pipe[1]);
}
#endif
if (uwsgi.shared->mule_signal_pipe[0] != -1) close(uwsgi.shared->mule_signal_pipe[0]);
if (muleid == 0) {
if (uwsgi.shared->mule_signal_pipe[1] != -1) close(uwsgi.shared->mule_signal_pipe[1]);
}
for(i=0;i<uwsgi.mules_cnt;i++) {
if (uwsgi.mules[i].signal_pipe[0] != -1) close(uwsgi.mules[i].signal_pipe[0]);
if (muleid != i+1) {
if (uwsgi.mules[i].signal_pipe[1] != -1) close(uwsgi.mules[i].signal_pipe[1]);
if (uwsgi.mules[i].queue_pipe[1] != -1) close(uwsgi.mules[i].queue_pipe[1]);
}
}
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi.farms[i].signal_pipe[0] != -1) close(uwsgi.farms[i].signal_pipe[0]);
if (muleid == 0) {
if (uwsgi.farms[i].signal_pipe[1] != -1) close(uwsgi.farms[i].signal_pipe[1]);
if (uwsgi.farms[i].queue_pipe[1] != -1) close(uwsgi.farms[i].queue_pipe[1]);
}
}
}
}
int uwsgi_respawn_worker(int wid) {
int respawns = uwsgi.workers[wid].respawn_count;
int i;
pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
if (pid == 0) {
signal(SIGWINCH, worker_wakeup);
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;
uwsgi.workers[uwsgi.mywid].cheaped = 0;
uwsgi.workers[uwsgi.mywid].busy = 0;
uwsgi.workers[uwsgi.mywid].sig = 0;
// reset the apps count with a copy from the master
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
uwsgi_fixup_fds(wid, 0);
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
if (uwsgi.master_process) {
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 (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;
}
}
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
void uwsgi_send_stats(int fd) {
int i,j;
struct sockaddr_un client_src;
struct uwsgi_app *ua;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
#ifdef __linux__
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
#endif
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
fprintf(output, "\"workers\": [\n");
for (i = 0; i < uwsgi.numproc; i++) {
fprintf(output,"\t{");
fprintf(output,"\"id\": %d, ", uwsgi.workers[i+1].id);
fprintf(output,"\"pid\": %d, ", (int) uwsgi.workers[i+1].pid);
stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i+1].requests);
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i+1].exceptions);
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i+1].signals);
if (uwsgi.workers[i + 1].cheaped) {
fprintf(output,"\"status\": \"cheap\", ");
}
else {
if (uwsgi.workers[i + 1].sig) {
fprintf(output,"\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
}
else if (uwsgi.workers[i + 1].busy) {
fprintf(output,"\"status\": \"busy\", ");
}
else {
fprintf(output,"\"status\": \"idle\", ");
}
}
stats_send_llu("\"rss\": %llu, ", uwsgi.workers[i+1].rss_size);
stats_send_llu("\"vsz\": %llu, ", uwsgi.workers[i+1].vsz_size);
stats_send_llu("\"running_time\": %llu, ", uwsgi.workers[i+1].running_time);
stats_send_llu("\"last_spawn\": %llu, ", uwsgi.workers[i+1].last_spawn);
stats_send_llu("\"respawn_count\": %llu, ", uwsgi.workers[i+1].respawn_count);
stats_send_llu("\"tx\": %llu, ", uwsgi.workers[i+1].tx);
stats_send_llu("\"avg_rt\": %llu, ", uwsgi.workers[i+1].avg_response_time);
fprintf(output,"\"apps\": [\n");
for(j=0;j<uwsgi.workers[i+1].apps_cnt;j++) {
ua = &uwsgi.workers[i+1].apps[j];
fprintf(output,"\t\t{ ");
fprintf(output, "\"id\": %d, ", j);
fprintf(output, "\"modifier1\": %d, ", ua->modifier1);
fprintf(output, "\"mountpoint\": \"%.*s\", ", ua->mountpoint_len, ua->mountpoint);
stats_send_llu( "\"requests\": %llu, ", ua->requests);
stats_send_llu( "\"exceptions\": %llu, ", ua->exceptions);
if (ua->chdir) {
fprintf(output, "\"chdir\": \"%s\", ", ua->chdir);
}
else {
fprintf(output, "\"chdir\": \"\" ");
}
if (j == uwsgi.workers[i+1].apps_cnt-1) {
fprintf(output,"}\n");
}
else {
fprintf(output,"},\n");
}
}
fprintf(output,"\t\t]");
if (i == uwsgi.numproc-1) {
fprintf(output,"}\n");
}
else {
fprintf(output,"},\n");
}
}
fprintf(output,"]}\n");
fclose(output);
}
+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'}
+213
View File
@@ -0,0 +1,213 @@
/*
uWSGI mules are very simple workers only managing signals or running custom code in background.
By default they born in signal-only mode, but if you patch them (passing the script/code to run) they will became fully customized daemons.
*/
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_mule_handler(void);
void uwsgi_mule(int id) {
int i;
pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
if (pid == 0) {
uwsgi.muleid = id;
// avoid race conditions
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = getpid();
uwsgi_fixup_fds(0, id);
uwsgi.my_signal_socket = uwsgi.mules[id-1].signal_pipe[1];
uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];
uwsgi_close_all_sockets();
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
if (uwsgi.mules[id-1].patch) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
uwsgi_log("loaded mule patch %s\n", uwsgi.mules[id-1].patch);
break;
}
}
}
}
uwsgi_mule_handler();
}
else if (pid > 0) {
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = pid;
uwsgi_log("spawned uWSGI mule %d (pid: %d)\n", id, (int) pid);
}
}
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
struct uwsgi_mule_farm *umf = farm->mules;
while(umf) {
if (umf->mule->id == muleid) {
return 1;
}
umf = umf->next;
}
return 0;
}
int farm_has_signaled(int fd) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while(umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].signal_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
return 0;
}
int farm_has_msg(int fd) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while(umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].queue_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
return 0;
}
void uwsgi_mule_add_farm_to_queue(int queue) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
event_queue_add_fd_read(queue, uwsgi.farms[i].signal_pipe[1]);
event_queue_add_fd_read(queue, uwsgi.farms[i].queue_pipe[1]);
}
}
}
void uwsgi_mule_handler() {
ssize_t len;
uint8_t uwsgi_signal;
int rlen;
int interesting_fd;
// this must be configurable
char message[65536];
int mule_queue = event_queue_init();
event_queue_add_fd_read(mule_queue, uwsgi.signal_socket);
event_queue_add_fd_read(mule_queue, uwsgi.my_signal_socket);
event_queue_add_fd_read(mule_queue, uwsgi.mules[uwsgi.muleid-1].queue_pipe[1]);
uwsgi_mule_add_farm_to_queue(mule_queue);
for(;;) {
rlen = event_queue_wait(mule_queue, -1, &interesting_fd);
if (rlen <= 0) {
continue;
}
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
}
}
else if (interesting_fd == uwsgi.mules[uwsgi.muleid-1].queue_pipe[1] || farm_has_msg(interesting_fd)) {
len = read(interesting_fd, message, 65536);
if (len < 0) {
uwsgi_error("read()");
}
else if (len == 0) {
exit(1);
}
else {
uwsgi_log("*** mule %d received a %d bytes message ***\n", uwsgi.muleid, len);
}
}
}
}
struct uwsgi_mule *get_mule_by_id(int id) {
int i;
for(i=0;i<uwsgi.mules_cnt;i++) {
if (uwsgi.mules[i].id == id) {
return &uwsgi.mules[i];
}
}
return NULL;
}
struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **umf, struct uwsgi_mule *um) {
struct uwsgi_mule_farm *uwsgi_mf = *umf, *old_umf;
if (!uwsgi_mf) {
*umf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
uwsgi_mf = *umf;
}
else {
while(uwsgi_mf) {
old_umf = uwsgi_mf;
uwsgi_mf = uwsgi_mf->next;
}
uwsgi_mf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
old_umf->next = uwsgi_mf;
}
uwsgi_mf->mule = um;
uwsgi_mf->next = NULL;
return uwsgi_mf;
}
+18 -4
View File
@@ -1,13 +1,27 @@
[uwsgi]
; socket 0
socket = :3033
; socket 1
socket = :3034
vacuum = true
; socket 2
socket = pippo1.sock
; socket 3
socket = pippo2.sock
; socket 4
socket = 127.0.0.1:1717
map-socket = 0:1,2,3,4
map-socket = 1:4
map-socket = 2:10
map-socket = 3:5,6,9
map-socket = 4:7,8,9
vacuum = true
memory-report = true
master = true
processes = 10
mount = /app1=werkzeug.testapp:test_app
mount = /app2=config:/Users/roberta/uwsgi/my.ini
mount = /app3=pinaxsite/deploy/pinax.wsgi
;mount = /app1=werkzeug.testapp:test_app
;mount = /app2=config:/Users/roberta/uwsgi/my.ini
;mount = /app3=pinaxsite/deploy/pinax.wsgi
+3 -8
View File
@@ -1,14 +1,9 @@
import werkzeug
def web3_app(environ):
status = b'200 OK'
headers = [(b'Content-type', b'text/plain')]
body = [b'I am a Web3 app\n']
return body, status, headers
import uwsgi
def zero_app(e,s):
s('200 OK', [ ('Content-Type', 'text/plain') ])
return ""
return "0"
def not_found(e,s):
s('404 Not Found', [ ('Content-Type', 'text/plain') ])
@@ -24,4 +19,4 @@ def internal_server_error(e, s):
s('500 Internal Server Error', [ ('Content-Type', 'text/plain') ])
return ""
applications = {'':web3_app, '/wsgi':wsgi_app, '/test':werkzeug.test_app, '/zero':zero_app, '/notfound':not_found, '/ise':internal_server_error}
uwsgi.applications = {'/wsgi':wsgi_app, '/test':werkzeug.test_app, '/zero':zero_app, '/notfound':not_found, '/ise':internal_server_error}
+11 -1
View File
@@ -2,6 +2,16 @@ import uwsgi
import struct
import sys
print sys.argv
if len(sys.argv) == 3:
chunks = uwsgi.send_message(sys.argv[1], 10, int(sys.argv[2]), '')
print uwsgi.send_uwsgi_message(sys.argv[1], int(sys.argv[2]), 10, int(sys.argv[3]), struct.pack("i", int(sys.argv[4])))
pkt = ''
for chunk in chunks:
pkt += chunk
print "%d = %d" % (int(sys.argv[2]), struct.unpack("I", pkt)[0])
elif len(sys.argv) == 4:
uwsgi.send_message(sys.argv[1], 10, int(sys.argv[2]), struct.pack("I", int(sys.argv[3])))
+72
View File
@@ -0,0 +1,72 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_systemd_notify(char *message) {
struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
struct iovec *iovec = msghdr->msg_iov;
iovec[0].iov_base = "STATUS=";
iovec[0].iov_len = 7;
iovec[1].iov_base = message;
iovec[1].iov_len = strlen(message);
iovec[2].iov_base = "\n";
iovec[2].iov_len = 1;
msghdr->msg_iovlen = 3;
sendmsg(uwsgi.notification_fd, msghdr, 0);
}
void uwsgi_systemd_notify_ready(void) {
struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
struct iovec *iovec = msghdr->msg_iov;
iovec[0].iov_base = "STATUS=uWSGI is ready\nREADY=1\n";
iovec[0].iov_len = 30;
msghdr->msg_iovlen = 1;
sendmsg(uwsgi.notification_fd, msghdr, 0);
}
void uwsgi_systemd_init(char *systemd_socket) {
struct sockaddr_un *sd_sun;
struct msghdr *msghdr;
uwsgi.notification_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (uwsgi.notification_fd < 0) {
uwsgi_error("socket()");
return;
}
sd_sun = uwsgi_malloc(sizeof(struct sockaddr_un));
memset(sd_sun, 0, sizeof(struct sockaddr_un));
sd_sun->sun_family = AF_UNIX;
strncpy(sd_sun->sun_path, systemd_socket, sizeof(sd_sun->sun_path));
if (sd_sun->sun_path[0] == '@') sd_sun->sun_path[0] = 0;
msghdr = uwsgi_malloc(sizeof(struct msghdr));
memset(msghdr, 0, sizeof(struct msghdr));
msghdr->msg_iov = uwsgi_malloc(sizeof(struct iovec)*3);
memset(msghdr->msg_iov, 0, sizeof(struct iovec)*3);
msghdr->msg_name = sd_sun;
msghdr->msg_namelen = sizeof(struct sockaddr_un);
uwsgi.notification_object = msghdr;
uwsgi.notify = uwsgi_systemd_notify;
uwsgi.notify_ready = uwsgi_systemd_notify_ready;
}
+115 -29
View File
@@ -2,63 +2,149 @@
extern struct uwsgi_server uwsgi;
void embed_plugins() {
#ifdef UWSGI_EMBED_PLUGIN_PSGI
if (uwsgi.plugin_arg_psgi)
uwsgi_load_plugin(5, "psgi_plugin.so", uwsgi.plugin_arg_psgi, 0);
#endif
#ifdef UWSGI_EMBED_PLUGIN_LUA
if (uwsgi.plugin_arg_lua)
uwsgi_load_plugin(6, "lua_plugin.so", uwsgi.plugin_arg_lua, 0);
#endif
#ifdef UWSGI_EMBED_PLUGIN_RACK
if (uwsgi.plugin_arg_rack)
uwsgi_load_plugin(7, "rack_plugin.so", uwsgi.plugin_arg_rack, 0);
#endif
}
int uwsgi_load_plugin(int modifier, char *plugin, char *pargs, int absolute) {
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option, int absolute) {
void *plugin_handle;
char *plugin_name;
char *plugin_entry_symbol;
struct uwsgi_plugin *up;
char linkpath_buf[1024], linkpath[1024];
int linkpath_size;
int i;
if (absolute) {
plugin_name = malloc(strlen(plugin) + 1);
memcpy(plugin_name, plugin, strlen(plugin) + 1);
char *colon = strchr(plugin, ':');
if (colon) {
colon[0] = 0;
}
check:
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->name) {
if (!strcmp(plugin, uwsgi.p[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
}
}
if (uwsgi.p[i]->alias) {
if (!strcmp(plugin, uwsgi.p[i]->alias)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
}
}
}
for(i=0;i<uwsgi.gp_cnt;i++) {
if (uwsgi.gp[i]->name) {
if (!strcmp(plugin, uwsgi.gp[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
}
}
if (uwsgi.gp[i]->alias) {
if (!strcmp(plugin, uwsgi.gp[i]->alias)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
}
}
}
if (colon) {
plugin = colon+1;
colon[0] = ':';
colon = NULL;
goto check;
}
if (absolute == 1) {
plugin_name = uwsgi_concat2(plugin, "");
// need to fix this... postpone until needed
plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0);
}
else if (absolute == 2) {
plugin_name = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin);
plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0);
}
else {
plugin_name = uwsgi_concat4(UWSGI_PLUGIN_DIR, "/", plugin, "_plugin.so");
plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin");
}
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
free(plugin_name);
if (!plugin_handle) {
uwsgi_log( "%s\n", dlerror());
}
else {
plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin");
up = dlsym(plugin_handle, plugin_entry_symbol);
if (!up) {
// is it a link ?
memset(linkpath_buf, 0, 1024);
memset(linkpath, 0, 1024);
if ((linkpath_size = readlink(plugin_name, linkpath_buf, 1023)) > 0) {
do {
linkpath_buf[linkpath_size] = '\0';
strcpy(linkpath, linkpath_buf);
} while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0);
uwsgi_log("%s\n", linkpath);
free(plugin_entry_symbol);
up = dlsym(plugin_handle, plugin_entry_symbol);
char *slash = uwsgi_get_last_char(linkpath, '/');
if (!slash) {
slash = linkpath;
}
else {
slash++;
}
plugin_entry_symbol = uwsgi_concat2n(slash, strlen(slash)-3, "",0);
up = dlsym(plugin_handle, plugin_entry_symbol);
}
}
if (up) {
if (has_option) {
struct option *lopt = up->options, *aopt;
int found = 0;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(has_option, aopt->name)) {
found = 1;
break;
}
lopt++;
}
if (!found) {
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
free(plugin_name);
free(plugin_entry_symbol);
return NULL;
}
}
if (modifier != -1) {
fill_plugin_table(modifier, up);
}
else {
fill_plugin_table(up->modifier1, up);
}
return 1;
free(plugin_name);
free(plugin_entry_symbol);
return plugin_handle;
}
uwsgi_log( "%s\n", dlerror());
}
return 0;
free(plugin_name);
return -1;
return NULL;
}
+47 -17
View File
@@ -1,28 +1,58 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
/* uwsgi ADMIN|10 */
int uwsgi_request_admin(struct wsgi_request *wsgi_req) {
uint32_t opt_value = 0;
int i;
ssize_t len;
if (wsgi_req->uh.pktsize >= 4) {
if (wsgi_req->uh.pktsize != 0 && wsgi_req->uh.pktsize != 4)
return UWSGI_OK;
// write request
if (wsgi_req->uh.pktsize == 4) {
memcpy(&opt_value, wsgi_req->buffer, 4);
// TODO: check endianess ?
}
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
// ACK
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
i = write(wsgi_req->poll.fd, wsgi_req, 4);
if (i != 4) {
uwsgi_error("write()");
}
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
// ACK
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
len = write(wsgi_req->poll.fd, wsgi_req, 4);
if (len != 4) {
uwsgi_error("write()");
}
}
// get request
else {
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh.modifier2, uwsgi.shared->options[wsgi_req->uh.modifier2]);
wsgi_req->uh.modifier1 = 10;
wsgi_req->uh.pktsize = 4;
len = write(wsgi_req->poll.fd, wsgi_req, 4);
if (len != 4) {
uwsgi_error("write()");
return UWSGI_OK;
}
len = write(wsgi_req->poll.fd, (char *) &uwsgi.shared->options[wsgi_req->uh.modifier2], 4);
if (len != 4) {
uwsgi_error("write()");
}
}
return UWSGI_OK;
}
struct uwsgi_plugin admin_plugin = {
.name = "admin",
.modifier1 = 10,
.request = uwsgi_request_admin,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='admin'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['admin_plugin']
+104
View File
@@ -0,0 +1,104 @@
#include "../../uwsgi.h"
void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) data;
uint64_t tmp_vallen = 0;
if (vallen > 0) {
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && tmp_vallen > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("cache value size: %llu\n", tmp_vallen);
#endif
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
}
}
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && vallen > 0) {
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
}
else {
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\n<h1>Not Found</h1>", 44);
}
}
}
}
int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uint64_t vallen = 0;
char *value;
char *argv[3];
uint8_t argc = 0;
switch(wsgi_req->uh.modifier2) {
case 0:
// get
if (wsgi_req->uh.pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh.pktsize = vallen;
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, value, vallen);
}
}
break;
case 1:
// set
if (wsgi_req->uh.pktsize > 0) {
argc = 3;
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
if (argc > 1) {
uwsgi_cache_set(argv[0], strlen(argv[0]), argv[1], strlen(argv[1]), 0, 0);
}
}
}
break;
case 2:
// del
if (wsgi_req->uh.pktsize > 0) {
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
}
break;
case 3:
case 4:
// dict
if (wsgi_req->uh.pktsize > 0) {
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh.pktsize, cache_command, (void *) wsgi_req);
}
break;
case 5:
// get (uwsgi + stream)
if (wsgi_req->uh.pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, value, vallen);
}
else {
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
}
}
break;
}
return 0;
}
struct uwsgi_plugin cache_plugin = {
.name = "cache",
.modifier1 = 111,
.request = uwsgi_cache_request,
};
@@ -1,7 +1,7 @@
NAME='proxy'
NAME='cache'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['proxy']
GCC_LIST = ['cache']
+63
View File
@@ -0,0 +1,63 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
class FakeClass {
public:
char *foobar;
uint16_t foobar_len;
void hello_world(struct wsgi_request *);
};
void FakeClass::hello_world(struct wsgi_request *wsgi_req) {
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n", 44);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, foobar, foobar_len);
}
extern "C" int uwsgi_cplusplus_init(){
uwsgi_log("Initializing example c++ plugin\n");
return 0;
}
extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
FakeClass *fc;
// empty request ?
if (!wsgi_req->uh.pktsize) {
uwsgi_log( "Invalid request. skip.\n");
goto clear;
}
// get uwsgi variables
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid request. skip.\n");
goto clear;
}
fc = new FakeClass();
// get PATH_INFO
fc->foobar = uwsgi_get_var(wsgi_req, (char *) "PATH_INFO", &fc->foobar_len);
if (fc->foobar) {
// send output
fc->hello_world(wsgi_req);
}
delete fc;
clear:
return UWSGI_OK;
}
extern "C" void uwsgi_cplusplus_after_request(struct wsgi_request *wsgi_req) {
uwsgi_log("logging c++ request\n");
}
+17
View File
@@ -0,0 +1,17 @@
#include "../../uwsgi.h"
int uwsgi_cplusplus_init(void);
int uwsgi_cplusplus_request(struct wsgi_request *);
void uwsgi_cplusplus_after_request(struct wsgi_request *);
struct uwsgi_plugin cplusplus_plugin = {
.name = "cplusplus",
.modifier1 = 250,
.init = uwsgi_cplusplus_init,
.request = uwsgi_cplusplus_request,
.after_request = uwsgi_cplusplus_after_request,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='cplusplus'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lstdc++']
GCC_LIST = ['base.cc', 'plugin']
+1 -1
View File
@@ -5,7 +5,7 @@ extern struct uwsgi_server uwsgi;
int uwsgi_echo_request(struct wsgi_request *wsgi_req) {
wsgi_req->response_size = write(wsgi_req->poll.fd, wsgi_req->buffer, wsgi_req->uh.pktsize);
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, wsgi_req->buffer, wsgi_req->uh.pktsize);
return 0;
}
+2 -1
View File
@@ -422,7 +422,7 @@ int erlang_init() {
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
if (register_fat_gateway("erlang", erlang_loop) == NULL) {
if (register_fat_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
uwsgi_log("unable to register the erlang gateway\n");
exit(1);
}
@@ -447,6 +447,7 @@ int erlang_opt(int i, char *optarg) {
struct uwsgi_plugin erlang_plugin = {
.name = "erlang",
.options = erlang_options,
.manage_opt = erlang_opt,
.init = erlang_init,
+17 -5
View File
@@ -2,21 +2,33 @@
extern struct uwsgi_server uwsgi;
int uwsgi_init(char *args){
uwsgi_log("i am the example plugin initialization function with arg: %s\n", args);
int uwsgi_example_init(){
uwsgi_log("i am the example plugin initialization function\n");
return 0;
}
int uwsgi_request(struct wsgi_request *wsgi_req) {
int uwsgi_example_request(struct wsgi_request *wsgi_req) {
char *http = "HTTP/1.1 200 Ok\r\nContent-type: text/html\r\n\r\n<h1>Hello World</h1>";
wsgi_req->response_size += write(wsgi_req->poll.fd, http, strlen(http));
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, http, strlen(http));
return 0;
}
void uwsgi_after_request(struct wsgi_request *wsgi_req) {
void uwsgi_example_after_request(struct wsgi_request *wsgi_req) {
uwsgi_log("i am the example plugin after request function\n");
}
struct uwsgi_plugin example_plugin = {
.name = "example",
.modifier1 = 250,
.init = uwsgi_example_init,
.request = uwsgi_example_request,
.after_request = uwsgi_example_after_request,
};
+5 -2
View File
@@ -1,3 +1,6 @@
NAME='example'
CFLAGS = ''
LDFLAGS = ''
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['example_plugin']
+412 -113
View File
@@ -12,10 +12,14 @@
#include "../../uwsgi.h"
#define LONG_ARGS_FASTROUTER 150001
#define LONG_ARGS_FASTROUTER_EVENTS 150002
#define LONG_ARGS_FASTROUTER_USE_PATTERN 150003
#define LONG_ARGS_FASTROUTER_USE_BASE 150004
#define LONG_ARGS_FASTROUTER 150001
#define LONG_ARGS_FASTROUTER_EVENTS 150002
#define LONG_ARGS_FASTROUTER_USE_PATTERN 150003
#define LONG_ARGS_FASTROUTER_USE_BASE 150004
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER 150005
#define LONG_ARGS_FASTROUTER_TIMEOUT 150006
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT 150007
#define LONG_ARGS_FASTROUTER_USE_CODE_STRING 150008
#define FASTROUTER_STATUS_FREE 0
#define FASTROUTER_STATUS_CONNECTING 1
@@ -23,29 +27,108 @@
#define FASTROUTER_STATUS_RECV_VARS 3
#define FASTROUTER_STATUS_RESPONSE 4
#define add_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+ufr.socket_timeout, x)
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
struct uwsgi_fastrouter_socket {
char *name;
int fd;
struct uwsgi_fastrouter_socket *next;
};
struct uwsgi_fastrouter {
char *socket_name;
int use_cache;
int nevents;
char *pattern;
int pattern_len;
struct uwsgi_fastrouter_socket *sockets;
char *base;
int base_len;
int use_cache;
int nevents;
int queue;
int subscription_slot;
char *pattern;
int pattern_len;
char *base;
int base_len;
char *subscription_server;
struct uwsgi_dict *subscription_dict;
int socket_timeout;
uint8_t code_string_modifier1;
char *code_string_code;
char *code_string_function;
struct rb_root *timeouts;
int cheap;
int i_am_cheap;
} ufr;
static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name) {
struct uwsgi_fastrouter_socket *uwsgi_sock = ufr.sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
ufr.sockets = uwsgi_malloc(sizeof(struct uwsgi_fastrouter_socket));
uwsgi_sock = ufr.sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_fastrouter_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_fastrouter_socket));
uwsgi_sock->name = name;
return uwsgi_sock;
}
struct option fastrouter_options[] = {
{"fastrouter", required_argument, 0, LONG_ARGS_FASTROUTER},
{"fastrouter-use-cache", no_argument, &ufr.use_cache, 1},
{"fastrouter-use-pattern", required_argument, 0, LONG_ARGS_FASTROUTER_USE_PATTERN},
{"fastrouter-use-base", required_argument, 0, LONG_ARGS_FASTROUTER_USE_BASE},
{"fastrouter-use-code-string", required_argument, 0, LONG_ARGS_FASTROUTER_USE_CODE_STRING},
{"fastrouter-events", required_argument, 0, LONG_ARGS_FASTROUTER_EVENTS},
{"fastrouter-cheap", no_argument, &ufr.cheap, 1},
{"fastrouter-subscription-server", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER},
{"fastrouter-subscription-slot", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT},
{"fastrouter-timeout", required_argument, 0, LONG_ARGS_FASTROUTER_TIMEOUT},
{0, 0, 0, 0},
};
extern struct uwsgi_server uwsgi;
void fastrouter_manage_subscription(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct uwsgi_subscribe_req *usr = (struct uwsgi_subscribe_req *) data;
if (!uwsgi_strncmp("key", 3, key, keylen)) {
usr->key = val;
usr->keylen = vallen;
}
else if (!uwsgi_strncmp("address", 7, key, keylen)) {
usr->address = val;
usr->address_len = vallen;
}
else if (!uwsgi_strncmp("modifier1", 9, key, keylen)) {
usr->modifier1 = uwsgi_str_num(val, vallen);
}
}
struct fastrouter_session {
int fd;
@@ -59,12 +142,74 @@ struct fastrouter_session {
char *hostname;
uint16_t hostname_len;
int has_key;
char *instance_address;
uint64_t instance_address_len;
struct uwsgi_subscriber_name *un;
int pass_fd;
struct uwsgi_rb_timer *timeout;
int instance_failed;
uint8_t modifier1;
};
static void close_session(struct fastrouter_session **fr_table, struct fastrouter_session *fr_session) {
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
if (fr_session->instance_fd != -1) {
if (ufr.subscription_server && (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING)) {
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
if (fr_session->un->len > 0) {
if (ufr.subscription_dict->count > 0) {
ufr.subscription_dict->count--;
}
if (ufr.subscription_dict->count == 0 && ufr.cheap && !ufr.i_am_cheap) {
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 1;
}
}
}
close(fr_session->instance_fd);
fr_table[fr_session->instance_fd] = NULL;
}
del_timeout(fr_session);
free(fr_session);
}
static struct uwsgi_rb_timer *reset_timeout(struct fastrouter_session *fr_session) {
del_timeout(fr_session);
return add_timeout(fr_session);
}
static void expire_timeouts(struct fastrouter_session **fr_table) {
time_t current = time(NULL);
struct uwsgi_rb_timer *urbt;
for(;;) {
urbt = uwsgi_min_rb_timer(ufr.timeouts);
if (urbt == NULL) return;
if (urbt->key <= current) {
close_session(fr_table, (struct fastrouter_session *)urbt->data);
uwsgi_log("timeout !!!\n");
continue;
}
break;
}
}
void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct fastrouter_session *fr_session = (struct fastrouter_session *) data;
@@ -76,7 +221,14 @@ void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, voi
return;
}
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen)) {
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !fr_session->has_key) {
fr_session->hostname = val;
fr_session->hostname_len = vallen;
return;
}
if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) {
fr_session->has_key = 1;
fr_session->hostname = val;
fr_session->hostname_len = vallen;
return;
@@ -90,19 +242,26 @@ struct fastrouter_session *alloc_fr_session() {
void fastrouter_loop() {
int fr_queue;
int fr_server;
int nevents;
int interesting_fd;
int new_connection;
ssize_t len;
int i;
time_t delta;
char bbuf[UMAX16];
char *tcp_port;
char *tmp_socket_name;
int tmp_socket_name_len;
struct uwsgi_subscribe_req usr;
char *magic_table[0xff];
struct uwsgi_rb_timer *min_timeout;
void *events;
struct msghdr msg;
union {
@@ -123,25 +282,85 @@ void fastrouter_loop() {
int soopt;
socklen_t solen = sizeof(int);
int ufr_subserver = -1;
for(i=0;i<2048;i++) {
fr_table[i] = NULL;
}
fr_server = bind_to_tcp(ufr.socket_name, uwsgi.listen_queue, ufr.socket_name);
ufr.queue = event_queue_init();
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
if (ufr_sock->name[0] == '=') {
int shared_socket = atoi(ufr_sock->name+1);
if (shared_socket >= 0) {
ufr_sock->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
if (ufr_sock->fd == -1) {
uwsgi_log("unable to use shared socket %d\n", shared_socket);
}
}
}
else {
tcp_port = strchr(ufr_sock->name, ':');
if (tcp_port) {
ufr_sock->fd = bind_to_tcp(ufr_sock->name, uwsgi.listen_queue, tcp_port);
}
else {
ufr_sock->fd = bind_to_unix(ufr_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
}
uwsgi_log("uwsgi fastrouter/proxy bound on %s\n", ufr_sock->name);
if (!ufr.cheap) {
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
}
else {
uwsgi_log("[uwsgi-fastrouter] cheap mode requested. Waiting for subscriptions...\n");
ufr.i_am_cheap = 1;
}
ufr_sock = ufr_sock->next;
}
fr_queue = event_queue_init();
events = event_queue_alloc(ufr.nevents);
event_queue_add_fd_read(fr_queue, fr_server);
if (ufr.subscription_server) {
ufr_subserver = bind_to_udp(ufr.subscription_server, 0, 0);
event_queue_add_fd_read(ufr.queue, ufr_subserver);
if (!ufr.subscription_slot) ufr.subscription_slot = 30;
ufr.subscription_dict = uwsgi_dict_create(ufr.subscription_slot, 0);
}
if (ufr.pattern) {
init_magic_table(magic_table);
}
ufr.timeouts = uwsgi_init_rb_timer();
if (!ufr.socket_timeout) ufr.socket_timeout = 30;
for (;;) {
nevents = event_queue_wait_multi(fr_queue, -1, events, ufr.nevents);
min_timeout = uwsgi_min_rb_timer(ufr.timeouts);
if (min_timeout == NULL ) {
delta = -1;
}
else {
delta = min_timeout->key - time(NULL);
if (delta <= 0) {
expire_timeouts(fr_table);
delta = 0;
}
}
nevents = event_queue_wait_multi(ufr.queue, delta, events, ufr.nevents);
if (nevents == 0) {
expire_timeouts(fr_table);
}
for (i=0;i<nevents;i++) {
@@ -149,23 +368,59 @@ void fastrouter_loop() {
interesting_fd = event_queue_interesting_fd(events, i);
if (interesting_fd == fr_server) {
new_connection = accept(fr_server, (struct sockaddr *) &fr_addr, &fr_addr_len);
if (new_connection < 0) {
continue;
int taken = 0;
struct uwsgi_fastrouter_socket *uwsgi_sock = ufr.sockets;
while(uwsgi_sock) {
if (interesting_fd == uwsgi_sock->fd) {
new_connection = accept(interesting_fd, (struct sockaddr *) &fr_addr, &fr_addr_len);
if (new_connection < 0) {
continue;
}
fr_table[new_connection] = alloc_fr_session();
fr_table[new_connection]->fd = new_connection;
fr_table[new_connection]->instance_fd = -1;
fr_table[new_connection]->status = FASTROUTER_STATUS_RECV_HDR;
fr_table[new_connection]->h_pos = 0;
fr_table[new_connection]->pos = 0;
fr_table[new_connection]->un = NULL;
fr_table[new_connection]->instance_failed = 0;
fr_table[new_connection]->instance_address_len = 0;
fr_table[new_connection]->timeout = add_timeout(fr_table[new_connection]);
event_queue_add_fd_read(ufr.queue, new_connection);
taken = 1;
break;
}
fr_table[new_connection] = alloc_fr_session();
fr_table[new_connection]->fd = new_connection;
fr_table[new_connection]->instance_fd = -1;
fr_table[new_connection]->status = FASTROUTER_STATUS_RECV_HDR;
fr_table[new_connection]->h_pos = 0;
fr_table[new_connection]->pos = 0;
fr_table[new_connection]->instance_address_len = 0;
event_queue_add_fd_read(fr_queue, new_connection);
uwsgi_sock = uwsgi_sock->next;
}
if (taken) {
continue;
}
if (interesting_fd == ufr_subserver) {
len = recv(ufr_subserver, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ufr.queue, ufr_subserver);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf+4, len-4, fastrouter_manage_subscription, &usr);
uwsgi_add_subscriber(ufr.subscription_dict, &usr);
if (ufr.i_am_cheap) {
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 0;
uwsgi_log("[uwsgi-fastrouter] leaving cheap mode...\n");
}
}
}
else {
fr_session = fr_table[interesting_fd];
@@ -173,25 +428,19 @@ void fastrouter_loop() {
if (fr_session == NULL) continue;
if (event_queue_interesting_fd_has_error(events, i)) {
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
if (fr_session->instance_fd != -1) {
close(fr_session->instance_fd);
fr_table[fr_session->instance_fd] = NULL;
}
free(fr_session);
close_session(fr_table, fr_session);
continue;
}
fr_session->timeout = reset_timeout(fr_session);
switch(fr_session->status) {
case FASTROUTER_STATUS_RECV_HDR:
len = recv(fr_session->fd, (char *)(&fr_session->uh) + fr_session->h_pos, 4-fr_session->h_pos, 0);
if (len <= 0) {
uwsgi_error("recv()");
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
fr_session->h_pos += len;
@@ -208,30 +457,31 @@ void fastrouter_loop() {
len = recv(fr_session->fd, fr_session->buffer + fr_session->pos, fr_session->uh.pktsize - fr_session->pos, 0);
if (len <= 0) {
uwsgi_error("recv()");
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
fr_session->pos += len;
if (fr_session->pos == fr_session->uh.pktsize) {
if (uwsgi_hooked_parse(fr_session->buffer, fr_session->uh.pktsize, fr_get_hostname, (void *) fr_session)) {
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
if (fr_session->hostname_len == 0) {
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
//uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
#ifdef UWSGI_DEBUG
uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
#endif
if (ufr.use_cache) {
fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
if (cs_mod) {
fr_session->modifier1 = uwsgi_str_num(cs_mod+1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address))-1);
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
}
}
else if (ufr.pattern) {
magic_table['s'] = uwsgi_concat2n(fr_session->hostname, fr_session->hostname_len, "", 0);
@@ -240,17 +490,36 @@ void fastrouter_loop() {
fr_session->instance_address_len = tmp_socket_name_len;
fr_session->instance_address = tmp_socket_name;
}
else if (ufr.subscription_server) {
fr_session->un = uwsgi_get_subscriber(ufr.subscription_dict, fr_session->hostname, fr_session->hostname_len);
if (fr_session->un && fr_session->un->len) {
fr_session->instance_address = fr_session->un->name;
fr_session->instance_address_len = fr_session->un->len;
fr_session->modifier1 = fr_session->un->modifier1;
}
}
else if (ufr.base) {
tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
fr_session->instance_address_len = tmp_socket_name_len;
fr_session->instance_address = tmp_socket_name;
}
else if (ufr.code_string_code && ufr.code_string_function) {
if (uwsgi.p[ufr.code_string_modifier1]->code_string) {
fr_session->instance_address = uwsgi.p[ufr.code_string_modifier1]->code_string("uwsgi_fastrouter", ufr.code_string_code, ufr.code_string_function, fr_session->hostname, fr_session->hostname_len);
if (fr_session->instance_address) {
fr_session->instance_address_len = strlen(fr_session->instance_address);
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
if (cs_mod) {
fr_session->modifier1 = uwsgi_str_num(cs_mod+1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address))-1);
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
}
}
}
}
// no address found
if (!fr_session->instance_address_len) {
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
@@ -262,16 +531,32 @@ void fastrouter_loop() {
if (tmp_socket_name) free(tmp_socket_name);
if (fr_session->instance_fd < 0) {
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
free(fr_session);
if (ufr.subscription_server) {
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
if (fr_session->un->len > 0) {
fr_session->un->len = 0;
if (ufr.subscription_dict->count > 0) {
ufr.subscription_dict->count--;
}
if (ufr.subscription_dict->count == 0 && ufr.cheap && !ufr.i_am_cheap) {
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 1;
}
}
}
close_session(fr_table, fr_session);
break;
}
fr_session->status = FASTROUTER_STATUS_CONNECTING;
fr_table[fr_session->instance_fd] = fr_session;
event_queue_add_fd_write(fr_queue, fr_session->instance_fd);
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
}
break;
@@ -283,31 +568,31 @@ void fastrouter_loop() {
if (getsockopt(fr_session->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
close(fr_session->fd);
close(fr_session->instance_fd);
fr_table[fr_session->fd] = NULL;
fr_table[fr_session->instance_fd] = NULL;
free(fr_session);
fr_session->instance_failed = 1;
close_session(fr_table, fr_session);
break;
}
if (soopt) {
uwsgi_log("unable to connect() to uwsgi instance: %s\n", strerror(soopt));
close(fr_session->fd);
close(fr_session->instance_fd);
fr_table[fr_session->fd] = NULL;
fr_table[fr_session->instance_fd] = NULL;
free(fr_session);
fr_session->instance_failed = 1;
close_session(fr_table, fr_session);
break;
}
fr_session->uh.modifier1 = fr_session->modifier1;
iov[0].iov_base = &fr_session->uh;
iov[0].iov_len = 4;
iov[1].iov_base = fr_session->buffer;
iov[1].iov_len = fr_session->uh.pktsize;
// increment node requests counter
if (fr_session->un)
fr_session->un->requests++;
// fd passing: PERFORMANCE EXTREME BOOST !!!
if (fr_session->pass_fd) {
if (fr_session->pass_fd && !uwsgi.no_fd_passing) {
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
@@ -327,25 +612,17 @@ void fastrouter_loop() {
uwsgi_error("sendmsg()");
}
close(fr_session->fd);
close(fr_session->instance_fd);
fr_table[fr_session->fd] = NULL;
fr_table[fr_session->instance_fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
if (writev(fr_session->instance_fd, iov, 2) < 0) {
uwsgi_error("writev()");
close(fr_session->fd);
close(fr_session->instance_fd);
fr_table[fr_session->fd] = NULL;
fr_table[fr_session->instance_fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
event_queue_fd_write_to_read(fr_queue, fr_session->instance_fd);
event_queue_fd_write_to_read(ufr.queue, fr_session->instance_fd);
fr_session->status = FASTROUTER_STATUS_RESPONSE;
}
@@ -358,11 +635,7 @@ void fastrouter_loop() {
len = recv(fr_session->instance_fd, fr_session->buffer, 0xffff, 0);
if (len <= 0) {
if (len < 0) uwsgi_error("recv()");
close(fr_session->fd);
close(fr_session->instance_fd);
fr_table[fr_session->fd] = NULL;
fr_table[fr_session->instance_fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
@@ -370,13 +643,13 @@ void fastrouter_loop() {
if (len <= 0) {
if (len < 0) uwsgi_error("send()");
close(fr_session->fd);
close(fr_session->instance_fd);
fr_table[fr_session->fd] = NULL;
fr_table[fr_session->instance_fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
// update transfer statistics
if (fr_session->un)
fr_session->un->transferred += len;
}
// body from client
else if (interesting_fd == fr_session->fd) {
@@ -385,11 +658,7 @@ void fastrouter_loop() {
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
if (len <= 0) {
if (len < 0) uwsgi_error("recv()");
close(fr_session->fd);
close(fr_session->instance_fd);
fr_table[fr_session->fd] = NULL;
fr_table[fr_session->instance_fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
@@ -398,11 +667,7 @@ void fastrouter_loop() {
if (len <= 0) {
if (len < 0) uwsgi_error("send()");
close(fr_session->fd);
close(fr_session->instance_fd);
fr_table[fr_session->fd] = NULL;
fr_table[fr_session->instance_fd] = NULL;
free(fr_session);
close_session(fr_table, fr_session);
break;
}
}
@@ -414,13 +679,7 @@ void fastrouter_loop() {
// fallback to destroy !!!
default:
uwsgi_log("default action\n");
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
if (fr_session->instance_fd != -1) {
close(fr_session->instance_fd);
fr_table[fr_session->instance_fd] = NULL;
}
free(fr_session);
close_session(fr_table, fr_session);
break;
}
@@ -432,7 +691,7 @@ void fastrouter_loop() {
int fastrouter_init() {
if (ufr.socket_name) {
if (ufr.sockets) {
if (ufr.use_cache && !uwsgi.cache_max_items) {
uwsgi_log("you need to create a uwsgi cache to use the fastrouter (add --cache <n>)\n");
@@ -441,9 +700,17 @@ int fastrouter_init() {
if (!ufr.nevents) ufr.nevents = 64;
if (register_gateway("fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
if (ufr.code_string_code && ufr.code_string_function) {
if (register_fat_gateway("uWSGI fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
}
}
else {
if (register_gateway("uWSGI fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
}
}
}
@@ -452,9 +719,16 @@ int fastrouter_init() {
int fastrouter_opt(int i, char *optarg) {
char *cs;
char *cs_code;
char *cs_func;
switch(i) {
case LONG_ARGS_FASTROUTER:
ufr.socket_name = optarg;
uwsgi_fastrouter_new_socket(generate_socket_name(optarg));
return 1;
case LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER:
ufr.subscription_server = optarg;
return 1;
case LONG_ARGS_FASTROUTER_EVENTS:
ufr.nevents = atoi(optarg);
@@ -469,6 +743,30 @@ int fastrouter_opt(int i, char *optarg) {
// optimization
ufr.base_len = strlen(ufr.base);
return 1;
case LONG_ARGS_FASTROUTER_USE_CODE_STRING:
cs = uwsgi_str(optarg);
cs_code = strchr(cs, ':');
if (!cs_code) {
uwsgi_log("invalid code_string option\n");
exit(1);
}
cs_code[0] = 0;
cs_func = strchr(cs_code+1, ':');
if (!cs_func) {
uwsgi_log("invalid code_string option\n");
exit(1);
}
cs_func[0] = 0;
ufr.code_string_modifier1 = atoi(cs);
ufr.code_string_code = cs_code+1;
ufr.code_string_function = cs_func+1;
return 1;
case LONG_ARGS_FASTROUTER_TIMEOUT:
ufr.socket_timeout = atoi(optarg);
return -1;
case LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT:
ufr.subscription_slot = atoi(optarg);
return 1;
}
return 0;
}
@@ -476,6 +774,7 @@ int fastrouter_opt(int i, char *optarg) {
struct uwsgi_plugin fastrouter_plugin = {
.name = "fastrouter",
.options = fastrouter_options,
.manage_opt = fastrouter_opt,
.init = fastrouter_init,
+85
View File
@@ -0,0 +1,85 @@
#include "../rack/uwsgi_rack.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_rack ur;
struct ufib {
VALUE *fib;
} ufiber;
struct option fiber_options[] = {
{ 0, 0, 0, 0 }
};
VALUE uwsgi_fiber_request() {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->suspended = 0;
return Qnil;
}
inline static void fiber_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
if (!uwsgi.wsgi_req->suspended) {
ufiber.fib[id] = rb_fiber_new(uwsgi_fiber_request, Qnil);
rb_gc_register_address(&ufiber.fib[id]);
uwsgi.wsgi_req->suspended = 1;
}
rb_fiber_resume(ufiber.fib[id], 0, NULL);
if (uwsgi.wsgi_req->suspended) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
}
}
inline static void fiber_schedule_to_main(struct wsgi_request *wsgi_req) {
rb_fiber_yield(0, NULL);
uwsgi.wsgi_req = wsgi_req;
}
VALUE protected_async_loop() {
async_loop(NULL);
return Qnil;
}
void fiber_loop() {
int error = 0;
ufiber.fib = uwsgi_malloc( sizeof(VALUE) * uwsgi.async );
uwsgi.schedule_to_main = fiber_schedule_to_main;
uwsgi.schedule_to_req = fiber_schedule_to_req;
// must run all the rack/ruby plugins without protection
ur.unprotected = 1;
rb_protect(protected_async_loop, 0, &error);
if (error) {
uwsgi_ruby_exception();
exit(1);
}
// never here
}
int fiber_init() {
uwsgi_register_loop( (char *) "fiber", fiber_loop);
return 0;
}
struct uwsgi_plugin fiber_plugin = {
.name = "fiber",
.init = fiber_init,
.options = fiber_options,
};
+27
View File
@@ -0,0 +1,27 @@
import os
try:
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
except:
RUBYPATH = 'ruby'
NAME='fiber'
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
if includedir == 'nil':
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
CFLAGS.append('-I' + includedir)
else:
CFLAGS.append('-I' + includedir)
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['arch']\"").read().rstrip()
CFLAGS.append('-I' + archdir)
CFLAGS.append('-I' + archdir + '/' + arch)
CFLAGS.append('-I' + includedir + '/' + arch)
LDFLAGS = []
LIBS = []
GCC_LIST = ['fiber']
+356
View File
@@ -0,0 +1,356 @@
#include "../python/uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
struct option gevent_options[] = {
{ 0, 0, 0, 0 }
};
#define GEVENT_SWITCH PyObject *gswitch = python_call(ugevent.greenlet_switch, ugevent.greenlet_switch_args, 0, NULL); Py_DECREF(gswitch)
#define GET_CURRENT_GREENLET python_call(ugevent.get_current, ugevent.get_current_args, 0, NULL)
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req
#define stop_the_watchers ret = PyObject_CallMethod(timer, "stop", NULL);\
if (ret) Py_DECREF(ret);\
ret = PyObject_CallMethod(watcher, "stop", NULL);\
if (ret) Py_DECREF(ret);
struct uwsgi_gevent {
PyObject *greenlet_switch;
PyObject *greenlet_switch_args;
PyObject *get_current;
PyObject *get_current_args;
PyObject *hub;
PyObject *hub_loop;
PyObject *spawn;
PyObject *greenlet_args;
PyObject *signal_args;
} ugevent;
PyObject *py_uwsgi_gevent_signal_handler(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
int signal_socket;
if (!PyArg_ParseTuple(args, "i:uwsgi_gevent_signal_handler", &signal_socket)) {
return NULL;
}
if (read(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);
}
// close the socket to end the mess...from now on the worker is alone (no master)
else close(signal_socket);
}
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);
}
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_gevent_signal(PyObject * self, PyObject * args) {
PyTuple_SetItem(ugevent.signal_args, 1, PyInt_FromLong(uwsgi.signal_socket));
// spawn the signal_handler greenlet
PyObject *new_gl = python_call(ugevent.spawn, ugevent.signal_args, 0, NULL);
Py_DECREF(new_gl);
Py_INCREF(Py_None);
return Py_None;
}
// yes copy&paste no-DRY for me :P
PyObject *py_uwsgi_gevent_my_signal(PyObject * self, PyObject * args) {
PyTuple_SetItem(ugevent.signal_args, 1, PyInt_FromLong(uwsgi.my_signal_socket));
// spawn the signal_handler greenlet
PyObject *new_gl = python_call(ugevent.spawn, ugevent.signal_args, 0, NULL);
Py_DECREF(new_gl);
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = find_first_available_wsgi_req();
if (wsgi_req == NULL) {
uwsgi_log("async queue is full !!!\n");
goto clear;
}
uwsgi.wsgi_req = wsgi_req;
// fill wsgi_request structure
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi.sockets );
// mark core as used
uwsgi.core[wsgi_req->async_id]->in_request = 1;
gettimeofday(&wsgi_req->start_of_request, NULL);
// enter harakiri mode
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// accept the connection
if (wsgi_req_simple_accept(wsgi_req, uwsgi.sockets->fd)) {
uwsgi_close_request(wsgi_req);
free_req_queue;
goto clear;
}
// hack to easily pass wsgi_req pointer to the greenlet
PyTuple_SetItem(ugevent.greenlet_args, 1, PyLong_FromLong((long)wsgi_req));
// spawn the request greenlet
PyObject *new_gl = python_call(ugevent.spawn, ugevent.greenlet_args, 0, NULL);
Py_DECREF(new_gl);
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *uwsgi_gevent_wait(PyObject *watcher, PyObject *timer, PyObject *current) {
PyObject *ret;
// start the io watcher
ret = PyObject_CallMethod(watcher, "start", "OO", current, watcher);
if (!ret) return NULL;
Py_DECREF(ret);
// start the timeout handler
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
if (!ret) return NULL;
Py_DECREF(ret);
// pass control to the hub
return PyObject_CallMethod(ugevent.hub, "switch", NULL);
}
PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
PyObject *ret;
PyObject *py_wsgi_req = PyTuple_GetItem(args, 0);
struct wsgi_request *wsgi_req = (struct wsgi_request *) PyLong_AsLong(py_wsgi_req);
int status ;
PyObject *current_greenlet = GET_CURRENT_GREENLET;
PyObject *greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");
uwsgi.wsgi_req = wsgi_req;
// create a watcher for request socket
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
if (!watcher) goto clear1;
// a timer to implement timeoit (thanks Denis)
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (!timer) goto clear0;
for(;;) {
// wait for data in the socket
PyObject *ret = uwsgi_gevent_wait(watcher, timer, greenlet_switch);
if (!ret) goto clear_and_stop;
// do not forget to overwrite this pointer each time !!!
uwsgi.wsgi_req = wsgi_req;
// we can safely decref here as watcher and timer has got a +1 for start() method
Py_DECREF(ret);
if (ret == timer) {
uwsgi_log( "timeout. skip request.\n");
goto clear_and_stop;
}
else if (ret == watcher) {
status = wsgi_req->socket->proto(wsgi_req);
if (status < 0) {
goto clear_and_stop;
}
else if (status == 0) {
stop_the_watchers;
break;
}
}
else {
uwsgi_log("unrecognized gevent event !!!\n");
goto clear_and_stop;
}
stop_the_watchers;
}
for(;;) {
uwsgi.wsgi_req = wsgi_req;
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);
if (wsgi_req->async_status <= UWSGI_OK) {
goto clear;
}
// switch after each yield
GEVENT_SWITCH;
}
goto clear;
clear_and_stop:
stop_the_watchers;
clear:
Py_DECREF(timer);
clear0:
Py_DECREF(watcher);
clear1:
Py_DECREF(greenlet_switch);
Py_DECREF(current_greenlet);
uwsgi_close_request(wsgi_req);
uwsgi.wsgi_req = wsgi_req;
free_req_queue;
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef uwsgi_gevent_main_def[] = { {"uwsgi_gevent_main", py_uwsgi_gevent_main, METH_VARARGS, ""} };
PyMethodDef uwsgi_gevent_request_def[] = { {"uwsgi_gevent_request", py_uwsgi_gevent_request, METH_VARARGS, ""} };
PyMethodDef uwsgi_gevent_signal_def[] = { {"uwsgi_gevent_signal", py_uwsgi_gevent_signal, METH_VARARGS, ""} };
PyMethodDef uwsgi_gevent_my_signal_def[] = { {"uwsgi_gevent_my_signal", py_uwsgi_gevent_my_signal, METH_VARARGS, ""} };
PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler", py_uwsgi_gevent_signal_handler, METH_VARARGS, ""} };
void gevent_loop() {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
if (uwsgi.async < 2) {
uwsgi_log("the gevent loop engine requires async mode (--async <n>)\n");
exit(1);
}
PyObject *gevent_dict = get_uwsgi_pydict("gevent");
if (!gevent_dict) uwsgi_pyexit;
PyObject *gevent_version = PyDict_GetItemString(gevent_dict, "version_info");
if (!gevent_version) uwsgi_pyexit;
if (PyInt_AsLong(PyTuple_GetItem(gevent_version, 0)) < 1) {
uwsgi_log("uWSGI requires at least gevent 1.x version\n");
exit(1);
}
ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn");
if (!ugevent.spawn) uwsgi_pyexit;
ugevent.greenlet_switch = PyDict_GetItemString(gevent_dict, "sleep");
if (!ugevent.greenlet_switch) uwsgi_pyexit;
ugevent.greenlet_switch_args = PyTuple_New(0);
Py_INCREF(ugevent.greenlet_switch_args);
PyObject *gevent_get_hub = PyDict_GetItemString(gevent_dict, "get_hub");
ugevent.hub = python_call(gevent_get_hub, PyTuple_New(0), 0, NULL);
if (!ugevent.hub) uwsgi_pyexit;
ugevent.get_current = PyDict_GetItemString(gevent_dict, "getcurrent");
if (!ugevent.get_current) uwsgi_pyexit;
ugevent.get_current_args = PyTuple_New(0);
Py_INCREF(ugevent.get_current_args);
ugevent.hub_loop = PyObject_GetAttrString(ugevent.hub, "loop");
if (!ugevent.hub_loop) uwsgi_pyexit;
// this is the watcher for server socket
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi_sock->fd, 1);
if (!watcher) uwsgi_pyexit;
// main greenlet waiting for connection
PyObject *uwsgi_gevent_main = PyCFunction_New(uwsgi_gevent_main_def, NULL);
Py_INCREF(uwsgi_gevent_main);
// greenlet to run at each request
PyObject *uwsgi_request_greenlet = PyCFunction_New(uwsgi_gevent_request_def, NULL);
Py_INCREF(uwsgi_request_greenlet);
// pre-fill the greenlet args
ugevent.greenlet_args = PyTuple_New(2);
PyTuple_SetItem(ugevent.greenlet_args, 0, uwsgi_request_greenlet);
if (uwsgi.signal_socket > -1) {
// and these are the watcher for signal sockets
PyObject *signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.signal_socket, 1);
if (!signal_watcher) uwsgi_pyexit;
PyObject *my_signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.my_signal_socket, 1);
if (!my_signal_watcher) uwsgi_pyexit;
PyObject *uwsgi_greenlet_signal = PyCFunction_New(uwsgi_gevent_signal_def, NULL);
Py_INCREF(uwsgi_greenlet_signal);
PyObject *uwsgi_greenlet_my_signal = PyCFunction_New(uwsgi_gevent_my_signal_def, NULL);
Py_INCREF(uwsgi_greenlet_my_signal);
PyObject *uwsgi_greenlet_signal_handler = PyCFunction_New(uwsgi_gevent_signal_handler_def, NULL);
Py_INCREF(uwsgi_greenlet_signal_handler);
ugevent.signal_args = PyTuple_New(2);
PyTuple_SetItem(ugevent.signal_args, 0, uwsgi_greenlet_signal_handler);
// start the two signal watchers
if (!PyObject_CallMethod(signal_watcher, "start", "O", uwsgi_greenlet_signal)) uwsgi_pyexit;
if (!PyObject_CallMethod(my_signal_watcher, "start", "O", uwsgi_greenlet_my_signal)) uwsgi_pyexit;
}
// start the main greenlet
PyObject_CallMethod(watcher, "start", "O", uwsgi_gevent_main);
if (!PyObject_CallMethod(ugevent.hub, "join", NULL)) {
PyErr_Print();
}
uwsgi_log("the gevent Hub is no more :(\n");
}
int gevent_init() {
uwsgi_register_loop( (char *) "gevent", gevent_loop);
return 0;
}
struct uwsgi_plugin gevent_plugin = {
.name = "gevent",
.init = gevent_init,
.options = gevent_options,
};
+8
View File
@@ -0,0 +1,8 @@
from distutils import sysconfig
NAME='gevent'
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
LDFLAGS = []
LIBS = []
GCC_LIST = ['gevent']
+44 -15
View File
@@ -136,6 +136,8 @@ struct http_session {
char uss[MAX_HTTP_VEC*2];
char buffer[UMAX16];
char path_info[UMAX16];
uint16_t path_info_len;
struct uwsgi_subscriber_name *un;
@@ -145,13 +147,13 @@ struct http_session {
struct uwsgi_rb_timer *timeout;
};
struct uwsgi_rb_timer *reset_timeout(struct http_session *uhttp_session) {
static struct uwsgi_rb_timer *reset_timeout(struct http_session *uhttp_session) {
del_timeout(uhttp_session);
return add_timeout(uhttp_session);
}
void close_session(struct http_session **uhttp_table, struct http_session *uhttp_session) {
static void close_session(struct http_session **uhttp_table, struct http_session *uhttp_session) {
close(uhttp_session->fd);
uhttp_table[uhttp_session->fd] = NULL;
@@ -170,7 +172,7 @@ void close_session(struct http_session **uhttp_table, struct http_session *uhttp
}
void expire_timeouts(struct http_session **uhttp_table) {
static void expire_timeouts(struct http_session **uhttp_table) {
time_t current = time(NULL);
struct uwsgi_rb_timer *urbt;
@@ -325,13 +327,19 @@ int http_parse(struct http_session *h_session) {
base = ptr;
while(ptr < watermark) {
if (*ptr == '?' && !query_string) {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, base, ptr-base, &c);
// PATH_INFO must be url-decoded !!!
h_session->path_info_len = ptr-base;
http_url_decode(base, &h_session->path_info_len, h_session->path_info);
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, h_session->path_info, h_session->path_info_len, &c);
query_string = ptr+1;
}
else if (*ptr == ' ') {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "REQUEST_URI", 11, base, ptr-base, &c);
if (!query_string) {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, base, ptr-base, &c);
// PATH_INFO must be url-decoded !!!
h_session->path_info_len = ptr-base;
http_url_decode(base, &h_session->path_info_len, h_session->path_info);
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, h_session->path_info, h_session->path_info_len, &c);
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "QUERY_STRING", 12, "", 0, &c);
}
else {
@@ -403,6 +411,14 @@ int http_parse(struct http_session *h_session) {
ptr++;
}
int i;
for(i=0;i<uhttp.http_vars_cnt;i++) {
char *equal = strchr(uhttp.http_vars[i],'=');
if (equal) {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, uhttp.http_vars[i], equal-uhttp.http_vars[i], equal+1, strlen(equal+1), &c);
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("vec size: %d pkt size: %d load %d\n", c, h_session->uh.pktsize, uhttp.load);
#endif
@@ -429,12 +445,14 @@ void http_loop() {
struct uwsgi_rb_timer *min_timeout;
void *events;
#ifndef __sun__
struct msghdr msg;
union {
struct cmsghdr cmsg;
char control [CMSG_SPACE (sizeof (int))];
} msg_control;
struct cmsghdr *cmsg;
#endif
union uwsgi_sockaddr uhttp_addr;
socklen_t uhttp_addr_len = sizeof(struct sockaddr_un);
@@ -540,7 +558,7 @@ void http_loop() {
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf+4, len-4, http_manage_subscription, &usr);
uwsgi_add_subscriber(uhttp.subscription_dict, usr.key, usr.keylen, usr.address, usr.address_len);
uwsgi_add_subscriber(uhttp.subscription_dict, &usr);
}
}
else {
@@ -626,9 +644,9 @@ void http_loop() {
uhttp_session->instance_address_len = uhttp_session->un->len;
}
}
else if (uwsgi.sockets_cnt > 0) {
uhttp_session->instance_address = uwsgi.sockets[0].name;
uhttp_session->instance_address_len = strlen(uwsgi.sockets[0].name);
else if (uwsgi.sockets) {
uhttp_session->instance_address = uwsgi.sockets->name;
uhttp_session->instance_address_len = strlen(uwsgi.sockets->name);
}
if (!uhttp_session->instance_address_len) {
@@ -637,6 +655,7 @@ void http_loop() {
}
uhttp_session->pass_fd = is_unix(uhttp_session->instance_address, uhttp_session->instance_address_len);
uhttp_session->instance_fd = uwsgi_connectn(uhttp_session->instance_address, uhttp_session->instance_address_len, 0, 1);
@@ -705,8 +724,10 @@ void http_loop() {
uhttp_session->iov_len++;
}
#ifndef __sun__
// fd passing: PERFORMANCE EXTREME BOOST !!!
if (uhttp_session->pass_fd && !uhttp_session->remains) {
if (uhttp_session->pass_fd && !uhttp_session->remains && !uwsgi.no_fd_passing) {
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = uhttp_session->iov;
@@ -736,6 +757,7 @@ void http_loop() {
break;
}
#endif
#ifdef __sun__
if (uhttp_session->iov_len > IOV_MAX) {
int remains = uhttp_session->iov_len;
@@ -863,22 +885,27 @@ int http_init() {
if (!uhttp.nevents) uhttp.nevents = 64;
if (!uhttp.base && !uhttp.use_cache && !uhttp.to && !uwsgi.sockets_cnt && !uhttp.subscription_server && !uhttp.use_cluster) {
uwsgi.sockets[0].name = uwsgi_malloc(64);
uwsgi.sockets_cnt++;
snprintf(uwsgi.sockets[0].name, 64, "%d_%d.sock", (int) time(NULL), (int) getpid());
if (!uhttp.base && !uhttp.use_cache && !uhttp.to && !uwsgi.sockets && !uhttp.subscription_server && !uhttp.use_cluster) {
uwsgi_new_socket(uwsgi_concat2("127.0.0.1:0", ""));
}
uhttp.server = bind_to_tcp(uhttp.socket_name, uwsgi.listen_queue, strchr(uhttp.socket_name,':'));
if (register_gateway("http", http_loop) == NULL) {
if (register_gateway("uWSGI http", http_loop) == NULL) {
uwsgi_log("unable to register the http gateway\n");
exit(1);
}
uwsgi_log("HTTP router/proxy bound on %s\n", uhttp.socket_name);
}
return 0;
}
struct uwsgi_help_item http_help[] = {
{ "http-to <addr>", "forward http requests to uwsgi instance bound at <addr>"},
{ 0, 0 }
};
int http_opt(int i, char *optarg) {
@@ -929,8 +956,10 @@ int http_opt(int i, char *optarg) {
struct uwsgi_plugin http_plugin = {
.name = "http",
.options = http_options,
.manage_opt = http_opt,
.help = http_help,
.init = http_init,
};
+10
View File
@@ -16,6 +16,16 @@ NAME='jvm'
JVM_INCPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.15/include/linux"
JVM_LIBPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/i386/server/"
try:
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
except:
pass
try:
JVM_LIBPATH = os.environ['UWSGICONFIG_JVM_LIBPATH']
except:
pass
try:
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
except:
+95 -25
View File
@@ -374,7 +374,7 @@ void uwsgi_lua_app() {
luaL_openlibs(ulua.L[i]);
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
uwsgi_log("unable to load file %s\n", ulua.filename);
uwsgi_log("unable to load file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
exit(1);
}
// use a pcall
@@ -403,8 +403,7 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
if ((i = lua_pcall(L, 0, 1, 0)) == 0) {
if (lua_type(L, -1) == LUA_TSTRING) {
http = lua_tolstring(L, -1, &slen);
if ( (rlen = write(wsgi_req->poll.fd, http, slen)) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
return UWSGI_OK;
}
wsgi_req->response_size += rlen;
@@ -420,12 +419,12 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
/* Standard WSAPI request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log( "Invalid WSAPI request. skip.\n");
goto clear;
goto clear2;
}
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid WSAPI request. skip.\n");
goto clear;
goto clear2;
}
// put function in the stack
@@ -453,12 +452,16 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
lua_setfield(L, -2, "read");
lua_setfield(L, -2, "input");
#ifdef UWSGI_DEBUG
uwsgi_log("stack pos %d\n", lua_gettop(L));
#endif
// call function
i = lua_pcall(L, 1, 3, 0);
if (i != 0) {
uwsgi_log("%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
lua_pushvalue(L, -1);
goto clear;
}
@@ -468,26 +471,30 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
// send status
if (lua_type(L, -3) == LUA_TSTRING || lua_type(L, -3) == LUA_TNUMBER) {
http = lua_tolstring(L, -3, &slen);
if (write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len) != wsgi_req->protocol_len) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len)) != wsgi_req->protocol_len) {
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, " ", 1) != 1) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, " ", 1)) != 1) {
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
// a performance hack
ptrbuf = (char *) http;
ptrbuf[3] = 0;
wsgi_req->status = atoi(ptrbuf);
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
}
else {
raw = 1;
@@ -499,31 +506,41 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
lua_pushnil(L);
while(lua_next(L, -3) != 0) {
http = lua_tolstring(L, -2, &slen);
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, ": ", 2) != 2) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, ": ", 2)) != 2) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
http = lua_tolstring(L, -1, &slen);
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
lua_pop(L, 1);
wsgi_req->header_cnt++;
}
if (!raw) {
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
}
// send body with coroutine
@@ -532,8 +549,9 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
while ( (i = lua_pcall(L, 0, 1, 0)) == 0) {
if (lua_type(L, -1) == LUA_TSTRING) {
http = lua_tolstring(L, -1, &slen);
if ( (rlen = write(wsgi_req->poll.fd, http, slen)) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pop(L, 1);
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->response_size += rlen;
@@ -550,6 +568,7 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
clear:
lua_pop(L, 4);
clear2:
// set frequency
lua_gc(L, LUA_GCCOLLECT, 0);
@@ -590,6 +609,55 @@ int uwsgi_lua_magic(char *mountpoint, char *lazy) {
return 0;
}
char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, uint16_t keylen) {
static struct lua_State *L = NULL;
if (!L) {
L = luaL_newstate();
luaL_openlibs(L);
if (luaL_loadfile(L, code) || lua_pcall(L, 0, 0, 0)) {
uwsgi_log("unable to load file %s: %s\n", code, lua_tostring(L, -1));
lua_close(L);
L = NULL;
return NULL;
}
lua_getglobal(L, func);
if (!lua_isfunction(L,-1)) {
uwsgi_log("unable to find %s function in lua file %s\n", func, code);
lua_close(L);
L = NULL;
return NULL;
}
lua_pushnil(L);
}
lua_pop(L, 1);
lua_pushvalue(L, -1);
lua_pushlstring(L, key, keylen);
#ifdef UWSGI_DEBUG
uwsgi_log("stack pos %d %.*s\n", lua_gettop(L), keylen, key);
#endif
if (lua_pcall(L, 1, 1, 0) != 0) {
uwsgi_log("CAZZO\n");
uwsgi_log("error running function `f': %s",
lua_tostring(L, -1));
return NULL;
}
if (lua_isstring(L, -1)) {
const char *ret = lua_tolstring(L, -1, NULL);
return (char *)ret;
}
return NULL;
}
int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -664,6 +732,8 @@ struct uwsgi_plugin lua_plugin = {
.init_apps = uwsgi_lua_app,
.magic = uwsgi_lua_magic,
.signal_handler = uwsgi_lua_signal_handler,
.code_string = uwsgi_lua_code_string,
.rpc = uwsgi_lua_rpc,
};
+16 -13
View File
@@ -16,17 +16,17 @@ struct option nagios_options[] = {
int nagios() {
char *tcp_port;
struct pollfd nagios_poll;
struct wsgi_request nagios_req;
// connect and send
if (!use_nagios) {
return 1;
}
if (uwsgi.sockets[0].name == NULL) {
if (!uwsgi.sockets) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port = strchr(uwsgi.sockets[0].name, ':');
tcp_port = strchr(uwsgi.sockets->name, ':');
if (tcp_port == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
@@ -34,27 +34,30 @@ int nagios() {
tcp_port[0] = 0;
nagios_poll.fd = connect_to_tcp(uwsgi.sockets[0].name, atoi(tcp_port + 1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (nagios_poll.fd < 0) {
int fd = connect_to_tcp(uwsgi.sockets->name, atoi(tcp_port + 1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) {
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
exit(2);
}
uwsgi.wsgi_req->uh.modifier1 = UWSGI_MODIFIER_PING;
uwsgi.wsgi_req->uh.pktsize = 0;
uwsgi.wsgi_req->uh.modifier2 = 0;
if (write(nagios_poll.fd, uwsgi.wsgi_req, 4) != 4) {
nagios_req.uh.modifier1 = UWSGI_MODIFIER_PING;
nagios_req.uh.pktsize = 0;
nagios_req.uh.modifier2 = 0;
if (write(fd, &nagios_req.uh, 4) != 4) {
uwsgi_error("write()");
fprintf(stdout, "UWSGI CRITICAL: could not send ping packet to workers\n");
exit(2);
}
nagios_poll.events = POLLIN;
if (!uwsgi_parse_response(&nagios_poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) uwsgi.wsgi_req, uwsgi.wsgi_req->buffer)) {
nagios_req.poll.fd = fd;
nagios_req.poll.events = POLLIN;
if (!uwsgi_parse_packet(&nagios_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
fprintf(stdout, "UWSGI CRITICAL: timed out waiting for response\n");
exit(2);
}
else {
if (uwsgi.wsgi_req->uh.pktsize > 0) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", uwsgi.wsgi_req->uh.pktsize, uwsgi.wsgi_req->buffer);
if (nagios_req.uh.pktsize > 0) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", nagios_req.uh.pktsize, nagios_req.buffer);
exit(1);
}
else {
+18 -11
View File
@@ -15,32 +15,38 @@ struct option uwsgi_ping_options[] = {
static void ping() {
struct uwsgi_header uh;
struct pollfd uwsgi_poll;
struct wsgi_request ping_req;
char *buf = uwsgi_malloc(uwsgi.buffer_size);
// use a 3 secs timeout by default
if (!uping.ping_timeout) uping.ping_timeout = 3;
uwsgi_log("PING uwsgi host %s (timeout: %d)\n", uping.ping, uping.ping_timeout);
uwsgi_poll.fd = uwsgi_connect(uping.ping, uping.ping_timeout, 0);
if (uwsgi_poll.fd < 0) {
int fd = uwsgi_connect(uping.ping, uping.ping_timeout, 0);
if (fd < 0) {
exit(1);
}
uh.modifier1 = UWSGI_MODIFIER_PING;
uh.pktsize = 0;
uh.modifier2 = 0;
if (write(uwsgi_poll.fd, &uh, 4) != 4) {
memset(&ping_req, 0, sizeof(struct wsgi_request));
ping_req.uh.modifier1 = UWSGI_MODIFIER_PING;
ping_req.uh.pktsize = 0;
ping_req.uh.modifier2 = 0;
if (write(fd, &ping_req.uh, 4) != 4) {
uwsgi_error("write()");
exit(2);
}
uwsgi_poll.events = POLLIN;
if (!uwsgi_parse_response(&uwsgi_poll, uping.ping_timeout, &uh, NULL)) {
ping_req.poll.fd = fd;
ping_req.poll.events = POLLIN;
ping_req.buffer = buf;
if (!uwsgi_parse_packet(&ping_req, uping.ping_timeout)) {
exit(1);
}
else {
if (uh.pktsize > 0) {
if (ping_req.uh.pktsize > 0) {
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, ping_req.uh.pktsize, buf);
exit(2);
}
else {
@@ -92,6 +98,7 @@ int uwsgi_ping_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PING:
uwsgi.no_server = 1;
uping.ping = optarg;
return 1;
case LONG_ARGS_PING_TIMEOUT:
-490
View File
@@ -1,490 +0,0 @@
/*
uWSGI proxy
it needs one of this tecnology to work:
- epoll (linux 2.6)
- kqueue (various BSD and Darwin)
- /dev/poll (Solaris)
*/
#include "../../uwsgi.h"
#define LONG_ARGS_PROXY_WORKERS 50000
struct uwsgi_proxy {
char *socket_name;
int add_me;
int workers;
int fd;
} uproxy;
struct option proxy_options[] = {
{"proxy", required_argument, 0, LONG_ARGS_PROXY},
{"proxy-node", required_argument, 0, LONG_ARGS_PROXY_NODE},
{"proxy-max-connections", required_argument, 0, LONG_ARGS_PROXY_MAX_CONNECTIONS},
{"proxy-workers", required_argument, 0, LONG_ARGS_PROXY_WORKERS},
{0, 0, 0, 0},
};
#define UWSGI_PROXY_CONNECTING 1
#define UWSGI_PROXY_WAITING 2
extern struct uwsgi_server uwsgi;
struct uwsgi_proxy_connection {
int dest_fd;
int status;
int retry;
int node;
};
static void end_proxy(void) {
exit(UWSGI_END_CODE);
}
static void reload_proxy(void) {
exit(UWSGI_RELOAD_CODE);
}
static void uwsgi_proxy_close(struct uwsgi_proxy_connection *upcs, int fd) {
if (upcs[fd].dest_fd >= 0) {
close(upcs[fd].dest_fd);
upcs[upcs[fd].dest_fd].dest_fd = -1;
upcs[upcs[fd].dest_fd].status = 0;
upcs[upcs[fd].dest_fd].retry = 0;
if (upcs[upcs[fd].dest_fd].node > -1) {
if (uwsgi.shared->nodes[upcs[upcs[fd].dest_fd].node].connections > 0)
uwsgi.shared->nodes[upcs[upcs[fd].dest_fd].node].connections--;
}
}
if (fd >= 0) {
close(fd);
upcs[fd].dest_fd = -1;
upcs[fd].status = 0;
upcs[fd].retry = 0;
if (upcs[fd].node > -1) {
if (uwsgi.shared->nodes[upcs[fd].node].connections > 0)
uwsgi.shared->nodes[upcs[fd].node].connections--;
}
}
}
static int uwsgi_proxy_find_next_node(int current_node) {
int i;
current_node++;
if (current_node >= MAX_CLUSTER_NODES) {
current_node = 0;
}
// is it a good node ?
if (uwsgi.shared->nodes[current_node].name[0] != 0 && uwsgi.shared->nodes[current_node].status == UWSGI_NODE_OK) {
if (uwsgi.shared->nodes[current_node].connections < uwsgi.shared->nodes[current_node].workers)
return current_node;
}
// try to find a better one
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
if (uwsgi.shared->nodes[i].name[0] != 0 && uwsgi.shared->nodes[i].status == UWSGI_NODE_OK) {
if (uwsgi.shared->nodes[i].connections < uwsgi.shared->nodes[i].workers)
return i;
}
}
// ok, it is a very loaded system, fallback to round robin
if (uwsgi.shared->nodes[current_node].name[0] != 0 && uwsgi.shared->nodes[current_node].status == UWSGI_NODE_OK) {
return current_node;
}
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
if (uwsgi.shared->nodes[i].name[0] != 0 && uwsgi.shared->nodes[i].status == UWSGI_NODE_OK) {
return i;
}
}
return -1;
}
void proxy_loop() {
int efd;
#ifdef __linux__
struct epoll_event *eevents;
struct epoll_event ev;
#elif defined(__sun__)
struct pollfd *eevents;
struct pollfd ev;
#else
struct kevent *eevents;
struct kevent ev;
#endif
int max_events = 64;
int nevents, i;
const int nonblocking = 1;
const int blocking = 0;
char buffer[4096];
ssize_t rlen;
ssize_t wlen;
int max_connections = sysconf(_SC_OPEN_MAX);
int soopt;
socklen_t solen = sizeof(int);
int rc;
struct uwsgi_proxy_connection *upcs;
struct sockaddr_in upc_addr;
socklen_t upc_len = sizeof(struct sockaddr_in);
int next_node = -1;
#ifdef UWSGI_DEBUG
uwsgi_log( "allocating space for %d concurrent proxy connections\n", max_connections);
#endif
// allocate memory for connections
upcs = malloc(sizeof(struct uwsgi_proxy_connection) * max_connections);
if (!upcs) {
uwsgi_error("malloc()");
exit(1);
}
memset(upcs, 0, sizeof(struct uwsgi_proxy_connection) * max_connections);
if (uproxy.add_me) {
uwsgi_cluster_simple_add_node(uwsgi.sockets[0].name, 1, CLUSTER_NODE_STATIC);
}
efd = async_queue_init(uproxy.fd);
if (efd < 0) {
exit(1);
}
#ifdef __linux__
eevents = malloc(sizeof(struct epoll_event) * max_events);
memset(&ev, 0, sizeof(struct epoll_event));
#elif defined(__sun)
eevents = malloc(sizeof(struct pollfd) * max_events);
memset(&ev, 0, sizeof(struct pollfd));
#else
eevents = malloc(sizeof(struct kevent) * max_events);
memset(&ev, 0, sizeof(struct kevent));
#endif
if (!eevents) {
uwsgi_error("malloc()");
exit(1);
}
signal(SIGINT, (void *) &end_proxy);
signal(SIGTERM, (void *) &reload_proxy);
signal(SIGHUP, (void *) &reload_proxy);
// and welcome to the loop...
for (;;) {
nevents = async_wait(efd, eevents, max_events, -1, 0);
if (nevents < 0) {
uwsgi_error("epoll_wait()");
continue;
}
for (i = 0; i < nevents; i++) {
if ( (int)eevents[i].ASYNC_FD == uproxy.fd) {
if (eevents[i].ASYNC_IS_IN) {
// new connection, accept it
ev.ASYNC_FD = accept(uproxy.fd, (struct sockaddr *) &upc_addr, &upc_len);
if ( (int) ev.ASYNC_FD < 0) {
uwsgi_error("accept()");
continue;
}
upcs[ev.ASYNC_FD].node = -1;
// now connect to the first worker available
upcs[ev.ASYNC_FD].dest_fd = socket(AF_INET, SOCK_STREAM, 0);
if (upcs[ev.ASYNC_FD].dest_fd < 0) {
uwsgi_error("socket()");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[upcs[ev.ASYNC_FD].dest_fd].node = -1;
// set nonblocking
if (ioctl(upcs[ev.ASYNC_FD].dest_fd, FIONBIO, &nonblocking)) {
uwsgi_error("ioctl()");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[ev.ASYNC_FD].status = 0;
upcs[ev.ASYNC_FD].retry = 0;
next_node = uwsgi_proxy_find_next_node(next_node);
if (next_node == -1) {
uwsgi_log( "unable to find an available worker in the cluster !\n");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[upcs[ev.ASYNC_FD].dest_fd].node = next_node;
rc = connect(upcs[ev.ASYNC_FD].dest_fd, (struct sockaddr *) &uwsgi.shared->nodes[next_node].ucn_addr, sizeof(struct sockaddr_in));
uwsgi.shared->nodes[next_node].connections++;
if (!rc) {
// connected to worker, put it in the epoll_list
if (async_add(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[upcs[ev.ASYNC_FD].dest_fd].dest_fd = ev.ASYNC_FD;
upcs[upcs[ev.ASYNC_FD].dest_fd].status = 0;
upcs[upcs[ev.ASYNC_FD].dest_fd].retry = 0;
ev.ASYNC_FD = upcs[ev.ASYNC_FD].dest_fd;
if (async_add(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
// re-set blocking
if (ioctl(upcs[upcs[ev.ASYNC_FD].dest_fd].dest_fd, FIONBIO, &blocking)) {
uwsgi_error("ioctl()");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
else if (errno == EINPROGRESS) {
// the socket is waiting, set status to CONNECTING
upcs[ev.ASYNC_FD].status = UWSGI_PROXY_WAITING;
upcs[upcs[ev.ASYNC_FD].dest_fd].dest_fd = ev.ASYNC_FD;
upcs[upcs[ev.ASYNC_FD].dest_fd].status = UWSGI_PROXY_CONNECTING;
upcs[upcs[ev.ASYNC_FD].dest_fd].retry = 0;
ev.ASYNC_FD = upcs[ev.ASYNC_FD].dest_fd;
if (async_add(efd, ev.ASYNC_FD, ASYNC_OUT)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
else {
// connection failed, retry with the next node ?
uwsgi_error("connect()");
// close only when all node are tried
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
else {
uwsgi_log( "!!! something horrible happened to the uWSGI proxy, reloading it !!!\n");
exit(1);
}
}
else {
// this is for clients/workers
if (eevents[i].ASYNC_IS_IN) {
// is this a connected client/worker ?
//uwsgi_log("ready %d\n", upcs[eevents[i].data.fd].status);
if (!upcs[eevents[i].ASYNC_FD].status) {
if (upcs[eevents[i].ASYNC_FD].dest_fd >= 0) {
rlen = read(eevents[i].ASYNC_FD, buffer, 4096);
if (rlen < 0) {
uwsgi_error("read()");
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
else if (rlen == 0) {
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
else {
wlen = write(upcs[eevents[i].ASYNC_FD].dest_fd, buffer, rlen);
if (wlen != rlen) {
uwsgi_error("write()");
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
}
}
else {
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
}
else if (upcs[eevents[i].ASYNC_FD].status == UWSGI_PROXY_WAITING) {
// disconnected node
continue;
}
else {
uwsgi_log( "UNKNOWN STATUS %d\n", upcs[eevents[i].ASYNC_FD].status);
continue;
}
}
else if (eevents[i].ASYNC_IS_OUT) {
if (upcs[eevents[i].ASYNC_FD].status == UWSGI_PROXY_CONNECTING) {
#ifdef UWSGI_PROXY_USE_KQUEUE
if (getsockopt(eevents[i].ASYNC_FD, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
/* is something bad ? */
if (soopt) {
uwsgi_log( "connect() %s\n", strerror(soopt));
// increase errors on node
uwsgi_log( "*** marking cluster node %d/%s as failed ***\n", upcs[eevents[i].ASYNC_FD].node, uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name);
if (uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].type == CLUSTER_NODE_DYNAMIC) {
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name[0] = 0 ;
}
else {
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].errors++;
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].status = UWSGI_NODE_FAILED;
}
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
// increase errors on node
#endif
ev.ASYNC_FD = upcs[eevents[i].ASYNC_FD].dest_fd;
upcs[ev.ASYNC_FD].status = 0;
if (async_add(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
ev.ASYNC_FD = upcs[ev.ASYNC_FD].dest_fd;
upcs[ev.ASYNC_FD].status = 0;
if (async_mod(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
// re-set blocking
if (ioctl(ev.ASYNC_FD, FIONBIO, &blocking)) {
uwsgi_error("ioctl()");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
else {
uwsgi_log( "strange event for %d\n", (int) eevents[i].ASYNC_FD);
}
}
else {
if (upcs[eevents[i].ASYNC_FD].status == UWSGI_PROXY_CONNECTING) {
if (getsockopt(eevents[i].ASYNC_FD, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
}
/* is something bad ? */
if (soopt) {
uwsgi_log( "connect() %s\n", strerror(soopt));
}
// increase errors on node
uwsgi_log( "*** marking cluster node %d/%s as failed ***\n", upcs[eevents[i].ASYNC_FD].node, uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name);
if (uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].type == CLUSTER_NODE_DYNAMIC) {
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name[0] = 0;
}
else {
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].errors++;
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].status = UWSGI_NODE_FAILED;
}
}
else {
uwsgi_log( "STRANGE EVENT !!! %d %d %d\n", (int) eevents[i].ASYNC_FD, (int) eevents[i].ASYNC_EV, upcs[eevents[i].ASYNC_FD].status);
}
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
}
}
}
}
int proxy_init() {
int i;
char *tcp_port;
if (!uproxy.workers) uproxy.workers = 1 ;
if (uproxy.socket_name) {
tcp_port = strchr(uproxy.socket_name, ':');
if (tcp_port == NULL) {
uproxy.fd = bind_to_unix(uproxy.socket_name, UWSGI_LISTEN_QUEUE, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
else {
uproxy.fd = bind_to_tcp(uproxy.socket_name, UWSGI_LISTEN_QUEUE, tcp_port);
tcp_port[0] = ':';
}
if (uproxy.fd < 0) {
uwsgi_log( "unable to create the proxy server socket.\n");
exit(1);
}
for(i=0;i<uproxy.workers;i++) {
if (register_gateway("proxy", proxy_loop) == NULL) {
uwsgi_log("unable to register the proxy gateway\n");
}
}
}
return 0;
}
int proxy_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PROXY_NODE:
if (uwsgi.cluster_fd >= 0 && !strcmp(optarg, "@self")) {
uproxy.add_me = 1;
}
else {
uwsgi_cluster_simple_add_node(optarg, 1, CLUSTER_NODE_STATIC);
}
return 1;
case LONG_ARGS_PROXY:
uproxy.socket_name = optarg;
return 1;
case LONG_ARGS_PROXY_WORKERS:
uproxy.workers = atoi(optarg);
return 1;
}
return 0;
}
struct uwsgi_plugin proxy_plugin = {
.options = proxy_options,
.manage_opt = proxy_opt,
.init = proxy_init,
};
+19 -3
View File
@@ -1,6 +1,9 @@
#undef __USE_GNU
#include "../../uwsgi.h"
#ifdef __APPLE__
#define HAS_BOOL 1
#endif
#include <EXTERN.h>
#include <perl.h>
#include "XSUB.h"
@@ -11,17 +14,30 @@ struct uwsgi_perl {
int fd;
char *psgibuffer;
char *psgi;
char *locallib;
char *embedding[3];
PerlInterpreter *main;
pthread_key_t u_interpreter;
PerlInterpreter **interp;
SV *psgi_main;
SV **psgi_func;
CV *stream_responder;
HV *streaming_stash;
HV *input_stash;
HV *error_stash;
};
#define LONG_ARGS_PERL_BASE 17000 + ((5 + 1) * 100)
#define LONG_ARGS_PSGI LONG_ARGS_PERL_BASE + 1
#define LONG_ARGS_PERL_BASE 17000 + ((5 + 1) * 1000)
#define LONG_ARGS_PSGI LONG_ARGS_PERL_BASE + 1
#define LONG_ARGS_PERL_LOCAL_LIB LONG_ARGS_PERL_BASE + 2
void init_perl_embedded_module(void);
int psgi_response(struct wsgi_request *, PerlInterpreter *, AV*);
void uwsgi_psgi_app(void);
int psgi_response(struct wsgi_request *, AV*);
#define psgi_xs(func) newXS("uwsgi::" #func, XS_##func, "uwsgi")
#define psgi_check_args(x) if (items < x) Perl_croak(aTHX_ "Usage: uwsgi::%s takes %d arguments", __FUNCTION__ + 3, x)
SV *uwsgi_perl_obj_call(SV *, char *);
int uwsgi_perl_obj_can(SV *, char *, size_t);
+327
View File
@@ -0,0 +1,327 @@
#include "psgi.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_perl uperl;
XS(XS_input_seek) {
dXSARGS;
psgi_check_args(1);
XSRETURN(0);
}
XS(XS_error) {
dXSARGS;
psgi_check_args(0);
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.error_stash);
XSRETURN(1);
}
XS(XS_input) {
dXSARGS;
psgi_check_args(0);
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.input_stash);
XSRETURN(1);
}
XS(XS_stream)
{
dXSARGS;
struct wsgi_request *wsgi_req = current_wsgi_req();
psgi_check_args(1);
AV *response = (AV* ) SvREFCNT_inc(SvRV(ST(0))) ;
if (av_len(response) == 2) {
while (psgi_response(wsgi_req, response) != UWSGI_OK);
}
else if (av_len(response) == 1) {
while (psgi_response(wsgi_req, response) != UWSGI_OK);
SvREFCNT_dec(response);
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.streaming_stash);
XSRETURN(1);
}
else {
uwsgi_log("invalid PSGI response: array size %d\n", av_len(response));
}
SvREFCNT_dec(response);
XSRETURN(0);
}
XS(XS_input_read) {
dXSARGS;
struct wsgi_request *wsgi_req = current_wsgi_req();
int fd = -1;
char *tmp_buf;
ssize_t bytes = 0, len;
size_t remains;
SV *read_buf;
psgi_check_args(3);
read_buf = ST(1);
len = SvIV(ST(2));
// return empty string if no post_cl or pos >= post_cl
if (!wsgi_req->post_cl || (size_t) wsgi_req->post_pos >= wsgi_req->post_cl) {
sv_setpvn(read_buf, "", 0);
goto ret;
}
if (wsgi_req->body_as_file) {
fd = fileno((FILE *)wsgi_req->async_post);
}
else if (uwsgi.post_buffering > 0) {
fd = -1;
if (wsgi_req->post_cl <= (size_t) uwsgi.post_buffering) {
fd = fileno((FILE *)wsgi_req->async_post);
}
}
else {
fd = wsgi_req->poll.fd;
}
// return the whole input
if (len <= 0) {
remains = wsgi_req->post_cl;
}
else {
remains = len ;
}
if (remains + wsgi_req->post_pos > wsgi_req->post_cl) {
remains = wsgi_req->post_cl - wsgi_req->post_pos;
}
if (remains <= 0) {
sv_setpvn(read_buf, "", 0);
goto ret;
}
// data in memory ?
if (fd == -1) {
sv_setpvn(read_buf, wsgi_req->post_buffering_buf, remains);
bytes = remains;
wsgi_req->post_pos += remains;
}
tmp_buf = uwsgi_malloc(remains);
if (uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
free(tmp_buf);
croak("error waiting for wsgi.input data");
goto ret;
}
bytes = read(fd, tmp_buf, remains);
if (bytes < 0) {
free(tmp_buf);
croak("error reading wsgi.input data");
goto ret;
}
wsgi_req->post_pos += bytes;
sv_setpvn(read_buf, tmp_buf, bytes);
free(tmp_buf);
ret:
XSRETURN_IV(bytes);
}
XS(XS_streaming_close) {
dXSARGS;
psgi_check_args(0);
XSRETURN(0);
}
XS(XS_streaming_write) {
dXSARGS;
struct wsgi_request *wsgi_req = current_wsgi_req();
STRLEN blen;
char *body;
psgi_check_args(2);
body = SvPV(ST(1), blen);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, body, blen);
XSRETURN(0);
}
XS(XS_error_print) {
dXSARGS;
STRLEN blen;
char *body;
psgi_check_args(1);
if (items > 1) {
body = SvPV(ST(1), blen);
uwsgi_log("%.*s", blen, body);
}
XSRETURN(0);
}
/* automatically generated */
EXTERN_C void xs_init (pTHX);
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
EXTERN_C void
xs_init(pTHX)
{
char *file = __FILE__;
dXSUB_SYS;
/* DynaLoader is a special case */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
newXS("uwsgi::input::new", XS_input, "uwsgi::input");
newXS("uwsgi::input::read", XS_input_read, "uwsgi::input");
newXS("uwsgi::input::seek", XS_input_seek, "uwsgi::input");
uperl.input_stash = gv_stashpv("uwsgi::input", 0);
newXS("uwsgi::error::new", XS_error, "uwsgi::error");
newXS("uwsgi::error::print", XS_error_print, "uwsgi::print");
uperl.error_stash = gv_stashpv("uwsgi::error", 0);
uperl.stream_responder = newXS("uwsgi::stream", XS_stream, "uwsgi");
newXS("uwsgi::streaming::write", XS_streaming_write, "uwsgi::streaming");
newXS("uwsgi::streaming::close", XS_streaming_close, "uwsgi::streaming");
uperl.streaming_stash = gv_stashpv("uwsgi::streaming", 0);
#ifdef UWSGI_EMBEDDED
init_perl_embedded_module();
#endif
}
/* end of automagically generated part */
void uwsgi_psgi_app() {
struct stat stat_psgi;
int id = uwsgi_apps_cnt;
if (uperl.psgi) {
// two-pass loading: parse the script -> eval the script
if (uperl.locallib) {
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
uperl.embedding[2] = uperl.psgi;
if (perl_parse(uperl.main, xs_init, 3, uperl.embedding, NULL)) {
exit(1);
}
}
else {
uperl.embedding[1] = uperl.psgi;
if (perl_parse(uperl.main, xs_init, 2, uperl.embedding, NULL)) {
exit(1);
}
}
perl_eval_pv("use IO::Handle;", 0);
perl_eval_pv("use IO::File;", 0);
SV *dollar_zero = get_sv("0", GV_ADD);
sv_setsv(dollar_zero, newSVpv(uperl.psgi, 0));
SV *dollar_slash = get_sv("/", GV_ADD);
sv_setsv(dollar_slash, newRV_inc(newSViv(uwsgi.buffer_size)));
uperl.fd = open(uperl.psgi, O_RDONLY);
if (uperl.fd < 0) {
uwsgi_error_open(uperl.psgi);
exit(1);
}
if (fstat(uperl.fd, &stat_psgi)) {
uwsgi_error("fstat()");
exit(1);
}
uperl.psgibuffer = malloc(stat_psgi.st_size + 1);
if (!uperl.psgibuffer) {
uwsgi_error("malloc()");
exit(1);
}
if (read(uperl.fd, uperl.psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) {
uwsgi_error("read()");
exit(1);
}
uperl.psgibuffer[stat_psgi.st_size] = 0;
uperl.psgi_main = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
if (!uperl.psgi_main) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
if (uwsgi.threads < 2) {
free(uperl.psgibuffer);
close(uperl.fd);
}
struct uwsgi_app *wi = &uwsgi_apps[id];
memset(wi, 0, sizeof(struct uwsgi_app));
wi->modifier1 = 5;
wi->mountpoint = "";
wi->mountpoint_len = 0;
uwsgi_log("PSGI app %d (%s) loaded at %p\n", id, uperl.psgi, uperl.psgi_main);
uwsgi_apps_cnt++;
// check if we need to emulate fork() COW
int i;
if (uwsgi.mywid == 0) {
for(i=1;i<=uwsgi.numproc;i++) {
memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
}
}
}
}
+345 -245
View File
@@ -3,72 +3,308 @@
extern char **environ;
extern struct uwsgi_server uwsgi;
#ifdef __APPLE__
extern struct uwsgi_perl uperl;
#else
struct uwsgi_perl uperl;
#endif
struct option uwsgi_perl_options[] = {
{"psgi", required_argument, 0, LONG_ARGS_PSGI},
{"perl-local-lib", required_argument, 0, LONG_ARGS_PERL_LOCAL_LIB},
{0, 0, 0, 0},
};
extern struct http_status_codes hsc[];
XS(XS_stream)
{
dXSARGS;
struct wsgi_request *wsgi_req = current_wsgi_req();
SV *stack;
AV *response;
SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
uwsgi_log("args: %d %p\n", items, wsgi_req);
stack = ST(0);
uwsgi_log("type %d\n", SvTYPE(stack));
response = (AV* ) SvRV(stack) ;
SV *newobj;
// set current context ?
dTHX;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv( class, class_len)));
PUTBACK;
psgi_response(wsgi_req, my_perl, response);
call_method( "new", G_SCALAR);
//mXPUSHp("x", 1);
XSRETURN(0);
SPAGAIN;
newobj = POPs;
PUTBACK;
FREETMPS;
LEAVE;
return newobj;
}
SV *uwsgi_perl_call_stream(SV *func) {
SV *ret = NULL;
// set current context ?
dTHX;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( sv_2mortal(newRV((SV*) uperl.stream_responder)));
PUTBACK;
call_sv( func, G_SCALAR | G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
}
else {
ret = SvREFCNT_inc(POPs);
}
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
int ret;
// set current context ? needed for threading
dTHX;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(obj);
XPUSHs(sv_2mortal(newSVpv(method, len)));
PUTBACK;
call_method( "can", G_SCALAR);
SPAGAIN;
ret = SvROK(POPs);
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
/* automatically generated */
EXTERN_C void xs_init (pTHX);
SV *uwsgi_perl_obj_call(SV *obj, char *method) {
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
SV *ret = NULL;
EXTERN_C void
xs_init(pTHX)
{
char *file = __FILE__;
dXSUB_SYS;
dTHX;
dSP;
/* DynaLoader is a special case */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
ENTER;
SAVETMPS;
PUSHMARK(SP);
uperl.stream_responder = newXS("uwsgi::stream", XS_stream, "uwsgi");
XPUSHs(obj);
#ifdef UWSGI_EMBEDDED
init_perl_embedded_module();
PUTBACK;
call_method( method, G_SCALAR | G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
}
else {
ret = SvREFCNT_inc(POPs);
}
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
AV *ret = NULL;
dTHX;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(env);
PUTBACK;
call_sv(psgi_func, G_SCALAR | G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
internal_server_error(wsgi_req, "exception raised");
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
}
else {
ret = (AV *) SvREFCNT_inc(SvRV(POPs));
}
PUTBACK;
FREETMPS;
LEAVE;
return (AV *)ret;
}
SV *build_psgi_env(struct wsgi_request *wsgi_req) {
int i;
HV *env = newHV();
// fill perl hash
for(i=0;i<wsgi_req->var_cnt;i++) {
if (wsgi_req->hvec[i+1].iov_len > 0) {
// check for multiline header
if (hv_exists(env, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
SV **already_avalable_header = hv_fetch(env, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, 0);
STRLEN hlen;
char *old_value = SvPV(*already_avalable_header, hlen );
char *multiline_header = uwsgi_concat3n(old_value, hlen, ", ", 2, wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
if (!hv_store(env, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len,
newSVpv(multiline_header, hlen+wsgi_req->hvec[i+1].iov_len+2), 0)) { free(multiline_header); goto clear;}
free(multiline_header);
}
else {
if (!hv_store(env, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len,
newSVpv(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len), 0)) goto clear;
}
}
else {
if (!hv_store(env, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, newSVpv("", 0), 0)) goto clear;
}
//uwsgi_log("%.*s = %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
i++;
}
// psgi.version
AV *av = newAV();
av_store( av, 0, newSViv(1));
av_store( av, 1, newSViv(1));
if (!hv_store(env, "psgi.version", 12, newRV_noinc((SV *)av ), 0)) goto clear;
if (uwsgi.numproc > 1) {
if (!hv_store(env, "psgi.multiprocess", 17, newSViv(1), 0)) goto clear;
}
else {
if (!hv_store(env, "psgi.multiprocess", 17, newSViv(0), 0)) goto clear;
}
if (uwsgi.threads > 1) {
if (!hv_store(env, "psgi.multithread", 16, newSViv(1), 0)) goto clear;
}
else {
if (!hv_store(env, "psgi.multithread", 16, newSViv(0), 0)) goto clear;
}
if (!hv_store(env, "psgi.run_once", 13, newSViv(0), 0)) goto clear;
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
if (!hv_store(env, "psgi.nonblocking", 16, newSViv(1), 0)) goto clear;
}
else {
#else
if (!hv_store(env, "psgi.nonblocking", 16, newSViv(0), 0)) goto clear;
#endif
#ifdef UWSGI_ASYNC
}
#endif
if (!hv_store(env, "psgi.streaming", 14, newSViv(1), 0)) goto clear;
SV *us;
// psgi.url_scheme, honour HTTPS var or UWSGI_SCHEME
if (wsgi_req->scheme_len > 0) {
us = newSVpv(wsgi_req->scheme, wsgi_req->scheme_len);
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
us = newSVpv("https", 5);
}
else {
us = newSVpv("http", 4);
}
}
else {
us = newSVpv("http", 4);
}
if (!hv_store(env, "psgi.url_scheme", 15, us, 0)) goto clear;
SV *pi = uwsgi_perl_obj_new("uwsgi::input", 12);
if (!hv_store(env, "psgi.input", 10, pi, 0)) goto clear;
if (!hv_store(env, "psgix.input.buffered", 20, newSViv(wsgi_req->body_as_file), 0)) goto clear;
if (uwsgi.master_process) {
if (!hv_store(env, "psgix.harakiri", 14, newSViv(1), 0)) goto clear;
}
SV *pe = uwsgi_perl_obj_new("uwsgi::error", 12);
if (!hv_store(env, "psgi.errors", 11, pe, 0)) goto clear;
return newRV_noinc((SV *)env);
clear:
SvREFCNT_dec((SV *)env);
return NULL;
}
/* end of automagically generated part */
int uwsgi_perl_init(){
struct http_status_codes *http_sc;
int argc = 4;
char *embedding[] = { "", "-e", "-e", "0" };
int argc;
uperl.embedding[0] = "";
uperl.embedding[1] = "-e";
uperl.embedding[2] = "0";
if (setenv("PLACK_ENV", "uwsgi", 0)) {
uwsgi_error("setenv()");
}
if (setenv("PLACK_SERVER", "uwsgi", 0)) {
uwsgi_error("setenv()");
}
#ifdef PERL_VERSION_STRING
uwsgi_log("initializing Perl %s environment\n", PERL_VERSION_STRING);
#else
uwsgi_log("initializing Perl environment\n");
PERL_SYS_INIT3(&argc, (char ***) &embedding, &environ);
#endif
argc = 3;
PERL_SYS_INIT3(&argc, (char ***) &uperl.embedding, &environ);
uperl.main = perl_alloc();
if (!uperl.main) {
uwsgi_log("unable to allocate perl interpreter\n");
@@ -79,6 +315,7 @@ int uwsgi_perl_init(){
PERL_SET_CONTEXT(uperl.main);
PL_perl_destruct_level = 2;
PL_origalen = 1;
perl_construct(uperl.main);
// filling http status codes
@@ -87,129 +324,40 @@ int uwsgi_perl_init(){
}
PL_origalen = 1;
perl_parse(uperl.main, xs_init, 4, embedding, NULL);
perl_eval_pv("use IO::Handle;", 0);
return 1;
}
void uwsgi_psgi_app() {
struct stat stat_psgi;
if (uperl.psgi) {
uperl.fd = open(uperl.psgi, O_RDONLY);
if (uperl.fd < 0) {
uwsgi_error_open(uperl.psgi);
exit(1);
}
if (fstat(uperl.fd, &stat_psgi)) {
uwsgi_error("fstat()");
exit(1);
}
uperl.psgibuffer = malloc(stat_psgi.st_size + 1);
if (!uperl.psgibuffer) {
uwsgi_error("malloc()");
exit(1);
}
if (read(uperl.fd, uperl.psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) {
uwsgi_error("read()");
exit(1);
}
uperl.psgibuffer[stat_psgi.st_size] = 0;
if (uwsgi.threads < 2) {
uperl.psgi_main = perl_eval_pv(uperl.psgibuffer, 0);
if (!uperl.psgi_main) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
free(uperl.psgibuffer);
close(uperl.fd);
}
uwsgi_log("PSGI app (%s) loaded at %p\n", uperl.psgi, uperl.psgi_main);
}
}
#ifdef USE_ITHREADS
void uwsgi_perl_enable_threads() {
int i;
if (pthread_key_create(&uperl.u_interpreter, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
uperl.interp = malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
if (!uperl.interp) {
uwsgi_error("malloc()");
exit(1);
}
uperl.interp = uwsgi_malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
uperl.interp[0] = uperl.main;
for(i=1;i<uwsgi.threads;i++) {
uperl.interp[i] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
if (!uperl.interp[i]) {
uwsgi_log("unable to create new perl interpreter\n");
exit(1);
}
}
uperl.psgi_func = uwsgi_malloc( sizeof(SV*) * uwsgi.threads );
uperl.psgi_func = malloc( sizeof(SV*) * uwsgi.threads );
if (!uperl.psgi_func) {
uwsgi_error("malloc()");
exit(1);
}
dTHXa(uperl.main);
PERL_SET_CONTEXT(uperl.main);
uperl.psgi_main = perl_eval_pv(uperl.psgibuffer, 0);
if (!uperl.psgi_main) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
}
#endif
int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
HV *env;
SV **item;
AV *response;
SV *io_new, *io_err;
int i;
SV **harakiri;
SV *psgi_func = uperl.psgi_main;
// ugly hack
register PerlInterpreter *my_perl = uperl.main;
dSP;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
return psgi_response(wsgi_req, wsgi_req->async_placeholder);
}
#endif
/* Standard PSGI request */
if (!wsgi_req->uh.pktsize) {
@@ -219,133 +367,59 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid PSGI request. skip.\n");
return -1;
}
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1 && wsgi_req->async_id > 0) {
if (uwsgi.threads > 1) {
psgi_func = uperl.psgi_func[wsgi_req->async_id];
my_perl = pthread_getspecific(uperl.u_interpreter);
}
#endif
ENTER;
SAVETMPS;
wsgi_req->async_environ = build_psgi_env(wsgi_req);
if (!wsgi_req->async_environ) goto clear;
env = (HV*) sv_2mortal((SV*)newHV());
wsgi_req->async_result = psgi_call(wsgi_req, psgi_func, wsgi_req->async_environ);
if (!wsgi_req->async_result) goto clear;
// fill perl hash
for(i=0;i<wsgi_req->var_cnt;i++) {
if (wsgi_req->hvec[i+1].iov_len > 0) {
item = hv_store(env, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len,
newSVpv(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len), 0);
if (SvTYPE((AV *)wsgi_req->async_result) == SVt_PVCV) {
SV *stream_result = uwsgi_perl_call_stream((SV*)wsgi_req->async_result);
if (!stream_result) {
internal_server_error(wsgi_req, "exception raised");
}
else {
item = hv_store(env, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, newSVpv("", 0), 0);
SvREFCNT_dec(stream_result);
}
//uwsgi_log("%.*s = %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
i++;
goto clear2;
}
SV *us = newSVpv("http", 4);
item = hv_store(env, "psgi.url_scheme", 15, us, 0);
SV* iohandle = newSVpv( "IO::Handle", 10 );
PUSHMARK(SP);
XPUSHs( sv_2mortal(iohandle));
PUTBACK;
perl_call_method( "new", G_SCALAR);
SPAGAIN;
io_new = POPs;
PUSHMARK(SP);
XPUSHs( io_new );
XPUSHs( sv_2mortal(newSViv( wsgi_req->poll.fd)));
XPUSHs( sv_2mortal(newSVpv( "r", 1)));
PUTBACK;
perl_call_method( "fdopen", G_SCALAR);
SPAGAIN;
SV *pi = SvREFCNT_inc(POPs);
item = hv_store(env, "psgi.input", 10, pi, 0);
PUSHMARK(SP);
XPUSHs( newSVpv( "IO::Handle", 10 ));
PUTBACK;
perl_call_method( "new", G_SCALAR);
SPAGAIN;
io_err = POPs;
PUSHMARK(SP);
XPUSHs( io_err );
XPUSHs( sv_2mortal( newSViv( 2 )));
XPUSHs( sv_2mortal( newSVpv( "w", 1)));
PUTBACK;
perl_call_method( "fdopen", G_SCALAR);
SPAGAIN;
SV *pe = SvREFCNT_inc(POPs);
item = hv_store(env, "psgi.errors", 11, pe, 0);
PUSHMARK(SP);
XPUSHs( sv_2mortal(newRV((SV *)env )) );
PUTBACK;
perl_call_sv(psgi_func, G_SCALAR);
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
goto clear;
}
SPAGAIN;
// no leaks to here
// dereference output
response = (AV *) SvRV( POPs );
//uwsgi_log("response: %p %d\n", response, SvTYPE(response));
if (SvTYPE(response) == SVt_PVCV) {
uwsgi_log("streaming response\n");
PUSHMARK(SP);
XPUSHs( newRV((SV*) uperl.stream_responder));
PUTBACK;
perl_call_sv( (SV*)response, G_SCALAR);
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
while (psgi_response(wsgi_req, wsgi_req->async_result) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
FREETMPS;
LEAVE;
return UWSGI_AGAIN;
}
goto clear;
#endif
}
psgi_response(wsgi_req, my_perl, response);
clear2:
// check for psgix.harakiri
harakiri = hv_fetch((HV*)SvRV( (SV*)wsgi_req->async_environ), "psgix.harakiri.commit", 21, 0);
if (harakiri) {
if (SvTRUE(*harakiri)) wsgi_req->async_plagued = 1;
}
SvREFCNT_dec(wsgi_req->async_environ);
SvREFCNT_dec(wsgi_req->async_result);
clear:
FREETMPS;
LEAVE;
return 0;
return UWSGI_OK;
}
@@ -353,28 +427,49 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
if (wsgi_req->async_plagued) {
uwsgi_log("*** psgix.harakiri.commit requested ***\n");
goodbye_cruel_world();
}
}
#ifdef USE_ITHREADS
void uwsgi_perl_init_thread(int core_id) {
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
if (core_id > 0) {
uperl.interp[core_id] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
if (!uperl.interp[core_id]) {
uwsgi_log("unable to create new perl interpreter\n");
exit(1);
}
}
dTHXa(uperl.interp[core_id]);
PERL_SET_CONTEXT(uperl.interp[core_id]);
uperl.psgi_func[core_id] = perl_eval_pv(uperl.psgibuffer, 0);
if (!uperl.psgi_func[core_id]) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
uperl.psgi_func[0] = uperl.psgi_main;
if (core_id > 0) {
uperl.psgi_func[core_id] = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
if (!uperl.psgi_func[core_id]) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
}
}
#endif
int uwsgi_perl_manage_options(int i, char *optarg) {
@@ -382,6 +477,9 @@ int uwsgi_perl_manage_options(int i, char *optarg) {
case LONG_ARGS_PSGI:
uperl.psgi = optarg;
return 1;
case LONG_ARGS_PERL_LOCAL_LIB:
uperl.locallib = optarg;
return 1;
}
return 0;
@@ -412,9 +510,11 @@ struct uwsgi_plugin psgi_plugin = {
.init_apps = uwsgi_psgi_app,
//.magic = uwsgi_perl_magic,
//.help = uwsgi_perl_help,
#ifdef USE_ITHREADS
.enable_threads = uwsgi_perl_enable_threads,
.manage_opt = uwsgi_perl_manage_options,
.init_thread = uwsgi_perl_init_thread,
#endif
.manage_opt = uwsgi_perl_manage_options,
.request = uwsgi_perl_request,
.after_request = uwsgi_perl_after_request,
+111 -65
View File
@@ -1,53 +1,10 @@
#include "psgi.h"
/* statistically ordered */
struct http_status_codes hsc[] = {
{"200", "OK"},
{"302", "Found"},
{"404", "Not Found"},
{"500", "Internal Server Error"},
{"301", "Moved Permanently"},
{"304", "Not Modified"},
{"303", "See Other"},
{"403", "Forbidden"},
{"307", "Temporary Redirect"},
{"401", "Unauthorized"},
{"400", "Bad Request"},
{"405", "Method Not Allowed"},
{"408", "Request Timeout"},
extern struct uwsgi_server uwsgi;
{"100", "Continue"},
{"101", "Switching Protocols"},
{"201", "Created"},
{"202", "Accepted"},
{"203", "Non-Authoritative Information"},
{"204", "No Content"},
{"205", "Reset Content"},
{"206", "Partial Content"},
{"300", "Multiple Choices"},
{"305", "Use Proxy"},
{"402", "Payment Required"},
{"406", "Not Acceptable"},
{"407", "Proxy Authentication Required"},
{"409", "Conflict"},
{"410", "Gone"},
{"411", "Length Required"},
{"412", "Precondition Failed"},
{"413", "Request Entity Too Large"},
{"414", "Request-URI Too Long"},
{"415", "Unsupported Media Type"},
{"416", "Requested Range Not Satisfiable"},
{"417", "Expectation Failed"},
{"501", "Not Implemented"},
{"502", "Bad Gateway"},
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{ "", NULL },
};
extern struct http_status_codes hsc[];
int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *response) {
int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
SV **status_code, **hitem ;
AV *headers, *body =NULL;
@@ -55,16 +12,61 @@ int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *r
struct http_status_codes *http_sc;
int i,vi, base;
char *chitem;
dSP;
SV **harakiri;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
wsgi_req->async_force_again = 0;
wsgi_req->switches++;
SV *chunk = uwsgi_perl_obj_call(wsgi_req->async_placeholder, "getline");
if (!chunk) {
internal_server_error(wsgi_req, "exception raised");
return UWSGI_OK;
}
if (wsgi_req->async_force_again) {
SvREFCNT_dec(chunk);
return UWSGI_AGAIN;
}
chitem = SvPV( chunk, hlen);
if (hlen <= 0) {
SvREFCNT_dec(chunk);
SV *closed = uwsgi_perl_obj_call(wsgi_req->async_placeholder, "close");
if (closed) {
SvREFCNT_dec(closed);
}
// check for psgix.harakiri
harakiri = hv_fetch((HV*)SvRV( (SV*)wsgi_req->async_environ), "psgix.harakiri.commit", 21, 0);
if (harakiri) {
if (SvTRUE(*harakiri)) wsgi_req->async_plagued = 1;
}
SvREFCNT_dec(wsgi_req->async_environ);
SvREFCNT_dec(wsgi_req->async_result);
return UWSGI_OK;
}
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, chitem, hlen);
SvREFCNT_dec(chunk);
return UWSGI_AGAIN;
}
#endif
status_code = av_fetch(response, 0, 0);
if (!status_code) { uwsgi_log("invalid PSGI status code\n"); return UWSGI_OK;}
wsgi_req->hvec[0].iov_base = "HTTP/1.1 ";
wsgi_req->hvec[0].iov_len = 9;
//uwsgi_log("setting status %d %d\n", SvTYPE(*status_code), SvIV(*status_code));
wsgi_req->hvec[1].iov_base = SvPV(*status_code, hlen);
wsgi_req->hvec[1].iov_len = 3;
wsgi_req->status = atoi(wsgi_req->hvec[1].iov_base);
@@ -92,8 +94,10 @@ int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *r
wsgi_req->hvec[4].iov_len = 2;
hitem = av_fetch(response, 1, 0);
if (!hitem) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
headers = (AV *) SvRV(*hitem);
if (!headers) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
base = 5;
@@ -122,34 +126,76 @@ int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *r
vi = (i*2)+base;
wsgi_req->hvec[vi].iov_base = "\r\n"; wsgi_req->hvec[vi].iov_len = 2;
if ( !(wsgi_req->headers_size = writev(wsgi_req->poll.fd, wsgi_req->hvec, vi+1)) ) {
if ( !(wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, vi+1)) ) {
uwsgi_error("writev()");
}
hitem = av_fetch(response, 2, 0);
if (SvTYPE(SvRV(*hitem)) == SVt_PVGV || SvTYPE(SvRV(*hitem)) == SVt_PVHV) {
if (!hitem) {
return UWSGI_OK;
}
if (!SvRV(*hitem)) { uwsgi_log("invalid PSGI response body\n") ; return UWSGI_OK; }
if (SvTYPE(SvRV(*hitem)) == SVt_PVGV || SvTYPE(SvRV(*hitem)) == SVt_PVHV || SvTYPE(SvRV(*hitem)) == SVt_PVMG) {
// respond to fileno ?
if (uwsgi.async < 2) {
if (uwsgi_perl_obj_can(*hitem, "fileno", 6)) {
SV *fn = uwsgi_perl_obj_call(*hitem, "fileno");
wsgi_req->sendfile_fd = SvIV(fn);
SvREFCNT_dec(fn);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
return UWSGI_OK;
}
if (uwsgi_perl_obj_can(*hitem, "path", 4)) {
SV *p = uwsgi_perl_obj_call(*hitem, "path");
wsgi_req->sendfile_fd = open(SvPV_nolen(p), O_RDONLY);
SvREFCNT_dec(p);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
close(wsgi_req->sendfile_fd);
return UWSGI_OK;
}
}
for(;;) {
PUSHMARK(SP);
XPUSHs(*hitem);
PUTBACK;
perl_call_method("getline", G_SCALAR);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
break;
}
SV *chunk = POPs;
wsgi_req->switches++;
SV *chunk = uwsgi_perl_obj_call(*hitem, "getline");
if (!chunk) {
internal_server_error(wsgi_req, "exception raised");
break;
}
chitem = SvPV( chunk, hlen);
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1 && wsgi_req->async_force_again) {
SvREFCNT_dec(chunk);
wsgi_req->async_status = UWSGI_AGAIN;
wsgi_req->async_placeholder = (SV *) *hitem;
return UWSGI_AGAIN;
}
#endif
if (hlen <= 0) {
SvREFCNT_dec(chunk);
break;
}
wsgi_req->response_size = write(wsgi_req->poll.fd, chitem, hlen);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, chitem, hlen);
SvREFCNT_dec(chunk);
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
wsgi_req->async_status = UWSGI_AGAIN;
wsgi_req->async_placeholder = (SV *) *hitem;
return UWSGI_AGAIN;
}
#endif
}
SV *closed = uwsgi_perl_obj_call(*hitem, "close");
if (closed) {
SvREFCNT_dec(closed);
}
}
else if (SvTYPE(SvRV(*hitem)) == SVt_PVAV) {
@@ -159,7 +205,7 @@ int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *r
for(i=0; i<=av_len(body); i++) {
hitem = av_fetch(body,i,0);
chitem = SvPV(*hitem, hlen);
wsgi_req->response_size = write(wsgi_req->poll.fd, chitem, hlen);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, chitem, hlen);
}
}
@@ -167,6 +213,6 @@ int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *r
uwsgi_log("unsupported response body type: %d\n", SvTYPE(SvRV(*hitem)));
}
return 1;
return UWSGI_OK;
}
+116 -3
View File
@@ -2,12 +2,85 @@
extern struct uwsgi_server uwsgi;
#define psgi_xs(func) newXS("uwsgi::" #func, XS_##func, "uwsgi")
#define psgi_check_args(x) if (items < x) Perl_croak(aTHX_ "Usage: uwsgi::%s takes %d arguments", __FUNCTION__ + 3, x)
#ifdef UWSGI_ASYNC
XS(XS_async_sleep) {
dXSARGS;
int timeout ;
psgi_check_args(1);
struct wsgi_request *wsgi_req = current_wsgi_req();
timeout = SvIV(ST(0));
if (timeout >= 0) {
async_add_timeout(wsgi_req, timeout);
}
wsgi_req->async_force_again = 1;
XSRETURN_UNDEF;
}
XS(XS_wait_fd_read) {
dXSARGS;
int fd, timeout = 0;
psgi_check_args(1);
struct wsgi_request *wsgi_req = current_wsgi_req();
fd = SvIV(ST(0));
if (items > 1) {
timeout = SvIV(ST(1));
}
if (fd >= 0) {
async_add_fd_read(wsgi_req, fd, timeout);
}
wsgi_req->async_force_again = 1;
XSRETURN_UNDEF;
}
XS(XS_wait_fd_write) {
dXSARGS;
int fd, timeout = 0;
psgi_check_args(1);
struct wsgi_request *wsgi_req = current_wsgi_req();
fd = SvIV(ST(0));
if (items > 1) {
timeout = SvIV(ST(1));
}
if (fd >= 0) {
async_add_fd_write(wsgi_req, fd, timeout);
}
wsgi_req->async_force_again = 1;
XSRETURN_UNDEF;
}
#endif
XS(XS_reload) {
dXSARGS;
items = 0;
psgi_check_args(0);
uwsgi_log("SENDING HUP TO %d\n", (int) uwsgi.workers[0].pid);
if (kill(uwsgi.workers[0].pid, SIGHUP)) {
@@ -57,6 +130,27 @@ XS(XS_cache_get) {
}
XS(XS_log) {
dXSARGS;
psgi_check_args(1);
uwsgi_log("%s", SvPV_nolen(ST(0)));
XSRETURN_UNDEF;
}
XS(XS_async_connect) {
dXSARGS;
psgi_check_args(1);
ST(0) = newSViv(uwsgi_connect(SvPV_nolen(ST(0)), 0, 1));
XSRETURN(1);
}
XS(XS_call) {
dXSARGS;
@@ -88,11 +182,30 @@ XS(XS_call) {
}
XS(XS_suspend) {
dXSARGS;
psgi_check_args(0);
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_force_again = 0;
if (uwsgi.schedule_to_main) uwsgi.schedule_to_main(wsgi_req);
XSRETURN_UNDEF;
}
void init_perl_embedded_module() {
psgi_xs(reload);
psgi_xs(cache_set);
psgi_xs(cache_get);
psgi_xs(call);
psgi_xs(wait_fd_read);
psgi_xs(wait_fd_write);
psgi_xs(async_sleep);
psgi_xs(log);
psgi_xs(async_connect);
psgi_xs(suspend);
}
+7 -3
View File
@@ -1,7 +1,11 @@
import os,sys
NAME='psgi'
CFLAGS = [os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip()]
LDFLAGS = [os.popen('perl -MExtUtils::Embed -e ldopts').read().rstrip()]
CFLAGS = os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip().split()
LDFLAGS = os.popen('perl -MExtUtils::Embed -e ldopts').read().rstrip().split()
LIBS = []
GCC_LIST = ['uwsgi_plmodule', 'psgi_response', 'psgi_plugin']
GCC_LIST = ['uwsgi_plmodule', 'psgi_loader', 'psgi_response', 'psgi_plugin']
for item in LDFLAGS:
if item.endswith('DynaLoader.a'):
GCC_LIST.append(item)

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