Compare commits

..
241 Commits
Author SHA1 Message Date
roberto@sirius 79fa25c4e0 latest (i hope) pip hack 2010-05-01 08:10:36 +02:00
roberto@sirius 02050675a8 pip hack [5] 2010-05-01 08:06:44 +02:00
roberto@sirius 0d5857a1bc pip hack [4] 2010-05-01 08:04:05 +02:00
roberto@sirius e3a51be1f9 pip hack [3] 2010-05-01 07:58:53 +02:00
roberto@sirius 57cb098a6e move to setuptools 2010-05-01 07:39:56 +02:00
roberto@sirius 5f285eef56 pip hack [2] 2010-05-01 07:29:07 +02:00
roberto@sirius 7d5cf6f318 pip hack 2010-05-01 07:14:14 +02:00
roberto@silente 99d305c7a1 snmp big endian fixes 2010-04-30 16:41:57 +02:00
roberto@sirius b9cc3b6a7d snmp fix 2010-04-30 15:51:32 +02:00
roberto@sirius e1f8c69d3d minor fixes 2010-04-30 15:16:18 +02:00
roberto@sirius 67b6fbd15b admin modifier fix 2010-04-30 14:46:27 +02:00
roberto@sirius 50f407eb9e no_server fix 2010-04-30 14:41:30 +02:00
roberto@freebsd b127699c0a FreeBSD/Dragonfly little fix 2010-04-30 14:12:51 +02:00
roberto@netbsd 4d74fa6759 small netbsd include fix 2010-04-30 16:04:02 +02:00
roberto@sirius 2b9d6cb7c2 uwsgi_log everywhere 2010-04-30 12:28:01 +02:00
roberto@solaris e0b67bba58 uwsgi_log instead of fprintf [1] 2010-04-30 12:22:07 +02:00
roberto@silente 3cdf17df75 strlcopy insted of strcpy 2010-04-30 09:54:25 +02:00
roberto@silente 43c086494b be more verbose on extreme cases 2010-04-30 09:18:53 +02:00
roberto@silente ae26e90b3a OpenBSD ha no RLIMIT_AS and swapcontext(), added an harakiri message to avoid user confusion 2010-04-30 09:01:26 +02:00
roberto@sirius d35a7d8725 updated urack.rb for unbit 2010-04-27 12:47:29 +02:00
roberto@sirius 043e7ddde4 uWSGI 0.9.5-rc2 2010-04-20 10:51:54 +02:00
roberto@sirius 3930960159 psycogreen example 2010-04-20 10:30:57 +02:00
roberto@sirius be12175c8a psycopg2 async example 2010-04-20 10:19:00 +02:00
roberto@sirius 02a1847539 async memory fixes 2010-04-19 16:01:13 +02:00
roberto@solaris 0235535658 /dev/poll complete support 2010-04-19 13:43:36 +02:00
roberto@sirius 3af75ca64c default uwsgiconfig.py 2010-04-19 10:14:21 +02:00
roberto@sirius efbe28502d new wsgi_request struct fixes 2010-04-19 10:13:38 +02:00
roberto@solaris 47847ee471 Solaris/Sparc fixes 2010-04-19 08:34:46 +02:00
roberto@sirius 688ffe32a9 urack refactoring 2010-04-15 17:02:29 +02:00
roberto@sirius c6bbe01f3e fix for Plack handler 2010-04-15 12:59:24 +02:00
roberto@sirius 002af6128c UWSGI_FD for plack handler 2010-04-15 11:47:39 +02:00
roberto@sirius 5b5c92a9d7 fix for ruby 1.8.6 2010-04-15 11:01:18 +02:00
roberto@sirius 7d31d73fc5 UWSGI_FD for rack handler 2010-04-15 10:56:25 +02:00
roberto@sirius c5c2c83c65 uWSGI 0.9.5-rc1 2010-04-14 07:26:32 +02:00
roberto@sirius 174116c48b a bunch of fixes for release candidate 2010-04-14 07:25:58 +02:00
roberto@sirius 4be5830fc3 removed base.mk 2010-04-14 07:07:47 +02:00
roberto@sirius 5f55357e17 remove UNBIT makefiles 2010-04-14 07:06:12 +02:00
roberto@sirius 8d033159b8 uwsgiplugin.py for Lua and example 2010-04-13 08:47:33 +02:00
roberto@sirius 299fd9cf8a introduced open PSGI plugin for uWSGI 2010-04-13 08:39:49 +02:00
roberto@sirius 8caee1b15b remove packed attribute from wsgi_request 2010-04-12 13:58:35 +02:00
roberto@sirius c2d963aa0d Plack::Handler:Uwsgi fixes 2010-04-12 13:11:08 +02:00
roberto@sirius 94691b3cc3 Plack::Handler:Uwsgi 2010-04-12 13:07:25 +02:00
roberto@sirius 9073a2856b added uwsgi Rack handler 2010-04-11 20:41:23 +02:00
roberto@sirius 4c26f34239 spooler fixes, and a new example (rrdtool and cron-like spooling) 2010-04-10 09:07:53 +02:00
roberto@sirius ad0cc774e1 shebang on ugreenchat 2010-04-09 11:56:55 +02:00
roberto@sirius d238fc50d0 new uGreen functions, sample comet chat included 2010-04-09 11:13:01 +02:00
roberto@fedora-arm dcf16c994e python headers check 2010-04-08 06:06:54 -04:00
roberto@sirius 65cc44e611 multicast fixes 2010-04-06 14:21:36 +02:00
roberto@sirius 9887177d9a startup logic fixes 2010-04-06 13:58:28 +02:00
roberto@voldemort 6b11777bb3 udp logging fixes 2010-04-06 13:02:04 +02:00
roberto@sirius 604b412f4a remove junk from udp logging 2010-04-06 12:57:17 +02:00
roberto@sirius 1d9da31f18 udp logging support 2010-04-06 12:38:04 +02:00
roberto@sirius fadf640f41 shebang friendly getopt_long() 2010-04-06 10:37:56 +02:00
roberto@sirius 743432a53d Sun fixes 2010-04-02 08:56:02 +02:00
roberto@sirius c1956fc371 /dev/poll support 2010-04-01 10:31:04 +02:00
roberto@sirius 3d098358da SO_ACCEPTFILTER 2010-04-01 09:25:15 +02:00
roberto@sirius 757e908372 uGreen timeout implementation 2010-03-31 15:17:04 +02:00
roberto@sirius dd12caa6f3 interrupt compilation if XML+libxml2 is requested but libxml2 headers are unavailable 2010-03-31 11:34:10 +02:00
roberto@sirius 0bfa5c4f46 Wally's patch for not compiled-in options 2010-03-31 11:15:24 +02:00
roberto@sirius cb252e4f0a OSX re-fix 2010-03-31 10:01:07 +02:00
roberto@sirius bdab4dcf84 uGreen fd async waiting support 2010-03-31 09:57:16 +02:00
roberto@sirius 474860cd39 uGreen configurable stack size 2010-03-30 20:07:50 +02:00
roberto@fierobecco 82f722b1f9 OSX fixes for uGreen 2010-03-29 13:05:36 +02:00
roberto@sirius 919501e92c uGreen little refactoring and fixes 2010-03-29 10:30:03 +02:00
roberto@sirius b1f3e48b2b uGreen fix 2010-03-28 18:21:23 +02:00
roberto@sirius 314df1d809 ugreen support 2010-03-28 18:18:23 +02:00
roberto@sirius 0416914951 fixed async wsgi mode 2010-03-26 17:01:13 +01:00
roberto@sirius 159a5660b2 Added tag 0.9.5beta2 for changeset 63560de14789 2010-03-26 09:24:55 +01:00
roberto@sirius 6ea9ee4ee9 re-enabled environment 2010-03-26 09:24:46 +01:00
roberto@sirius c60a81db47 uWSGI 0.9.5beta2 2010-03-26 09:19:03 +01:00
roberto@sirius b71634c76b erlang support is dependent on python embedded module 2010-03-26 09:17:53 +01:00
roberto@sirius 9a23c42262 another setrlimit() fix 2010-03-26 09:01:37 +01:00
roberto@sirius 680df4cff6 setrlimit() fixes 2010-03-26 08:59:33 +01:00
roberto@sirius 27fa8df9e6 automatically rise RLIMIT_NOFILE if possibile 2010-03-26 08:45:40 +01:00
roberto@sirius 2151b17aa3 check on RLIMIT_NOFILE beforse allocating async cores 2010-03-26 08:34:37 +01:00
roberto@sirius b93d0cc2b0 kevent() on pre-forking fix 2010-03-25 17:55:08 +01:00
roberto@sirius 1729275f8c async fix for fd waiting on kevent() 2010-03-25 17:35:58 +01:00
roberto@sirius 9b2460f8df another fix errno in tests.iobound_async 2010-03-25 17:21:05 +01:00
roberto@sirius 5451ff490c fix errno in tests.iobound_async 2010-03-25 17:17:33 +01:00
roberto@sirius 5a828aefdc python 3k full support 2010-03-25 16:04:40 +01:00
roberto@unbit 6a4332ca4d use distutils.sysconfig instead of python-config 2010-03-25 11:07:12 +01:00
roberto@sirius 7f3750b174 no fd-leak in stackless and async mode 2010-03-25 08:05:17 +01:00
roberto@sirius 7b1672497e stackless python support 2010-03-24 15:32:36 +01:00
roberto@sirius 113223567a typo fixes 2010-03-23 10:47:48 +01:00
roberto@fierobecco ecf23f93d1 osx erlang help 2010-03-22 15:32:01 +01:00
roberto@freebsd 2504af4dd1 FreeBSD sendfile fixes 2010-03-22 15:12:17 +01:00
roberto@netbsd c340e972ad NetBSD sendfile fixes, memory report and typecasting 2010-03-22 15:45:03 +01:00
roberto@sirius e382de291f expat implementation 2010-03-22 11:14:58 +01:00
roberto@sirius 51d97fadd9 nagios refactoring 2010-03-22 09:06:32 +01:00
roberto@sirium 878b515e23 code refactoring 2010-03-22 08:22:21 +01:00
roberto@sirius 03bdaa50b6 linux sendfile fix 2010-03-21 21:05:33 +01:00
roberto@sirius 34dbfc597e proxy refactoring 2010-03-21 21:01:27 +01:00
roberto@fierobecco 05efe4b7b3 kqueue fixes, sendfile osx, fix on apache2 module 2010-03-21 19:50:20 +01:00
roberto@sirius a18bc5f148 sendfile async implementation, still broken on BSD 2010-03-21 14:38:26 +01:00
roberto@sirius 9852b2fa62 async sleep implementation, kqueue re-broken, profiler leaks memory 2010-03-21 08:53:36 +01:00
roberto@sirius 9cedbb6716 WSGI handler refactoring 2010-03-18 18:14:06 +01:00
roberto@sirius 96a6c5eff4 report async switches 2010-03-18 17:42:22 +01:00
roberto@sirius e5233f09cc fix for a stupid typo 2010-03-18 13:53:53 +01:00
roberto@sirius 2f7bf001e8 new async test for I/O 2010-03-18 13:39:41 +01:00
roberto@fierobecco 1caea3dbeb async support for BSD systems (kqueue based) 2010-03-18 13:35:11 +01:00
roberto@sirius 6805e5ee9f merge 2010-03-18 12:38:21 +01:00
roberto@sirius 82f33591ae revert snmp fix 2010-03-18 12:37:37 +01:00
roberto@sirius b3e3e2ca1d async.c (only epoll) 2010-03-18 12:34:23 +01:00
roberto@sirius 4ae0361f6d little snmp fix 2010-03-18 12:34:12 +01:00
roberto@sirius.local 5706dd0a31 remove non-included option from getopt 2010-03-18 09:09:28 +01:00
roberto@sirius d8cd5580b7 preliminary async support 2010-03-17 18:08:53 +01:00
roberto@sirius e16c9b46ed little tag fix 2010-03-12 11:23:26 +01:00
roberto@sirius 86d28b2654 uWSGI 0.9.5beta1 2010-03-12 11:22:37 +01:00
roberto@sirius 09bc058e88 goodbye to ROCK_SOLID 2010-03-12 11:01:34 +01:00
roberto@sirius 0bf55fc1f9 Yann is right, remove the interactive setup.py 2010-03-11 18:26:23 +01:00
roberto@sirius e05edd9f82 almost ready SNMP support 2010-03-11 18:24:37 +01:00
roberto@sirius aa9c5331d4 re-indent all the code 2010-03-11 12:39:30 +01:00
roberto@sirius 665511e6fa updated --help 2010-03-11 10:06:06 +01:00
roberto@sirius 41190a5336 UWSGI_VERSION --version 2010-03-11 10:04:21 +01:00
roberto@fierobecco f2b72814a6 kqueue fixes for connect() 2010-03-10 16:11:28 +01:00
roberto@sirius 67d49defb6 remove useless service_unavailable in proxy 2010-03-10 15:51:22 +01:00
roberto@sirius bf1f800cf4 epoll fixes 2010-03-10 15:50:06 +01:00
roberto@fierobecco 55a95ac4b4 kqueue support and apache2 fix 2010-03-10 14:42:14 +01:00
roberto@sirius 820caa5364 python3.x compatible uwsgiconfig.py 2010-03-10 08:14:28 +01:00
roberto@sirius 67ce14dfa8 other 64 bit fixes 2010-03-10 07:09:18 +01:00
roberto@sirius dc16e8eb38 sendfile 64bit fixes 2010-03-09 21:42:37 +01:00
roberto@sirius fc0de78d88 fixed conditional proxy compilatio 2010-03-09 09:12:35 +01:00
roberto@sirius 1ffecc7939 setup.py build_ext interactive 2010-03-09 08:55:30 +01:00
roberto@sirius 2b4759e5e1 setup.py write flush (10) 2010-03-09 08:54:55 +01:00
roberto@sirius 779ab3702a setup.py write flush (9) 2010-03-09 08:54:21 +01:00
roberto@sirius 25fe41dd50 setup.py write flush (8) 2010-03-09 08:53:47 +01:00
roberto@sirius 1c03935b76 setup.py write flush (7) 2010-03-09 08:50:32 +01:00
roberto@sirius 6b10370c0a setup.py write flush (6) 2010-03-09 08:49:20 +01:00
roberto@sirius e84c3808e9 setup.py write flush (5) 2010-03-09 08:48:51 +01:00
roberto@sirius b9ff3f87d0 setup.py write flush (4) 2010-03-09 08:47:28 +01:00
roberto@sirius 7a6d40c258 setup.py write flush (3) 2010-03-09 08:46:03 +01:00
roberto@sirius 5c211817b7 setup.py write flush (2) 2010-03-09 08:33:37 +01:00
roberto@sirius 21b2769edd setup.py write flush 2010-03-09 08:31:33 +01:00
roberto@sirius baff440f18 setup.py update 2010-03-09 08:30:02 +01:00
roberto@sirius 793dcd92d2 setup.py print input to stderr 2010-03-09 08:28:38 +01:00
roberto@sirius 1d203021c7 new setup.py fixes 2010-03-09 08:18:33 +01:00
roberto@sirius.local d38cc66738 better default values for trunk 2010-03-08 15:49:01 +01:00
roberto@sirius 603351c736 interactive setup.py 2010-03-08 15:44:11 +01:00
roberto@sirius ae5b69b19c setup.py new try (3) 2010-03-08 15:24:12 +01:00
roberto@sirius 0229a9727e setup.py new try (2) 2010-03-08 15:18:58 +01:00
roberto@sirius da571c2515 setup.py new try 2010-03-08 15:17:44 +01:00
roberto@sirius d3160c3f60 setup.py fix 2010-03-08 13:37:38 +01:00
roberto@sirius 175ef65d9f new build system 2010-03-08 13:25:02 +01:00
roberto@sirius 8a572a642e a bit of vacuum 2010-03-08 11:05:02 +01:00
roberto@sirius 70a51c2909 erlang fixes and rpc 2010-03-05 15:32:49 +01:00
roberto@sirius 8b32564b05 proxy.c 2010-03-04 17:25:13 +01:00
roberto@sirius c0ada5e52a wsgi file support 2010-03-04 16:54:26 +01:00
roberto@sirius 0ffcb9e05e the uWSGI proxy 2010-03-04 16:48:33 +01:00
roberto@sirius 5a279bb170 new binary-path options, useful for chroot reloads and cherokee wizard 2010-03-03 14:10:51 +01:00
roberto@sirius 757049d9da nagios plugin mode 2010-03-02 17:57:09 +01:00
roberto@sirius.local 8674787692 leak free ( i hope ) erlang node 2010-03-02 11:50:18 +01:00
roberto@sirius 3654016c53 complete erlang integration. Now working on timeout and memory management 2010-03-01 18:51:11 +01:00
roberto@sirius 4dbc15a253 big erlang update, still a lot of memory problems 2010-03-01 18:06:38 +01:00
roberto@sirius 3d55ab8327 contrib reorganization 2010-03-01 14:11:36 +01:00
roberto@sirius f4e336026b Erlang and new XML configuration 2010-03-01 14:06:56 +01:00
roberto@sirius ed90e0cf4b Makefile.Py25 2010-03-01 14:05:04 +01:00
roberto@sirius bed7682a3b useful XML support, first commit of uwsgiconfig.py 2010-03-01 14:02:36 +01:00
roberto@sirius 3874d3e610 stronger reload recognition 2010-02-15 14:55:20 +01:00
roberto@sirius d378d42c4c more getsockopt fixes 2010-02-15 12:09:18 +01:00
roberto@sirius 4faeb852c6 fix socket_type initialization 2010-02-15 11:33:10 +01:00
roberto@sirius 27177a4df9 trying to fix strange darwin behaviour on getsockopt 2010-02-15 10:03:56 +01:00
roberto@sirius 4ee9b36579 lower the scheduler priority of the spooler process 2010-02-14 11:20:13 +01:00
roberto@sirius c06a1626ed print a warning when the spooler dies 2010-02-14 11:03:09 +01:00
roberto@sirius 86787b796a fixed bug signalled by Valery Masiutsin 2010-02-14 10:58:45 +01:00
roberto@sirius 3bae35805b uwsgi.functions refactoring 2010-02-12 15:52:06 +01:00
roberto@sirius f26e79fb09 support for multiple --pythonpath options 2010-02-12 15:18:03 +01:00
roberto@sirius b72fc0a178 UWSGI_SCHEME for apache 2010-02-12 15:11:15 +01:00
roberto@sirius f1853568f9 latest Joerg Sonnenberger patches and some fix to the spooler 2010-02-12 14:57:19 +01:00
roberto@sirius 2785cd3065 remove the automatic locking for sharedarea, and export the uwsgi.lock() and uwsgi.unlock() functions 2010-02-12 10:41:41 +01:00
roberto@sirius a8a497e431 portability fix on spooler code 2010-02-11 10:36:55 +01:00
roberto@sirius 710588fcfd fixed plugin initialization 2010-02-11 09:55:02 +01:00
roberto@sirius a66aad02d8 added Joerg Sonnenberger UWSGI_SCHEME patch 2010-02-10 18:29:17 +01:00
roberto@freebsd 651dacad3a memory report for FreeBSD (finally) 2010-02-10 18:21:52 +01:00
roberto@sirius fdeb2e26cf fixed stupid check 2010-02-10 17:54:25 +01:00
roberto@sirius d5d5b87627 new configuration way 2010-02-10 17:52:13 +01:00
roberto@sirius 67c1a547af SCTP support is disabled and experimental 2010-02-10 17:31:32 +01:00
roberto@sirius ed9c99c417 ucheck.py for automagic makefiles 2010-02-10 17:30:29 +01:00
roberto@sirius 2e29b6b234 first (destructive) public commit for the 0.9.5 branch 2010-02-10 17:28:58 +01:00
roberto@sirius e0882ed8df big update: hooks and plugins 2010-02-07 23:06:24 +01:00
roberto@sirius.local a6b42af85a remove get_free_memory function. Is useless on modern systems 2010-02-04 14:02:30 +01:00
roberto@fierobecco 595e99a0c6 fix for 64 bit systems 2010-02-04 12:21:09 +01:00
roberto@sirius 54f666f214 fix warning 2010-02-04 11:55:35 +01:00
roberto@sirius f1fad65b43 fix warning 2010-02-04 11:54:25 +01:00
roberto@sirius 40fb6ffa91 print arch size 2010-02-04 11:52:24 +01:00
roberto@sirius d83a685d01 print address space limit only if limited 2010-02-04 11:48:09 +01:00
roberto@sirius e7b346d3d9 address space limiting with --limit-as 2010-02-04 11:37:04 +01:00
roberto@fierobecco 25ec7aadc0 OSX free memory monitoring 2010-02-04 10:33:06 +01:00
roberto@sirius f7ef3161e4 huge update, uwsgi.sorry_i_need_block(), uwsgi.log(), uwsgi.worker_id(), uwsgi.request_id(), uwsgi.disconnect() 2010-02-04 09:51:41 +01:00
roberto@sirius 2cd731f36d follow Igor coding style 2010-01-29 08:52:38 +01:00
roberto@sirius 15a0b7fbc9 nginx indentation fixes 2010-01-29 08:29:41 +01:00
roberto@sirius f33d16edb7 base for the uwsgi.sorry_i_have_to_block() hint 2010-01-29 08:16:56 +01:00
roberto@sirius 6fdb5cac37 working setup.py 2010-01-26 17:38:31 +01:00
roberto@sirius 20f7e4f0bc setup.py 2010-01-26 17:37:09 +01:00
roberto@sirius 0c1e9080af setup.py 2010-01-26 17:34:59 +01:00
roberto@sirius 1ceb82af59 setup.py 2010-01-26 17:34:22 +01:00
roberto@sirius ace76d686d setup.py 2010-01-26 17:32:21 +01:00
roberto@sirius a7bb9bd2bb setup.py 2010-01-26 17:27:33 +01:00
roberto@sirius aa39cc0eca better setup.py (third try) 2010-01-26 16:43:14 +01:00
roberto@sirius 74c88f21a9 better setup.py (second try) 2010-01-26 16:40:49 +01:00
roberto@sirius c03e94f97e better setup.py 2010-01-26 16:29:20 +01:00
roberto@sirius be4da2e8d9 third try for pip install 2010-01-26 16:19:39 +01:00
roberto@sirius d781a02eed second try for pip install 2010-01-26 16:15:35 +01:00
roberto@sirius fd42997e8f first try for pip install 2010-01-26 16:14:33 +01:00
roberto@sirius 6be13c2e04 uwsgi.get_option and uwsgi.set_option 2010-01-26 15:17:46 +01:00
roberto@sirius 63f63adda6 TCP_DEFER_ACCEPT optimization, automagic setup.py, dynamic options, python argv customization, refactoring of embedded module 2010-01-26 10:19:51 +01:00
roberto@sirius c0904e42fc setup.py 2010-01-22 16:39:59 +01:00
roberto@sirius 8b8f1d60ed uwsgi.unbit 2010-01-22 13:24:18 +01:00
roberto@sirius 5a6850e64b uWSGI 0.9.4 2010-01-21 15:18:17 +01:00
roberto@sirius cc6e9924b8 endianess fixes for lighttpd module 2010-01-21 14:36:07 +01:00
roberto@sirius 816998155e little bugfix for 64bit apache2 2010-01-21 14:04:56 +01:00
roberto@silente b2ffd406e3 apache2 module for 0.9.4 2010-01-21 13:07:52 +01:00
roberto@sirius 713ffe38b4 apache2 endianess fixes 2010-01-21 12:32:07 +01:00
roberto@sirius 1810af7b2d report load of the uWSGI workers in the django admin app 2010-01-21 09:42:58 +01:00
roberto@sirius d0fb89c783 print the listen backlog, as it is an important value for tuning 2010-01-21 09:06:08 +01:00
roberto@gambit b0c23faeeb unbit makefile for py2.6 2010-01-20 09:52:43 +01:00
roberto@sirius edc4aa42c8 fix warnings 2010-01-20 09:43:12 +01:00
roberto@sirius dda8c2ffaa unbit fixes (2) 2010-01-20 09:41:23 +01:00
roberto@sirius 7059fd8d88 unbit fixes 2010-01-20 09:40:08 +01:00
roberto@sirius dad81ce7bd paste.deploy support 2010-01-19 17:42:52 +01:00
roberto@sirius 277afccf64 new --pythonpath long options and django admin module 2010-01-19 14:27:09 +01:00
roberto@sirius 3854d14867 DragonflyBSD support 2010-01-18 16:26:14 +01:00
roberto@sirius e3a67a9bcd vacuum 2010-01-18 14:55:18 +01:00
roberto@sirius a51b19669c uWSGI 0.9.4-rc1 2010-01-18 14:45:13 +01:00
roberto@sirius 2707860bc5 removed the cherokee handler as it is included in the official cherokee distribution 2010-01-18 14:40:54 +01:00
roberto@sirius 7c69aade57 remove the chroot warning on unbit systems 2010-01-15 09:41:20 +01:00
roberto@sirius 38c5d3d4b5 a little linux warning for chroot environments 2010-01-15 09:40:28 +01:00
roberto@sirius 065b992bf9 fix worker id for single process environment 2010-01-15 09:32:52 +01:00
roberto@sirius 3b93696775 --chroot, --gid, --uid implementation (root only) 2010-01-14 15:33:18 +01:00
roberto@sirius 62534b2490 freebsd fixes 2010-01-14 13:48:24 +01:00
roberto@voldemort 5018c152e9 new UNBIT makefiles 2010-01-14 12:13:59 +01:00
roberto@voldemort 57fc6bcef0 remove python2.6 support for rock_solid 2010-01-14 12:07:08 +01:00
roberto@voldemort 36f26dba85 remove useless LLVM files, they will be in the experimental directory after the 0.9.4 release 2010-01-14 12:06:21 +01:00
roberto@voldemort 6062bf8a72 new makefiles for py2.4, 3.0, 3.1 and ROCK_SOLID mode 2010-01-14 11:54:51 +01:00
roberto@voldemort 0152fb077b fix for process management 2010-01-14 10:29:42 +01:00
roberto@voldemort 440d42303d another typo. damn. 2010-01-13 09:30:36 +01:00
roberto@voldemort 72e28580a6 fix typo 2010-01-13 09:30:01 +01:00
roberto@sirius acf7984eb3 finally a working (and fast) lighttpd module 2010-01-11 18:38:32 +01:00
roberto@sirius bda58ad5cd lighttpd module 2010-01-11 17:33:48 +01:00
roberto@sirius 89258474ad allow single-app definition using 'application' callable 2010-01-11 17:00:43 +01:00
roberto@sirius dc01fc4b42 help/usage for 0.9.4 release 2010-01-11 16:47:14 +01:00
roberto@sirius 0dd5add615 no-server mode (useful for using uwsgi embedded module in standalone apps) 2010-01-11 16:24:36 +01:00
92 changed files with 12165 additions and 5275 deletions
+4
View File
@@ -0,0 +1,4 @@
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
+71
View File
@@ -1,3 +1,74 @@
*** may 2010 ***
* 0.9.5 [20100501] *
- hook based request/modifier management
- plugin support via dlopen
- on-the-fly management flag
- integrated proxy
- logging via udp
- improved spooler for cron-like apps
- async support
- green thread platform (uGreen) on top of teh async mode
- transparent Erlang integration
- embedded snmp agent
- nagios mode
- improved python 3.x support
- improved xml configuration
- new build system
- address space usage limiting
- lot of portability fixes
- lot of optimizations and code refactoring
*** april 2010 ***
* Fourth Maintenance release [20100427] *
- backported non-yielding app optimization from 0.9.5
- backported udp logging from 0.9.5
- backported uwsgi_error() from 0.9.5 (no more dumb perror())
- fix a rare (but possible) segmentation fault
- added --version
- updated apache2 module
*** march 2010 ***
* Third Maintenance release [20100310] *
- fix sendfile on 64bit
- include setup.py
*** february 2010 ***
* Maintenance release *
- better support for NetBSD
- threading fix for FreeBSD
- sendfile portability fixes
- new makefiles
- example app for testing static file serving
- fixes for ROCK_SOLID mode
*** january 2010 ***
- Integrated Spooler
- better error management
- long options
- clustering functions
- experimental lighttpd module
- official support for OpenBSD and OpenSolaris
- FastFuncs
- new functions for embedded module
- reliable harakiri
- better Makefiles
- python threads support in master process
- proper timeout handling in apache2 module
- endianess fixes all over the place
- paste support
- Django app for managing and monitoring the uWSGI server
- options for changin uid/gid and chrooting when run by root
- lot of bugfixes and optimizations
*** 20091129 Version 0.9.3 ***
- Nginx 0.7.x module
+2 -13
View File
@@ -1,13 +1,2 @@
CC=gcc
PYTHON_CFLAGS=`python2.5-config --cflags`
PYTHON_LIBS=`python2.5-config --libs`
XML_CFLAGS=`xml2-config --cflags`
XML_LIBS=`xml2-config --libs`
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
PROGRAM=uwsgi
include base.mk
all:
python uwsgiconfig.py --build
-31
View File
@@ -1,31 +0,0 @@
CC=/usr/lib/llvm/llvm/gcc-4.2/bin/llvm-gcc
PYTHON_CFLAGS=`python2.5-config --cflags`
PYTHON_LIBS=`python2.5-config --libs`
XML_CFLAGS=`xml2-config --cflags`
XML_LIBS=`xml2-config --libs`
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
PROGRAM=uwsgi
all: uwsgi
uwsgi: utils.o socket.o pymodule.o main.o
$(CC) $(LD_FLAGS) utils.o socket.o pymodule.o main.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
socket.o: socket.c
$(CC) -c $(CFLAGS) socket.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o socket.o pymodule.o main.o
-31
View File
@@ -1,31 +0,0 @@
CC=/usr/lib/llvm/llvm/gcc-4.2/bin/llvm-gcc
PYTHON_CFLAGS=`python2.6-config --cflags`
PYTHON_LIBS=`python2.6-config --libs`
XML_CFLAGS=`xml2-config --cflags`
XML_LIBS=`xml2-config --libs`
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
PROGRAM=uwsgi26
all: uwsgi
uwsgi: utils.o socket.o pymodule.o main.o
$(CC) $(LD_FLAGS) utils.o socket.o pymodule.o main.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
socket.o: socket.c
$(CC) -c $(CFLAGS) socket.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o socket.o pymodule.o main.o
+2
View File
@@ -0,0 +1,2 @@
all:
python2.4 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python2.5 uwsgiconfig.py --build
+2 -13
View File
@@ -1,13 +1,2 @@
CC=gcc
PYTHON_CFLAGS=`python2.6-config --cflags`
PYTHON_LIBS=`python2.6-config --libs`
XML_CFLAGS=`xml2-config --cflags`
XML_LIBS=`xml2-config --libs`
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
PROGRAM=uwsgi26
include base.mk
all:
python2.6 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python3.0 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python3.1 uwsgiconfig.py --build
-29
View File
@@ -1,29 +0,0 @@
CC=gcc
PYTHON_CFLAGS=`python2.6-config --cflags`
PYTHON_LIBS=`python2.6-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DROCK_SOLID
LD_FLAGS=$(PYTHON_LIBS) -DROCK_SOLID
PROGRAM=uwsgi26_rs
all: uwsgi
uwsgi: utils.o socket.o pymodule.o main.o
$(CC) $(LD_FLAGS) utils.o socket.o pymodule.o main.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
socket.o: socket.c
$(CC) -c $(CFLAGS) socket.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o socket.o pymodule.o main.o
-26
View File
@@ -1,26 +0,0 @@
CC=gcc
PYTHON_CFLAGS=`python2.4-config --cflags`
PYTHON_LIBS=`python2.4-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
PROGRAM=/usr/share/unbit/uwsgi24
all: clean uwsgi
uwsgi: utils.o pymodule.o main.o
$(CC) $(LD_FLAGS) main.o utils.o pymodule.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o pymodule.o main.o
-26
View File
@@ -1,26 +0,0 @@
CC=gcc
PYTHON_CFLAGS=`python2.5-config --cflags`
PYTHON_LIBS=`python2.5-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
PROGRAM=/usr/share/unbit/uwsgi
all: clean uwsgi
uwsgi: utils.o pymodule.o main.o
$(CC) $(LD_FLAGS) main.o utils.o pymodule.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o pymodule.o main.o
-33
View File
@@ -1,33 +0,0 @@
CC=gcc
PYBASE=/opt/packages/python/26
PATH := ${PATH}:$(PYBASE)/bin
LD_LIBRARY_PATH= $(PYBASE)/lib
export LD_LIBRARY_PATH
PYTHON_CFLAGS=`python2.6-config --cflags`
PYTHON_LIBS=`python2.6-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE -L $(LD_LIBRARY_PATH)
PROGRAM=/usr/share/unbit/uwsgi26
all: clean uwsgi
uwsgi: utils.o pymodule.o main.o
$(CC) $(LD_FLAGS) main.o utils.o pymodule.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o pymodule.o main.o
-30
View File
@@ -1,30 +0,0 @@
CC=gcc
PYBASE=/opt/packages/python/30
PATH := ${PATH}:$(PYBASE)/bin
LD_LIBRARY_PATH= $(PYBASE)/lib
export LD_LIBRARY_PATH
PYTHON_CFLAGS=`python3.0-config --cflags`
PYTHON_LIBS=`python3.0-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE -DPYTHREE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE -DPYTHREE -L $(LD_LIBRARY_PATH)
PROGRAM=/usr/share/unbit/uwsgi30
all: clean uwsgi
uwsgi: utils.o main.o
$(CC) $(LD_FLAGS) main.o utils.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o main.o
-30
View File
@@ -1,30 +0,0 @@
CC=gcc
PYBASE=/opt/packages/python/31
PATH := ${PATH}:$(PYBASE)/bin
LD_LIBRARY_PATH= $(PYBASE)/lib
export LD_LIBRARY_PATH
PYTHON_CFLAGS=`python3.1-config --cflags`
PYTHON_LIBS=`python3.1-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE -DPYTHREE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE -DPYTHREE -L $(LD_LIBRARY_PATH)
PROGRAM=/usr/share/unbit/uwsgi31
all: clean uwsgi
uwsgi: utils.o main.o
$(CC) $(LD_FLAGS) main.o utils.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o main.o
+116 -21
View File
@@ -24,8 +24,8 @@ To compile:
apxs2 -i -c mod_uwsgi.c
(OSX)
sudo apxs -i -a -c mod_uwsgi.c
(OSX 64bit)
sudo apxs -i -a -c -Wc,'-arch x86_64' -Wl,'-arch x86_64' mod_uwsgi.c
(OSX Universal binary)
sudo apxs -i -a -c -Wc,"-arch ppc -arch i386 -arch x86_64" -Wl,"-arch ppc -arch i386 -arch x86_64" mod_uwsgi.c
Configure:
@@ -71,25 +71,73 @@ typedef struct {
uint8_t modifier1;
uint8_t modifier2;
char script_name[256];
char scheme[9];
int cgi_mode ;
} uwsgi_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
#if APR_IS_BIGENDIAN
static uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
#endif
static int uwsgi_add_var(struct iovec *vec, int i, char *key, char *value, uint16_t *pkt_size) {
vec[i].iov_base = &vec[i+1].iov_len ;
vec[i].iov_len = 2 ;
#if APR_IS_BIGENDIAN
char *ptr;
vec[i+2].iov_base = key ;
vec[i+2].iov_len = strlen(key) ;
#else
vec[i+1].iov_base = key ;
vec[i+1].iov_len = strlen(key) ;
vec[i+2].iov_base = &vec[i+3].iov_len ;
vec[i+2].iov_len = 2 ;
vec[i+3].iov_base = value ;
vec[i+3].iov_len = strlen(value) ;
#endif
#if APR_IS_BIGENDIAN
ptr = (char *) &vec[i+2].iov_len;
vec[i].iov_base = ptr+sizeof(long)-1 ;
vec[i].iov_len = 1 ;
vec[i+1].iov_base = ptr+sizeof(long)-2 ;
vec[i+1].iov_len = 1 ;
#else
vec[i].iov_base = &vec[i+1].iov_len ;
vec[i].iov_len = 2 ;
#endif
#if APR_IS_BIGENDIAN
vec[i+5].iov_base = value ;
vec[i+5].iov_len = strlen(value) ;
#else
vec[i+3].iov_base = value ;
vec[i+3].iov_len = strlen(value) ;
#endif
#if APR_IS_BIGENDIAN
ptr = (char *) &vec[i+5].iov_len;
vec[i+3].iov_base = ptr+sizeof(long)-1 ;
vec[i+3].iov_len = 1 ;
vec[i+4].iov_base = ptr+sizeof(long)-2 ;
vec[i+4].iov_len = 1 ;
#else
vec[i+2].iov_base = &vec[i+3].iov_len ;
vec[i+2].iov_len = 2 ;
#endif
#if APR_IS_BIGENDIAN
*pkt_size+= vec[i+2].iov_len + vec[i+5].iov_len + 4 ;
#else
*pkt_size+= vec[i+1].iov_len + vec[i+3].iov_len + 4 ;
#endif
#if APR_IS_BIGENDIAN
return i+6;
#else
return i+4;
#endif
}
static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
@@ -195,12 +243,17 @@ 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
int vecptr = 1 ;
char pkt_header[4];
uint16_t pkt_size = 0;
char buf[4096] ;
int cnt,i ;
int i ;
ssize_t cnt ;
const apr_array_header_t *headers;
apr_table_entry_t *h;
char *penv, *cp;
@@ -272,9 +325,16 @@ static int uwsgi_handler(request_rec *r) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_URI", r->uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "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, "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) ;
}
if (c->script_name[0] == '/') {
if (c->script_name[1] == 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
@@ -302,6 +362,7 @@ static int uwsgi_handler(request_rec *r) {
}
}
headers = apr_table_elts(r->headers_in);
h = (apr_table_entry_t *) headers->elts;
@@ -339,7 +400,13 @@ static int uwsgi_handler(request_rec *r) {
uwsgi_vars[0].iov_len = 4;
pkt_header[0] = c->modifier1 ;
#if APR_IS_BIGENDIAN
pkt_size = uwsgi_swap16(pkt_size);
memcpy(pkt_header+1, &pkt_size, 2);
pkt_size = uwsgi_swap16(pkt_size);
#else
memcpy(pkt_header+1, &pkt_size, 2);
#endif
pkt_header[3] = c->modifier2 ;
cnt = writev( uwsgi_poll.fd, uwsgi_vars, vecptr );
@@ -354,6 +421,7 @@ static int uwsgi_handler(request_rec *r) {
return HTTP_INTERNAL_SERVER_ERROR;
}
if (ap_should_client_block(r)) {
while ((cnt = ap_get_client_block(r, buf, 4096)) > 0) {
@@ -366,25 +434,35 @@ static int uwsgi_handler(request_rec *r) {
}
}
if (!c->cgi_mode) {
r->assbackwards = 1 ;
uwsgi_http_status[13] = 0 ;
uwsgi_http_status[12] = 0 ;
}
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
uwsgi_poll.events = POLLIN ;
for(;;) {
/* put -1 to disable timeout on zero */
cnt = poll(&uwsgi_poll, 1, (c->socket_timeout*1000)-1) ;
if (cnt == 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
break;
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
cnt = recv(uwsgi_poll.fd, buf, 4096, 0) ;
if (cnt > 0) {
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
if (!c->cgi_mode && uwsgi_http_status_read < 12) {
if (uwsgi_http_status_read + cnt >= 12) {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, 12-uwsgi_http_status_read);
@@ -397,31 +475,32 @@ static int uwsgi_handler(request_rec *r) {
}
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
}
else if (cnt == 0) {
break;
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
break;
}
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
break;
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
close(uwsgi_poll.fd);
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
if (!c->cgi_mode) {
if (uwsgi_http_status_read == 0) {
return HTTP_INTERNAL_SERVER_ERROR;
}
}
else {
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
if (hret = ap_scan_script_header_err_brigade(r, bb, NULL)) {
apr_brigade_destroy(bb);
@@ -429,7 +508,8 @@ static int uwsgi_handler(request_rec *r) {
}
}
return ap_pass_brigade(r->output_filters, bb);
return ap_pass_brigade(r->output_filters, bb) ;
}
static const char * cmd_uwsgi_force_script_name(cmd_parms *cmd, void *cfg, const char *location) {
@@ -446,6 +526,20 @@ static const char * cmd_uwsgi_force_script_name(cmd_parms *cmd, void *cfg, const
}
static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const char *scheme) {
uwsgi_cfg *c = cfg;
if (strlen(scheme) < 9 & strlen(scheme) > 0) {
strcpy(c->scheme, scheme);
}
else {
return "ignored uWSGIforceWSGIscheme. Invalid size (max 8 chars)" ;
}
return NULL ;
}
static const char * cmd_uwsgi_modifier1(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
@@ -588,6 +682,7 @@ static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE1("uWSGImodifier2", cmd_uwsgi_modifier2, NULL, RSRC_CONF|ACCESS_CONF, "Set uWSGI modifier2"),
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\")"),
{NULL}
};
+459
View File
@@ -0,0 +1,459 @@
#ifdef UWSGI_ASYNC
#include "uwsgi.h"
#ifdef __linux__
#include <sys/epoll.h>
int async_queue_init(int serverfd) {
int epfd ;
struct epoll_event ee;
epfd = epoll_create(256);
if (epfd < 0) {
uwsgi_error("epoll_create()");
return -1 ;
}
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = serverfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, serverfd, &ee)) {
uwsgi_error("epoll_ctl()");
close(epfd);
return -1;
}
return epfd;
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret ;
if (timeout <= 0) {
timeout = block;
}
else {
timeout = timeout*1000;
}
//uwsgi_log("waiting with timeout %d nevents %d\n", timeout, nevents);
ret = epoll_wait(queuefd, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
uwsgi_error("epoll_wait()");
}
return ret ;
}
int async_add(int queuefd, int fd, int etype) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_MOD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return 0;
}
int async_del(int queuefd, int fd, int etype) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return 0;
}
#elif defined(__sun__)
int async_queue_init(int serverfd) {
int dpfd ;
struct pollfd dpev;
dpfd = open("/dev/poll", O_RDWR);
if (dpfd < 0) {
uwsgi_error("open()");
return -1 ;
}
dpev.fd = serverfd;
dpev.events = POLLIN ;
dpev.revents = 0;
if (write(dpfd, &dpev, sizeof(struct pollfd)) < 0) {
uwsgi_error("write()");
return -1;
}
return dpfd;
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret ;
struct dvpoll dv ;
if (timeout <= 0) {
timeout = block;
}
else {
timeout = timeout*1000;
}
dv.dp_fds = (struct pollfd *) events;
dv.dp_nfds = nevents;
dv.dp_timeout = timeout;
//uwsgi_log("waiting with timeout %d nevents %d\n", timeout, nevents);
ret = ioctl(queuefd, DP_POLL, &dv);
if (ret < 0) {
uwsgi_error("ioctl()");
}
return ret ;
}
int async_add(int queuefd, int fd, int etype) {
struct pollfd pl;
pl.fd = fd ;
pl.events = etype ;
pl.revents = 0 ;
if (write(queuefd, &pl, sizeof(struct pollfd)) < 0) {
uwsgi_error("write()");
return -1;
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
// using the same fd will overwrite existing rule
return async_add(queuefd, fd, etype);
}
int async_del(int queuefd, int fd, int etype) {
// use POLLREMOVE to remove an fd
return async_add(queuefd, fd, POLLREMOVE);
}
#else
int async_queue_init(int serverfd) {
int kfd ;
struct kevent kev;
kfd = kqueue();
if (kfd < 0) {
uwsgi_error("kqueue()");
return -1 ;
}
EV_SET(&kev, serverfd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(kfd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return kfd;
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret;
struct timespec ts ;
if (timeout <= 0) {
if (!block) {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout ;
ret = kevent(queuefd, NULL, 0, events, nevents, &ts);
}
else {
ret = kevent(queuefd, NULL, 0, events, nevents, NULL);
}
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout ;
ret = kevent(queuefd, NULL, 0, events, nevents, &ts);
}
if (ret < 0) {
uwsgi_error("kevent()");
}
return ret;
}
int async_add(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, etype, EV_ADD, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, ASYNC_OUT, EV_DISABLE, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
EV_SET(&kev, fd, etype, EV_ADD, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
int async_del(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, etype, EV_DELETE, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
#endif
inline struct wsgi_request *next_wsgi_req(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
uint8_t *ptr = (uint8_t *) wsgi_req ;
ptr += sizeof(struct wsgi_request) ;
return (struct wsgi_request *) ptr ;
}
int async_get_timeout(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
if (!uwsgi->async_running) return 0;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_timeout_expired) {
return 0;
}
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return 0;
}
void async_expire_timeouts(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t deadline = time(NULL);
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN && wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_timeout = 0 ;
wsgi_req->async_timeout_expired = 1 ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_OK) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return NULL ;
}
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *uwsgi, int async_id) {
uint8_t *ptr = (uint8_t *) uwsgi->wsgi_requests ;
ptr += sizeof(struct wsgi_request) * async_id ;
return (struct wsgi_request *) ptr ;
}
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *uwsgi, int fd, int etype) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
if (etype != -1) {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd && wsgi_req->async_waiting_fd_type == etype) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
else {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
return NULL ;
}
void async_set_timeout(struct wsgi_request *wsgi_req, time_t timeout) {
wsgi_req->async_timeout = time(NULL);
wsgi_req->async_timeout += timeout;
wsgi_req->async_timeout_expired = 0 ;
}
void async_write_all(struct uwsgi_server *uwsgi, char *data, size_t len) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
ssize_t rlen ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
uwsgi_error("write()");
}
else {
wsgi_req->response_size += rlen ;
}
}
}
}
void async_unpause_all(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
}
}
}
struct wsgi_request * async_loop(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req ;
int i ;
uwsgi->async_running = -1 ;
wsgi_req = uwsgi->wsgi_requests ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_waiting_fd != -1 && !wsgi_req->async_waiting_fd_monitored) {
// add fd to monitoring
if (async_add(uwsgi->async_queue, wsgi_req->async_waiting_fd, wsgi_req->async_waiting_fd_type)) {
// error adding fd to the async queue, better to close it...
close(wsgi_req->async_waiting_fd);
wsgi_req->async_status = UWSGI_OK ;
return wsgi_req;
}
wsgi_req->async_waiting_fd_monitored = 1;
wsgi_req->async_status = UWSGI_AGAIN;
}
else if (wsgi_req->async_waiting_fd == -1 && wsgi_req->async_timeout <= 0) {
uwsgi->async_running = 0 ;
// st global wsgi_req for python functions
uwsgi->wsgi_req = wsgi_req ;
wsgi_req->async_status = (*uwsgi->shared->hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
wsgi_req->async_switches++;
if (wsgi_req->async_status < UWSGI_AGAIN) {
return wsgi_req;
}
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return NULL;
}
#endif
-25
View File
@@ -1,25 +0,0 @@
all: clean uwsgi
uwsgi: utils.o protocol.o socket.o pymodule.o spooler.o main.o
$(CC) $(LD_FLAGS) utils.o protocol.o socket.o spooler.o pymodule.o main.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
protocol.o: protocol.c
$(CC) -c $(CFLAGS) protocol.c
socket.o: socket.c
$(CC) -c $(CFLAGS) socket.c
spooler.o: spooler.c
$(CC) -c $(CFLAGS) spooler.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o protocol.o socket.o pymodule.o spooler.o main.o
+1
View File
@@ -0,0 +1 @@
the uwsgi handler is included in the official Cherokee distribution
-92
View File
@@ -1,92 +0,0 @@
from Form import *
from Table import *
from Module import *
from validations import *
from consts import *
# For gettext
N_ = lambda x: x
from ModuleCgi import *
from ModuleBalancer import NOTE_BALANCER
HELPS = [
('modules_handlers_uwsgi', "UWSGI")
]
class ModuleUwsgi (ModuleCgiBase):
PROPERTIES = ModuleCgiBase.PROPERTIES + [
'balancer',
'modifier1',
'modifier2',
'pass_wsgi_vars',
'pass_request_body'
]
def __init__ (self, cfg, prefix, submit):
ModuleCgiBase.__init__ (self, cfg, prefix, 'uwsgi', submit)
self.show_script_alias = False
self.show_change_uid = False
self.show_document_root = True
def _op_render (self):
txt = ModuleCgiBase._op_render (self)
txt += '<h2>%s</h2>' % (_('UWSGI specific'))
table = TableProps()
opt = "%s!modifier1" % (self._prefix)
self.AddPropEntry(table, _('Modifier1'), opt, 'a number between 0 and 255', size=3);
opt = "%s!modifier2" % (self._prefix)
self.AddPropEntry(table, _('Modifier2'), opt, 'a number between 0 and 255', size=3);
opt = "%s!pass_wsgi_vars" % (self._prefix)
self.AddPropCheck (table, _("Pass WSGI vars"), opt, True, 'pass all the wsgi vars to the application')
opt = "%s!pass_request_body" % (self._prefix)
self.AddPropCheck (table, _("Pass Request body"), opt, True, 'pass the request body to the application')
opt = "%s!balancer" % (self._prefix)
e = self.AddPropOptions_Reload_Module (table, _("Balancer"), opt,
modules_available(BALANCERS), _(NOTE_BALANCER))
txt += self.Indent(str(table) + e)
return txt
def _op_apply_changes (self, uri, post):
# Apply modifier1
opt = "%s!modifier1" % (self._prefix)
mod1 = post.pop(opt)
if mod1:
self._cfg[opt] = mod1
# Apply modifier2
opt = "%s!modifier2" % (self._prefix)
mod2 = post.pop(opt)
if mod2:
self._cfg[opt] = mod2
# Apply pass_request_body and pass_wsgi_vars
self.ApplyChangesPrefix (self._prefix, ['pass_wsgi_vars','pass_request_body'], post)
# Apply balancer changes
pre = "%s!balancer" % (self._prefix)
new_balancer = post.pop(pre)
if new_balancer:
self._cfg[pre] = new_balancer
cfg = self._cfg[pre]
if cfg and cfg.value:
name = cfg.value
props = module_obj_factory (name, self._cfg, pre, self.submit_url)
props._op_apply_changes (uri, post)
# And CGI changes
return ModuleCgiBase._op_apply_changes (self, uri, post)
-452
View File
@@ -1,452 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Cherokee
*
* Authors:
* Alvaro Lopez Ortega <alvaro@alobbs.com>
*
* Copyright (C) 2001-2009 Alvaro Lopez Ortega
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "common-internal.h"
#include "handler_uwsgi.h"
#include "connection.h"
#include "source_interpreter.h"
#include "thread.h"
#include "util.h"
#include "connection-protected.h"
#include "bogotime.h"
#define ENTRIES "handler,cgi"
/* Plug-in initialization
*/
CGI_LIB_INIT (uwsgi, http_all_methods);
#if BYTE_ORDER == BIG_ENDIAN
static uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
#endif
/* Methods implementation
*/
static ret_t
props_free (cherokee_handler_uwsgi_props_t *props)
{
if (props->balancer)
cherokee_balancer_free (props->balancer);
return cherokee_handler_cgi_base_props_free (PROP_CGI_BASE(props));
}
ret_t
cherokee_handler_uwsgi_configure (cherokee_config_node_t *conf, cherokee_server_t *srv, cherokee_module_props_t **_props)
{
ret_t ret;
cherokee_list_t *i;
cherokee_handler_uwsgi_props_t *props;
/* Instance a new property object
*/
if (*_props == NULL) {
CHEROKEE_NEW_STRUCT (n, handler_uwsgi_props);
cherokee_handler_cgi_base_props_init_base (PROP_CGI_BASE(n),
MODULE_PROPS_FREE(props_free));
n->balancer = NULL;
n->modifier1 = 0 ;
n->modifier2 = 0 ;
n->pass_wsgi_vars = true;
n->pass_request_body = true;
*_props = MODULE_PROPS(n);
}
props = PROP_UWSGI(*_props);
/* Parse the configuration tree
*/
cherokee_config_node_foreach (i, conf) {
cherokee_config_node_t *subconf = CONFIG_NODE(i);
if (equal_buf_str (&subconf->key, "balancer")) {
ret = cherokee_balancer_instance (&subconf->val, subconf, srv, &props->balancer);
if (ret != ret_ok) return ret;
}
else if (equal_buf_str (&subconf->key, "modifier1")) {
props->modifier1 = (uint8_t) atoi(subconf->val.buf);
}
else if (equal_buf_str (&subconf->key, "modifier2")) {
props->modifier2 = (uint8_t) atoi(subconf->val.buf);
}
else if (equal_buf_str (&subconf->key, "pass_wsgi_vars")) {
props->pass_wsgi_vars = !! atoi (subconf->val.buf);
}
else if (equal_buf_str (&subconf->key, "pass_request_body")) {
props->pass_request_body = !! atoi (subconf->val.buf);
}
}
/* Init base class
*/
ret = cherokee_handler_cgi_base_configure (conf, srv, _props);
if (ret != ret_ok) return ret;
/* Final checks
*/
if (props->balancer == NULL) {
LOG_CRITICAL_S (CHEROKEE_ERROR_HANDLER_NO_BALANCER);
return ret_error;
}
return ret_ok;
}
static void
add_env_pair (cherokee_handler_cgi_base_t *cgi_base,
const char *key, int key_len,
const char *val, int val_len)
{
cherokee_handler_uwsgi_t *uwsgi = HDL_UWSGI(cgi_base);
uint16_t u_key_len = (uint16_t) key_len ;
uint16_t u_val_len = (uint16_t) val_len ;
/* 2 bytes for every string (16 bit le) */
cherokee_buffer_ensure_size (&uwsgi->header, uwsgi->header.len + key_len + val_len + 4);
/* force to le if cherokee is big-endian */
#if BYTE_ORDER == BIG_ENDIAN
u_key_len = uwsgi_swap16(u_key_len);
#endif
cherokee_buffer_add (&uwsgi->header, (const char *) &u_key_len, 2);
#if BYTE_ORDER == BIG_ENDIAN
u_key_len = uwsgi_swap16(u_key_len);
#endif
cherokee_buffer_add (&uwsgi->header, key, key_len);
#if BYTE_ORDER == BIG_ENDIAN
u_val_len = uwsgi_swap16(u_val_len);
#endif
cherokee_buffer_add (&uwsgi->header, (const char *) &u_val_len, 2);
#if BYTE_ORDER == BIG_ENDIAN
u_val_len = uwsgi_swap16(u_val_len);
#endif
cherokee_buffer_add (&uwsgi->header, val, val_len);
}
static ret_t
read_from_uwsgi (cherokee_handler_cgi_base_t *cgi_base, cherokee_buffer_t *buffer)
{
ret_t ret;
size_t read = 0;
cherokee_handler_uwsgi_t *uwsgi = HDL_UWSGI(cgi_base);
ret = cherokee_socket_bufread (&uwsgi->socket, buffer, 4096, &read);
switch (ret) {
case ret_eagain:
cherokee_thread_deactive_to_polling (HANDLER_THREAD(cgi_base), HANDLER_CONN(cgi_base),
uwsgi->socket.socket, 0, false);
return ret_eagain;
case ret_ok:
TRACE (ENTRIES, "%d bytes read\n", read);
return ret_ok;
case ret_eof:
case ret_error:
cgi_base->got_eof = true;
return ret;
default:
RET_UNKNOWN(ret);
}
SHOULDNT_HAPPEN;
return ret_error;
}
ret_t
cherokee_handler_uwsgi_new (cherokee_handler_t **hdl, void *cnt, cherokee_module_props_t *props)
{
CHEROKEE_NEW_STRUCT (n, handler_uwsgi);
/* Init the base class
*/
cherokee_handler_cgi_base_init (
HDL_CGI_BASE(n), cnt,
PLUGIN_INFO_HANDLER_PTR(uwsgi),
HANDLER_PROPS(props),
add_env_pair, read_from_uwsgi);
/* Virtual methods
*/
MODULE(n)->init = (handler_func_init_t) cherokee_handler_uwsgi_init;
MODULE(n)->free = (module_func_free_t) cherokee_handler_uwsgi_free;
/* Virtual methods: implemented by handler_cgi_base
*/
HANDLER(n)->step = (handler_func_step_t) cherokee_handler_cgi_base_step;
HANDLER(n)->add_headers = (handler_func_add_headers_t) cherokee_handler_cgi_base_add_headers;
/* Properties
*/
n->post_len = 0;
n->src_ref = NULL;
cherokee_buffer_init (&n->header);
cherokee_socket_init (&n->socket);
/* Return the object
*/
*hdl = HANDLER(n);
return ret_ok;
}
ret_t
cherokee_handler_uwsgi_free (cherokee_handler_uwsgi_t *hdl)
{
/* Free the rest of the handler CGI memory
*/
cherokee_handler_cgi_base_free (HDL_CGI_BASE(hdl));
/* UWSGI stuff
*/
cherokee_socket_close (&hdl->socket);
cherokee_socket_mrproper (&hdl->socket);
cherokee_buffer_mrproper (&hdl->header);
return ret_ok;
}
static ret_t
uwsgi_fix_packet (cherokee_buffer_t *buf, uint8_t modifier1, uint8_t modifier2)
{
uwsgi_header uh;
uh.modifier1 = modifier1 ;
uh.modifier2 = modifier2 ;
#if BYTE_ORDER == BIG_ENDIAN
uh.env_size = uwsgi_swap16((uint16_t) buf->len) ;
#else
uh.env_size = (uint16_t) buf->len ;
#endif
cherokee_buffer_ensure_size (buf, buf->len + 4);
cherokee_buffer_prepend (buf, (const char * )&uh, 4);
return ret_ok;
}
static ret_t
build_header (cherokee_handler_uwsgi_t *hdl)
{
cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl);
cuint_t len;
char tmp[64];
if (props->pass_request_body == true && props->pass_wsgi_vars == true) {
len = snprintf (tmp, sizeof(tmp), FMT_OFFSET, (CST_OFFSET)hdl->post_len);
add_env_pair(HDL_CGI_BASE(hdl), "CONTENT_LENGTH", 14, tmp, len);
}
if (props->pass_wsgi_vars == true) {
cherokee_handler_cgi_base_build_envp (HDL_CGI_BASE(hdl), HANDLER_CONN(hdl));
}
return uwsgi_fix_packet (&hdl->header, props->modifier1, props->modifier2);
}
static ret_t
connect_to_server (cherokee_handler_uwsgi_t *hdl)
{
ret_t ret;
cherokee_connection_t *conn = HANDLER_CONN(hdl);
cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl);
/* Get a reference to the target host
*/
if (hdl->src_ref == NULL) {
ret = cherokee_balancer_dispatch (props->balancer, conn, &hdl->src_ref);
if (ret != ret_ok)
return ret;
}
/* Try to connect
*/
if (hdl->src_ref->type == source_host) {
ret = cherokee_source_connect_polling (hdl->src_ref, &hdl->socket, conn);
if ((ret == ret_deny) || (ret == ret_error))
{
cherokee_balancer_report_fail (props->balancer, conn, hdl->src_ref);
}
} else {
ret = cherokee_source_interpreter_connect_polling (SOURCE_INT(hdl->src_ref),
&hdl->socket, conn);
}
return ret;
}
static ret_t
send_header (cherokee_handler_uwsgi_t *hdl)
{
ret_t ret;
size_t written = 0;
cherokee_connection_t *conn = HANDLER_CONN(hdl);
ret = cherokee_socket_bufwrite (&hdl->socket, &hdl->header, &written);
if (ret != ret_ok) {
conn->error_code = http_bad_gateway;
return ret;
}
#if 0
cherokee_buffer_print_debug (&hdl->header, -1);
#endif
cherokee_buffer_move_to_begin (&hdl->header, written);
TRACE (ENTRIES, "sent remaining=%d\n", hdl->header.len);
if (! cherokee_buffer_is_empty (&hdl->header))
return ret_eagain;
return ret_ok;
}
static ret_t
send_post (cherokee_handler_uwsgi_t *hdl)
{
ret_t ret;
int e_fd = -1;
int mode = 0;
cherokee_connection_t *conn = HANDLER_CONN(hdl);
ret = cherokee_post_walk_to_fd (&conn->post, hdl->socket.socket, &e_fd, &mode);
switch (ret) {
case ret_ok:
break;
case ret_eagain:
if (e_fd != -1)
cherokee_thread_deactive_to_polling (HANDLER_THREAD(hdl), conn, e_fd, mode, false);
return ret_eagain;
default:
conn->error_code = http_bad_gateway;
return ret;
}
return ret_ok;
}
ret_t
cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl)
{
ret_t ret;
cherokee_connection_t *conn = HANDLER_CONN(hdl);
cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl);
switch (HDL_CGI_BASE(hdl)->init_phase) {
case hcgi_phase_build_headers:
TRACE (ENTRIES, "Init: %s\n", "begins");
/* Extracts PATH_INFO and filename from request uri
*/
ret = cherokee_handler_cgi_base_extract_path (HDL_CGI_BASE(hdl), false);
if (unlikely (ret < ret_ok)) {
conn->error_code = http_internal_error;
return ret_error;
}
/* Prepare Post
*/
if (! cherokee_post_is_empty (&conn->post)) {
cherokee_post_walk_reset (&conn->post);
cherokee_post_get_len (&conn->post, &hdl->post_len);
}
/* Build the headers
*/
ret = build_header (hdl);
if (unlikely (ret != ret_ok)) {
conn->error_code = http_internal_error;
return ret_error;
}
HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_connect;
case hcgi_phase_connect:
TRACE (ENTRIES, "Init: %s\n", "connect");
/* Connect
*/
ret = connect_to_server (hdl);
switch (ret) {
case ret_ok:
break;
case ret_eagain:
return ret_eagain;
case ret_deny:
conn->error_code = http_gateway_timeout;
return ret_error;
default:
conn->error_code = http_service_unavailable;
return ret_error;
}
HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_send_headers;
case hcgi_phase_send_headers:
TRACE (ENTRIES, "Init: %s\n", "send_headers");
/* Send the header
*/
ret = send_header (hdl);
if (ret != ret_ok)
return ret;
HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_send_post;
case hcgi_phase_send_post:
/* Send the Post
*/
if (hdl->post_len > 0 && props->pass_request_body == true) {
return send_post (hdl);
}
break;
}
return ret_ok;
}
-78
View File
@@ -1,78 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Cherokee
*
* Authors:
* Alvaro Lopez Ortega <alvaro@alobbs.com>
*
* Copyright (C) 2001-2009 Alvaro Lopez Ortega
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef CHEROKEE_HANDLER_UWSGI_H
#define CHEROKEE_HANDLER_UWSGI_H
#include "common-internal.h"
#include "handler.h"
#include "buffer.h"
#include "plugin_loader.h"
#include "socket.h"
#include "handler_cgi_base.h"
#include "balancer.h"
typedef struct __attribute__((packed)) {
uint8_t modifier1;
uint16_t env_size;
uint8_t modifier2;
} uwsgi_header ;
typedef struct {
cherokee_handler_cgi_base_t base;
cherokee_balancer_t *balancer;
uint8_t modifier1;
uint8_t modifier2;
cherokee_boolean_t pass_wsgi_vars;
cherokee_boolean_t pass_request_body;
} cherokee_handler_uwsgi_props_t;
typedef struct {
cherokee_handler_cgi_base_t base;
cherokee_buffer_t header;
cherokee_socket_t socket;
cherokee_source_t *src_ref;
time_t spawned;
off_t post_len;
} cherokee_handler_uwsgi_t;
#define HDL_UWSGI(x) ((cherokee_handler_uwsgi_t *)(x))
#define PROP_UWSGI(x) ((cherokee_handler_uwsgi_props_t *)(x))
#define HANDLER_UWSGI_PROPS(x) (PROP_UWSGI(MODULE(x)->props))
/* Library init function
*/
void PLUGIN_INIT_NAME(uwsgi) (cherokee_plugin_loader_t *loader);
/* Methods
*/
ret_t cherokee_handler_uwsgi_new (cherokee_handler_t **hdl, void *cnt, cherokee_module_props_t *props);
ret_t cherokee_handler_uwsgi_free (cherokee_handler_uwsgi_t *hdl);
ret_t cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl);
#endif /* CHEROKEE_HANDLER_UWSGI_H */
-1
View File
@@ -1 +0,0 @@
file
+144
View File
@@ -0,0 +1,144 @@
package Plack::Handler::Uwsgi;
use strict;
use warnings;
use IO::Socket::INET;
use HTTP::Status;
use Plack::Util;
sub new {
my $class = shift;
my $self = bless {@_}, $class;
$self;
}
sub run {
my ($self, $app) = @_;
my $server ;
if (exists($ENV{'UWSGI_FD'})) {
$server = IO::Socket::UNIX->new_from_fd($ENV{'UWSGI_FD'}, '+<');
}
else {
$server = IO::Socket::INET->new(LocalPort => $self->{port}, LocalAddr => $self->{host}, Listen => 100, ReuseAddr => 1);
}
while ( my $client = $server->accept ) {
my $head = '';
my $remains = 4 ;
while($remains) {
$client->recv(my $buf, $remains);
last unless $buf;
$head.=$buf;
$remains -= length($buf);
}
if (length($head) != 4) {
$client->close ;
next;
}
my ($mod1, $envsize, $mod2) = unpack('CvC', $head) ;
unless ($envsize) {
$client->close ;
next;
}
$remains = $envsize ;
my $envbuf = '' ;
while($remains) {
my $buf ;
if ($remains >= 4096) {
$client->recv($buf, 4096);
}
else {
$client->recv($buf, $remains);
}
unless($buf) {
$client->close ;
next;
}
$envbuf.=$buf;
$remains -= length($buf);
}
if (length($envbuf) != $envsize ) {
$client->close ;
next;
}
my %env ;
my $i = 0;
while($i < $envsize) {
my $kl = unpack('v', substr($envbuf, $i, 2)) ; $i+=2;
my $key = substr($envbuf, $i, $kl); $i+=$kl;
my $vl = unpack('v', substr($envbuf, $i, 2)) ; $i+=2;
$env{$key} = substr($envbuf, $i, $vl); $i+=$vl;
}
my $env = {
%env,
'psgi.version' => [1,1],
'psgi.url_scheme' => ($env{HTTPS}||'off') =~ /^(?:on|1)$/i ? 'https' : 'http',
'psgi.input' => $client,
'psgi.errors' => *STDERR,
'psgi.multithread' => Plack::Util::FALSE,
'psgi.multiprocess' => Plack::Util::TRUE,
'psgi.run_once' => Plack::Util::FALSE,
'psgi.streaming' => Plack::Util::TRUE,
'psgi.nonblocking' => Plack::Util::FALSE,
};
my $res = Plack::Util::run_app $app, $env;
if (ref $res eq 'ARRAY') {
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $res);
}
elsif (ref $res eq 'CODE') {
$res->(sub {
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $_[0]);
});
}
else {
die "Bad response $res";
}
$client->close ;
}
}
sub _handle_response {
my ($self, $client, $protocol, $res) = @_;
$client->send($protocol.' '.$res->[0].' '.HTTP::Status::status_message( $res->[0] )."\r\n");
my $headers = $res->[1];
my $hdrs = '';
while (my ($k, $v) = splice @$headers, 0, 2) {
$hdrs .= "$k: $v\r\n";
}
$hdrs .= "\r\n";
$client->send($hdrs);
my $cb = sub { $client->send($_[0]) };
my $body = $res->[2];
if (defined $body) {
Plack::Util::foreach($body, $cb);
}
else {
return Plack::Util::inline_object write => $cb,close => sub { };
}
}
1;
View File
+307
View File
@@ -0,0 +1,307 @@
require 'rubygems'
require 'socket'
require 'rack'
require 'rack/content_length'
require 'rack/rewindable_input'
require 'stringio'
require 'optparse'
options = {
:processes => 1,
:master => false,
:logging => true,
:static => true,
:config => nil,
:cachehack => false
}
opts = OptionParser.new do |opts|
opts.on("-p", "--processes=nproc", Integer, '') { |p| options[:processes] = p }
opts.on("-M", "--master", '') { options[:master] = true }
opts.on("-L", "--no-logging", '') { options[:logging] = false }
opts.on("-S", "--no-static", '') { options[:static] = false }
opts.on("-C", "--cache-hack", '') { options[:cachehack] = true }
opts.parse! ARGV
end
if ARGV[0]
options[:config] = ARGV[0]
end
def human_round(float)
(float * (10 ** 2)).round / (10 ** 2).to_f
end
$requests = 0
$workers = Array.new
module Rack
class RailsCachingHack
def initialize app
@app = app
end
def stripuri(uri)
uri = uri.split('/')
uri.slice!(1)
val = uri.join('/')
end
def call env
env['PATH_INFO'] = stripuri(env['PATH_INFO']) if env['PATH_INFO']
env['REQUEST_URI'] = stripuri(env['REQUEST_URI']) if env['REQUEST_URI']
env['REQUEST_URI'] = '/' if env['REQUEST_URI'] == ''
@app.call env
end
end
module Handler
class Unbit
def self.run(app, options={})
server = UNIXServer.for_fd(0)
can_spawn = true
if options[:master]
$0 = 'uRack master'
$workers[0] = Process.pid
ulog("master process enabled (pid: #{$workers[0]})")
$workers[1] = Process.fork
if $workers[1].to_i > 0
ulog("spawned worker 1 (pid: #{$workers[1]})")
elsif $workers[1].to_i == 0
$0 = "uRack worker 1"
can_spawn = false
end
else
$0 = 'uRack worker 1'
$workers[0] = nil
$workers[1] = Process.pid
ulog("spawned worker 1 (pid: #{$workers[1]})")
end
if options[:processes] > 1 and can_spawn
for p in 2..options[:processes]
$workers[p] = Process.fork
if $workers[p].to_i == 0
$0 = "uRack worker #{p}"
break
elsif $workers[p].to_i > 0
ulog("spawned worker #{p} (pid: #{$workers[p]})")
end
end
end
# am i the master ?
if options[:master] and Process.pid == $workers[0]
while 1
i_am_a_child = false
pid = Process.waitpid
for wid in 1..options[:processes]
if $workers[wid] == pid
ulog("worker #{wid} died ! (pid: #{pid})")
$workers[wid] = Process.fork
if $workers[wid].to_i == 0
$0 = "uRack worker #{wid}"
i_am_a_child = true
break
elsif $workers[wid].to_i > 0
ulog("respawned worker #{wid} (pid: #{$workers[wid]})")
end
end
end
break if i_am_a_child
end
end
while client = server.accept
serve client, app, options
end
end
def self.serve(client, app, options)
speed = Time.now
head, sender = client.recvfrom(4)
unless head
client.close
return
end
mod1, size, mod2 = head.unpack('CvC')
if size == 0 or size.nil?
client.close
return
end
vars, sender = client.recvfrom(size)
if vars.length != size
client.close
return
end
env = Hash.new
i = 0
while i < size
kl = vars[i, 2].unpack('v')[0]
i = i + 2
key = vars[i, kl]
i = i + kl
vl = vars[i, 2].unpack('v')[0]
i = i + 2
value = vars[i, vl]
i = i + vl
env[key] = value
end
env.delete "HTTP_CONTENT_LENGTH"
env.delete "HTTP_CONTENT_TYPE"
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == ""
if env["CONTENT_LENGTH"].to_i > 4096
rack_input = Rack::RewindableInput::Tempfile.new('Rack_unbit_Input')
rack_input.chmod(0000)
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
rack_input.binmode
rack_input.unlink
remains = env["CONTENT_LENGTH"].to_i
while remains > 0
if remains >= 4096
buf, sender = client.recvfrom(4096)
else
buf, sender = client.recvfrom(remains)
end
rack_input.write( buf )
remains -= buf.length
end
elsif env["CONTENT_LENGTH"].to_i > 0
rack_input = StringIO.new(client.recvfrom(env["CONTENT_LENGTH"].to_i)[0])
else
rack_input = StringIO.new('')
end
rack_input.rewind
env.update({"rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
})
app = Rack::ContentLength.new(app)
disconnected = false
begin
status, headers, body = app.call(env)
begin
send_headers client, env["HTTP_VERSION"] ,status, headers
send_body client, body
ensure
body.close if body.respond_to? :close
end
rescue Errno::EPIPE, Errno::ECONNRESET
disconnected = true
ensure
rack_input.close
client.close
end
$requests = $requests+1
ulog("req: #{$requests} ip: #{env['REMOTE_ADDR']} pid: #{Process.pid} as: #{human_round(syscall(356).to_f/1024/1024)} MB => #{env['REQUEST_METHOD']} #{env['REQUEST_URI']} in #{Time.now-speed} secs [#{status}]#{' DISCONNECTED !!!' if disconnected}") if options[:logging]
end
def self.send_headers(client, protocol, status, headers)
client.print "#{protocol} #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}\r\n"
headers.each { |k, vs|
vs.split("\n").each { |v|
client.print "#{k}: #{v}\r\n"
}
}
client.print "\r\n"
client.flush
end
def self.send_body(client, body)
body.each { |part|
client.print part
client.flush
}
end
end
end
end
def ulog(message)
$stderr.puts "[#{Time.new}] uRack: #{message}"
end
ulog("starting at #{Dir.getwd}")
limit_as = human_round(Process.getrlimit(Process::RLIMIT_AS)[1].to_f/1024/1024)
ulog("your process address space limit is #{limit_as} MB")
server = Rack::Handler.get('Unbit')
starttime = Time.now
app = nil
if options[:config]
cfgfile = File.read(options[:config])
if cfgfile[/^#\\(.*)/]
opts.parse! $1.split(/\s+/)
end
app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app", nil, options[:config]
else
# falling back to rails
if Dir.getwd =~ /\/public\/?$/
require '../config/environment'
else
require 'config/environment'
end
app = Rack::Builder.new {
if options[:cachehack]
use Rack::RailsCachingHack
end
if options[:static]
use Rails::Rack::Static
end
if ActionController.const_defined?(:Dispatcher) && (ActionController::Dispatcher.instance_methods.include?(:call) || ActionController::Dispatcher.instance_methods.include?("call"))
run ActionController::Dispatcher.new
else
require 'thin'
run Rack::Adapter::Rails.new(:environment => ENV['RAILS_ENV'])
end
}
end
ulog("your app is ready (in #{Time.now-starttime} seconds).")
server.run(app, options)
View File
View File
+150
View File
@@ -0,0 +1,150 @@
require 'socket'
require 'rack/content_length'
require 'rack/rewindable_input'
require 'stringio'
module Rack
module Handler
class Uwsgi
def self.run(app, options={})
if ENV['UWSGI_FD']
server = UNIXServer.for_fd(ENV['UWSGI_FD'].to_i)
else
server = TCPServer.new(options[:Host], options[:Port])
end
while client = server.accept
serve client, app
end
end
def self.serve(client, app)
head, sender = client.recvfrom(4)
unless head
client.close
return
end
mod1, size, mod2 = head.unpack('CvC')
if size == 0 or size.nil?
client.close
return
end
vars, sender = client.recvfrom(size)
if vars.length != size
client.close
return
end
env = Hash.new
i = 0
while i < size
kl = vars[i, 2].unpack('v')[0]
i = i + 2
key = vars[i, kl]
i = i + kl
vl = vars[i, 2].unpack('v')[0]
i = i + 2
value = vars[i, vl]
i = i + vl
env[key] = value
end
env.delete "HTTP_CONTENT_LENGTH"
env.delete "HTTP_CONTENT_TYPE"
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == ""
if env["CONTENT_LENGTH"].to_i > 4096
rack_input = Rack::RewindableInput::Tempfile.new('Rack_uwsgi_Input')
rack_input.chmod(0000)
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
rack_input.binmode
if RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/
rack_input.unlink
end
remains = env["CONTENT_LENGTH"].to_i
while remains > 0
if remains >= 4096
buf, sender = client.recvfrom(4096)
else
buf, sender = client.recvfrom(remains)
end
rack_input.write( buf )
remains -= buf.length
end
elsif env["CONTENT_LENGTH"].to_i > 0
rack_input = StringIO.new(client.recvfrom(env["CONTENT_LENGTH"].to_i)[0])
else
rack_input = StringIO.new('')
end
rack_input.rewind
env.update({"rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
})
app = Rack::ContentLength.new(app)
begin
status, headers, body = app.call(env)
begin
send_headers client, env["HTTP_VERSION"] ,status, headers
send_body client, body
ensure
body.close if body.respond_to? :close
end
rescue Errno::EPIPE, Errno::ECONNRESET
ensure
rack_input.close
client.close
end
end
def self.send_headers(client, protocol, status, headers)
client.print "#{protocol} #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}\r\n"
headers.each { |k, vs|
vs.split("\n").each { |v|
client.print "#{k}: #{v}\r\n"
}
}
client.print "\r\n"
client.flush
end
def self.send_body(client, body)
body.each { |part|
client.print part
client.flush
}
end
end
end
end
+3 -3
View File
@@ -1,6 +1,6 @@
Package: uwsgi
Version: 0.9.2
Version: 0.9.5
Maintainer: Unbit
Description: Fast, developer-friendly wsgi server
Architecture: i386
Depends: python2.5, libxml2
Architecture: all
Depends: python, libxml2
View File
+69
View File
@@ -0,0 +1,69 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="../">{% trans 'Home' %}</a> &rsaquo;
{% trans 'uWSGI' %}
</div>
{% endblock %}
{% block content %}
<div id="content-main">
<h1>uWSGI status</h1>
<b>masterpid:</b> {{masterpid}}<br/>
<b>started_on:</b> {{started_on}}<br/>
<b>buffer size:</b> {{buffer_size}}<br/>
<b>workers:</b> {{numproc}}<br/>
<b>total requests:</b> {{total_requests}}<br/>
<br/>
<div class="module" style="width:860px">
<table>
<caption style="width:860px">workers</caption>
<thead>
<tr>
<th scope="row">id</th>
<th scope="row">pid</th>
<th scope="row">requests</th>
<th scope="row">running time (milliseconds)</th>
<th scope="row">load</th>
<th scope="row">last spawn</th>
<th scope="row">respawn count</th>
<th scope="row">address space (vsz)</th>
<th scope="row">resident memory (rss)</th>
</tr>
</thead>
<tbody>
{% for w in workers %}
<tr>
<td align="center">{{w.id}}</td>
<td align="center">{{w.pid}}</td>
<td align="right">{{w.requests}}</td>
<td align="right">{{w.running_time}}</td>
<td align="right">{{w.load|floatformat:2}} %</td>
<td align="right">{{w.last_spawn_str}}</td>
<td align="right">{{w.respawn_count}}</td>
<td align="right">{{w.vsz|filesizeformat}}</td>
<td align="right">{{w.rss|filesizeformat}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if masterpid %}
<br/>
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
<input type="submit" value="gracefully reload uWSGI" name="_reload"/>
</form>
{% endif %}
</div>
{% endblock %}
+10
View File
@@ -0,0 +1,10 @@
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from django.conf.urls.defaults import *
urlpatterns = patterns('uwsgi_admin.views',
(r'^$', 'index'),
(r'^reload/$', 'reload')
)
+35
View File
@@ -0,0 +1,35 @@
import uwsgi
import time
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.admin.views.decorators import staff_member_required
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
def index(request):
workers = uwsgi.workers()
total_load = time.time() - uwsgi.started_on
for w in workers:
w['load'] = (100 * (w['running_time']/1000))/total_load
w['last_spawn_str'] = time.ctime(w['last_spawn'])
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
'started_on': time.ctime(uwsgi.started_on),
'buffer_size': uwsgi.buffer_size,
'total_requests': uwsgi.total_requests(),
'numproc': uwsgi.numproc,
'workers': workers,
}, RequestContext(request, {}))
index = staff_member_required(index)
def reload(request):
if uwsgi.masterpid() > 0:
uwsgi.reload()
request.user.message_set.create(message="uWSGI reloaded")
else:
request.user.message_set.create(message="The uWSGI master process is not active")
return HttpResponseRedirect(reverse(index))
reload = staff_member_required(reload)
+702
View File
@@ -0,0 +1,702 @@
#ifdef UWSGI_ERLANG
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static void erlang_log(void);
PyObject *py_erlang_connect(PyObject * self, PyObject * args) {
char *erlang_node;
int fd;
if (!PyArg_ParseTuple(args, "s:erlang_connect", &erlang_node)) {
return NULL;
}
UWSGI_SET_BLOCKING;
fd = erl_connect(erlang_node);
UWSGI_UNSET_BLOCKING;
return PyInt_FromLong(fd);
}
PyObject *py_erlang_recv_message(PyObject * self, PyObject * args) {
int erfd;
struct pollfd erpoll;
ErlMessage emsg;
PyObject *pyer = NULL;
unsigned char erlang_buffer[8192];
int eret;
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
if (!PyArg_ParseTuple(args, "i|i:erlang_recv_message", &erfd, &timeout)) {
return NULL;
}
if (erfd < 0) {
goto clear;
}
erpoll.fd = erfd;
erpoll.events = POLLIN;
cycle:
memset(&emsg, 0, sizeof(ErlMessage));
UWSGI_SET_BLOCKING;
if (timeout > 0) {
eret = poll(&erpoll, 1, timeout * 1000);
if (eret < 0) {
uwsgi_error("poll()");
goto clear;
}
else if (eret == 0) {
goto clear;
}
}
if (erl_receive_msg(erfd, erlang_buffer, 8192, &emsg) == ERL_MSG) {
if (emsg.type == ERL_TICK) {
goto cycle;
}
if (emsg.msg) {
pyer = eterm_to_py(emsg.msg);
}
if (emsg.msg) {
erl_free_compound(emsg.msg);
}
if (emsg.to) {
erl_free_compound(emsg.to);
}
if (emsg.from) {
erl_free_compound(emsg.from);
}
if (!pyer) {
goto clear;
}
UWSGI_UNSET_BLOCKING;
return pyer;
}
clear:
UWSGI_UNSET_BLOCKING;
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_send_message(PyObject * self, PyObject * args) {
ETERM *pymessage;
ETERM *pid;
int erfd;
PyObject *ermessage, *erdest, *zero;
int er_number, er_serial, er_creation;
char *er_node;
if (!PyArg_ParseTuple(args, "iOO|i:erlang_send_message", &erfd, &erdest, &ermessage)) {
return NULL;
}
if (erfd < 0) {
goto clear;
}
if (!PyString_Check(erdest) && !PyDict_Check(erdest)) {
goto clear;
}
pymessage = py_to_eterm(ermessage);
if (!pymessage) {
goto clear;
}
if (PyString_Check(erdest)) {
if (!erl_reg_send(erfd, PyString_AsString(erdest), pymessage)) {
erl_err_msg("erl_reg_send()");
goto clear2;
}
}
else if (PyDict_Check(erdest)) {
zero = PyDict_GetItemString(erdest, "node");
if (!zero) {
goto clear2;
}
if (!PyString_Check(zero)) {
goto clear2;
}
er_node = PyString_AsString(zero);
zero = PyDict_GetItemString(erdest, "number");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_number = PyInt_AsLong(zero);
zero = PyDict_GetItemString(erdest, "serial");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_serial = PyInt_AsLong(zero);
zero = PyDict_GetItemString(erdest, "creation");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_creation = PyInt_AsLong(zero);
pid = erl_mk_pid((const char *) er_node, er_number, er_serial, er_creation);
if (!pid) {
goto clear2;
}
if (!erl_send(erfd, pid, pymessage)) {
erl_err_msg("erl_send()");
erl_free_term(pid);
goto clear2;
}
erl_free_term(pid);
}
else {
goto clear;
}
erl_free_compound(pymessage);
Py_INCREF(Py_True);
return Py_True;
clear2:
erl_free_compound(pymessage);
clear:
PyErr_Print();
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_rpc(PyObject * self, PyObject * args) {
int fd, timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
char *emod, *efun;
PyObject *eargs, *pyer = NULL;
ETERM *pyargs, *rex;
ErlMessage emsg;
int eret;
if (!PyArg_ParseTuple(args, "issO|i:erlang_rpc", &fd, &emod, &efun, &eargs, &timeout)) {
return NULL;
}
if (fd < 0) {
goto clear;
}
pyargs = py_to_eterm(eargs);
if (!pyargs) {
goto clear;
}
if (erl_rpc_to(fd, emod, efun, pyargs)) {
erl_err_msg("erl_rpc_to()");
goto clear2;
}
cycle:
memset(&emsg, 0, sizeof(ErlMessage));
UWSGI_SET_BLOCKING;
eret = erl_rpc_from(fd, timeout * 1000, &emsg);
if (eret == ERL_TICK) {
goto cycle;
}
else if (eret == ERL_MSG) {
if (emsg.msg) {
if (ERL_IS_TUPLE(emsg.msg)) {
rex = erl_element(1, emsg.msg);
if (!rex) {
goto clear2;
}
if (!strncmp("rex", ERL_ATOM_PTR(rex), ERL_ATOM_SIZE(rex))) {
erl_free_term(rex);
rex = erl_element(2, emsg.msg);
if (!rex) {
goto clear2;
}
pyer = eterm_to_py(rex);
erl_free_term(rex);
}
else {
erl_free_term(rex);
}
}
}
if (emsg.msg) {
erl_free_compound(emsg.msg);
}
if (emsg.to) {
erl_free_compound(emsg.to);
}
if (emsg.from) {
erl_free_compound(emsg.from);
}
if (!pyer) {
goto clear2;
}
erl_free_compound(pyargs);
UWSGI_UNSET_BLOCKING;
return pyer;
}
else {
erl_err_msg("erl_rpc_from()");
}
clear2:
UWSGI_UNSET_BLOCKING;
erl_free_compound(pyargs);
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_close(PyObject * self, PyObject * args) {
int fd;
if (!PyArg_ParseTuple(args, "i:erlang_close", &fd)) {
return NULL;
}
if (fd >= 0) {
erl_close_connection(fd);
}
Py_INCREF(Py_True);
return Py_True;
}
static PyMethodDef uwsgi_erlang_methods[] = {
{"erlang_connect", py_erlang_connect, METH_VARARGS, ""},
{"erlang_send_message", py_erlang_send_message, METH_VARARGS, ""},
{"erlang_recv_message", py_erlang_recv_message, METH_VARARGS, ""},
{"erlang_rpc", py_erlang_rpc, METH_VARARGS, ""},
{"erlang_close", py_erlang_close, METH_VARARGS, ""},
{NULL, NULL},
};
int init_erlang(char *nodename, char *cookie) {
struct sockaddr_in e_addr;
char *ip;
char *node;
int efd;
int rlen;
char *cookiefile;
char *cookiehome;
char cookievalue[128];
int cookiefd;
PyMethodDef *uwsgi_function;
ip = strchr(nodename, '@');
if (ip == NULL) {
uwsgi_log( "*** invalid erlang node name ***\n");
return -1;
}
if (cookie == NULL) {
// get the cookie from the home
cookiehome = getenv("HOME");
if (!cookiehome) {
uwsgi_log( "unable to get erlang cookie from your home.\n");
return -1;
}
cookiefile = malloc(strlen(cookiehome) + 1 + strlen(".erlang.cookie") + 1);
if (!cookiefile) {
uwsgi_error("malloc()");
}
cookiefile[0] = 0;
strcat(cookiefile, cookiehome);
strcat(cookiefile, "/.erlang.cookie");
cookiefd = open(cookiefile, O_RDONLY);
if (cookiefd < 0) {
uwsgi_error("open()");
free(cookiefile);
return -1;
}
memset(cookievalue, 0, 128);
if (read(cookiefd, cookievalue, 127) < 1) {
uwsgi_log( "invalid cookie found in %s\n", cookiefile);
close(cookiefd);
free(cookiefile);
return -1;
}
cookie = cookievalue;
close(cookiefd);
free(cookiefile);
}
node = malloc((ip - nodename) + 1);
if (node == NULL) {
uwsgi_error("malloc()");
return -1;
}
memset(node, 0, (ip - nodename) + 1);
memcpy(node, nodename, ip - nodename);
erl_init(NULL, 0);
if (erl_connect_xinit(ip + 1, node, nodename, NULL, cookie, 0) == -1) {
uwsgi_log( "*** unable to initialize erlang c-node ***\n");
return -1;
}
efd = socket(AF_INET, SOCK_STREAM, 0);
if (efd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&e_addr, 0, sizeof(struct sockaddr_in));
e_addr.sin_family = AF_INET;
e_addr.sin_addr.s_addr = inet_addr(ip + 1);
rlen = 1;
if (setsockopt(efd, SOL_SOCKET, SO_REUSEADDR, &rlen, sizeof(rlen))) {
uwsgi_error("setsockopt()");
close(efd);
return -1;
}
if (bind(efd, (struct sockaddr *) &e_addr, sizeof(struct sockaddr_in)) < 0) {
uwsgi_error("bind()");
close(efd);
return -1;
}
rlen = sizeof(struct sockaddr_in);
if (getsockname(efd, (struct sockaddr *) &e_addr, (socklen_t *) & rlen)) {
uwsgi_error("getsockname()");
close(efd);
return -1;
}
if (listen(efd, uwsgi.listen_queue)) {
uwsgi_error("listen()");
close(efd);
return -1;
}
if (erl_publish(ntohs(e_addr.sin_port)) < 0) {
uwsgi_log( "*** unable to subscribe with EPMD ***\n");
close(efd);
return -1;
}
uwsgi_log( "Erlang C-Node initialized on port %d you can access it with name %s\n", ntohs(e_addr.sin_port), nodename);
for (uwsgi_function = uwsgi_erlang_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(uwsgi.embedded_dict, uwsgi_function->ml_name, func);
Py_DECREF(func);
}
return efd;
}
ETERM *py_to_eterm(PyObject * pobj) {
int i;
int count;
PyObject *pobj2;
ETERM *eobj = NULL;
ETERM *eobj2 = NULL;
ETERM **eobj3;
if (pobj == NULL) {
return erl_mk_empty_list();
}
if (PyString_Check(pobj)) {
eobj = erl_mk_atom(PyString_AsString(pobj));
}
else if (PyInt_Check(pobj)) {
eobj = erl_mk_int(PyInt_AsLong(pobj));
}
else if (PyList_Check(pobj)) {
eobj = erl_mk_empty_list();
for (i = PyList_Size(pobj) - 1; i >= 0; i--) {
pobj2 = PyList_GetItem(pobj, i);
eobj2 = py_to_eterm(pobj2);
eobj = erl_cons(eobj2, eobj);
}
}
else if (PyDict_Check(pobj)) {
// a pid
char *er_node;
int er_number, er_serial, er_creation;
pobj2 = PyDict_GetItemString(pobj, "node");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyString_Check(pobj2)) {
goto clear;
}
er_node = PyString_AsString(pobj2);
pobj2 = PyDict_GetItemString(pobj, "number");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_number = PyInt_AsLong(pobj2);
pobj2 = PyDict_GetItemString(pobj, "serial");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_serial = PyInt_AsLong(pobj2);
pobj2 = PyDict_GetItemString(pobj, "creation");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_creation = PyInt_AsLong(pobj2);
eobj = erl_mk_pid(er_node, er_number, er_serial, er_creation);
}
else if (PyTuple_Check(pobj)) {
count = PyTuple_Size(pobj);
eobj3 = malloc(sizeof(ETERM *) * count);
for (i = 0; i < count; i++) {
pobj2 = PyTuple_GetItem(pobj, i);
if (!pobj2) {
break;
}
eobj3[i] = py_to_eterm(pobj2);
}
eobj = erl_mk_tuple(eobj3, count);
free(eobj3);
}
else {
uwsgi_log( "UNMANAGED PYTHON TYPE: %s\n", pobj->ob_type->tp_name);
}
clear:
if (eobj == NULL) {
return erl_mk_empty_list();
}
return eobj;
}
PyObject *eterm_to_py(ETERM * obj) {
int i;
int count;
ETERM *obj2;
PyObject *eobj = NULL;
if (obj == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
switch (ERL_TYPE(obj)) {
case ERL_CONS:
case ERL_NIL:
count = erl_length(obj);
eobj = PyList_New(0);
for (i = 0; i < count; i++) {
obj2 = erl_hd(obj);
PyList_Append(eobj, eterm_to_py(obj2));
obj = erl_tl(obj);
}
break;
case ERL_TUPLE:
eobj = PyTuple_New(erl_size(obj));
for (i = 1; i <= erl_size(obj); i++) {
obj2 = erl_element(i, obj);
PyTuple_SetItem(eobj, i - 1, eterm_to_py(obj2));
}
break;
case ERL_ATOM:
eobj = PyString_FromStringAndSize(ERL_ATOM_PTR(obj), ERL_ATOM_SIZE(obj));
break;
case ERL_INTEGER:
eobj = PyInt_FromLong(ERL_INT_VALUE(obj));
break;
case ERL_BINARY:
uwsgi_log( "FOUND A BINARY %.*s\n", ERL_BIN_SIZE(obj), ERL_BIN_PTR(obj));
break;
case ERL_PID:
eobj = PyDict_New();
if (PyDict_SetItemString(eobj, "node", PyString_FromString(ERL_PID_NODE(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "number", PyInt_FromLong(ERL_PID_NUMBER(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "serial", PyInt_FromLong(ERL_PID_SERIAL(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "creation", PyInt_FromLong(ERL_PID_CREATION(obj)))) {
PyErr_Print();
break;
}
default:
uwsgi_log( "UNMANAGED ETERM TYPE: %d\n", ERL_TYPE(obj));
break;
}
if (eobj == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return eobj;
}
void erlang_loop(struct wsgi_request *wsgi_req) {
ErlConnect econn;
ErlMessage em;
ETERM *eresponse;
PyObject *callable = PyDict_GetItemString(uwsgi.embedded_dict, "erlang_func");
if (!callable) {
PyErr_Print();
uwsgi_log( "- you have not defined a uwsgi.erlang_func callable, Erlang message manager will be disabled until you define it -\n");
}
PyObject *pargs = PyTuple_New(1);
if (!pargs) {
PyErr_Print();
uwsgi_log( "- error preparing arg tuple for uwsgi.erlang_func callable, Erlang message manager will be disabled -\n");
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
UWSGI_CLEAR_STATUS;
wsgi_req->poll.fd = erl_accept(uwsgi.erlangfd, &econn);
if (wsgi_req->poll.fd >= 0) {
UWSGI_SET_ERLANGING;
for (;;) {
if (erl_receive_msg(wsgi_req->poll.fd, (unsigned char *) wsgi_req->buffer, uwsgi.buffer_size, &em) == ERL_MSG) {
if (em.type == ERL_TICK)
continue;
if (!callable) {
callable = PyDict_GetItemString(uwsgi.embedded_dict, "erlang_func");
}
if (!callable) {
uwsgi_log( "- you still have not defined a uwsgi.erlang_func callable, Erlang message rejected -\n");
}
PyObject *zero = eterm_to_py(em.msg);
if (em.msg) {
erl_free_compound(em.msg);
}
if (em.to) {
erl_free_compound(em.to);
}
if (!zero) {
PyErr_Print();
continue;
}
if (PyTuple_SetItem(pargs, 0, zero)) {
PyErr_Print();
continue;
}
PyObject *erlang_result = PyEval_CallObject(callable, pargs);
//Py_DECREF(zero);
if (erlang_result) {
eresponse = py_to_eterm(erlang_result);
if (eresponse) {
erl_send(wsgi_req->poll.fd, em.from, eresponse);
erl_free_compound(eresponse);
}
Py_DECREF(erlang_result);
}
if (em.from) {
erl_free_compound(em.from);
}
uwsgi.workers[0].requests++;
uwsgi.workers[uwsgi.mywid].requests++;
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
erlang_log();
}
else {
break;
}
}
erl_close_connection(wsgi_req->poll.fd);
UWSGI_UNSET_ERLANGING;
}
}
}
static void erlang_log() {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
get_memusage();
}
else {
uwsgi.workers[uwsgi.mywid].rss_size = 0;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
}
uwsgi_log( "[Erlang worker %d pid %d] request %llu done {rss: %llu vsz: %llu}\n", uwsgi.mywid, uwsgi.mypid, uwsgi.workers[uwsgi.mywid].requests, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].vsz_size);
}
#else
#warning "*** Erlang support is disabled ***"
#endif
+38
View File
@@ -0,0 +1,38 @@
import uwsgi
import time
import rrdtool
# rrdtool create test.rrd --start 1270879004 -s 10 DS:requests:COUNTER:300:U:U RRA:AVERAGE:0.5:3:105120
s_freq = 10
# this is a cron emulator done with the Spooler :)
def rrdtool_updater(env):
uwsgi.set_spooler_frequency(s_freq)
rrdtool.update('../test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.send_to_spooler({})
uwsgi.spooler = rrdtool_updater
def hello_world(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain')])
yield 'Hello world !'
def graph(env, start_response):
start_response('200 Ok', [('Content-type', 'image/png')])
now = int(time.time())
graph_range = (3600*24)
rrdtool.graph('uwsgi_graph.png', '--start', str(now - graph_range), '--end', str(now), 'DEF:urequests=test.rrd:requests:AVERAGE', 'LINE2:urequests#00FF00')
fd = open('uwsgi_graph.png', 'r')
# send file to browser
return env['wsgi.file_wrapper'](fd, 4096)
# start the simil-cron
uwsgi.send_to_spooler({})
uwsgi.applications = {'/': hello_world, '/graph':graph}
+104 -64
View File
@@ -35,6 +35,23 @@
#define data_uwsgi data_fastcgi
#define data_uwsgi_init data_fastcgi_init
#ifdef __linux__
#include <endian.h>
#elif __sun__
#elif __apple__
#include <libkern/OSByteOrder.h>
#else
#include <machine/endian.h>
#endif
#ifdef __BIG_ENDIAN__
static uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
#endif
/**
*
* the uwsgi module is based on the proxy module
@@ -49,23 +66,15 @@ typedef struct __attribute__((packed)) {
uint8_t modifier2;
} uwsgi_header ;
typedef enum {
UWSGI_BALANCE_UNSET,
UWSGI_BALANCE_FAIR,
} uwsgi_balance_t;
typedef struct {
array *extensions;
unsigned short debug;
uwsgi_balance_t balance;
} plugin_config;
typedef struct {
PLUGIN_DATA;
buffer *parse_response;
buffer *balance_buf;
plugin_config **config_storage;
@@ -121,6 +130,7 @@ static handler_ctx * handler_ctx_init() {
hctx->fd = -1;
hctx->fde_ndx = -1;
return hctx;
}
@@ -138,7 +148,6 @@ INIT_FUNC(mod_uwsgi_init) {
p = calloc(1, sizeof(*p));
p->parse_response = buffer_init();
p->balance_buf = buffer_init();
return p;
}
@@ -150,7 +159,6 @@ FREE_FUNC(mod_uwsgi_free) {
UNUSED(srv);
buffer_free(p->parse_response);
buffer_free(p->balance_buf);
if (p->config_storage) {
size_t i;
@@ -180,7 +188,6 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
config_values_t cv[] = {
{ "uwsgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
{ "uwsgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
{ "uwsgi.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
@@ -196,9 +203,7 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
cv[0].destination = s->extensions;
cv[1].destination = &(s->debug);
cv[2].destination = p->balance_buf;
buffer_reset(p->balance_buf);
p->config_storage[i] = s;
ca = ((data_config *)srv->config_context->data[i])->value;
@@ -207,16 +212,6 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
return HANDLER_ERROR;
}
if (buffer_is_empty(p->balance_buf)) {
s->balance = UWSGI_BALANCE_FAIR;
} else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
s->balance = UWSGI_BALANCE_FAIR;
} else {
log_error_write(srv, __FILE__, __LINE__, "s",
"uwsgi.balance has to be fair");
return HANDLER_ERROR;
}
if (NULL != (du = array_get_element(ca, "uwsgi.server"))) {
size_t j;
data_array *da = (data_array *)du;
@@ -276,7 +271,7 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
df = data_uwsgi_init();
df->port = 80;
df->port = 3031;
buffer_copy_string_buffer(df->key, da_host->key);
@@ -396,12 +391,28 @@ static int uwsgi_establish_connection(server *srv, handler_ctx *hctx) {
return 0;
}
static void uwsgi_add_var(buffer *b, char * key, uint16_t keylen, char *val, uint16_t vallen) {
#ifdef __BIG_ENDIAN__
uint16_t uwlen ;
uwlen = uwsgi_swap16(keylen);
buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, key, keylen);
uwlen = uwsgi_swap16(vallen);
buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, val, vallen);
#else
buffer_append_memory(b, (char *) &keylen, 2); buffer_append_memory(b, key, keylen);
buffer_append_memory(b, (char *) &vallen, 2); buffer_append_memory(b, val, vallen);
#endif
}
static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
size_t i;
char buf[32];
uwsgi_header *uh ;
uint16_t uwsgi_strsize;
const char *s;
#ifdef HAVE_IPV6
char b2[INET6_ADDRSTRLEN + 1];
@@ -416,36 +427,28 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
b = chunkqueue_get_append_buffer(hctx->wb);
log_error_write(srv, __FILE__, __LINE__, "s", "starting uwsgi request...");
/* make space for uwsgi header */
buffer_append_memory(b, "\0\0\0\0", 4);
log_error_write(srv, __FILE__, __LINE__, "s", "space done...");
/* set WSGI vars */
s = get_http_method_name(con->request.http_method);
uwsgi_strsize = 14; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REQUEST_METHOD", uwsgi_strsize);
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_add_var(b, "REQUEST_METHOD", 14, (char *) s, strlen(s));
uwsgi_strsize = 12; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "QUERY_STRING", uwsgi_strsize);
if (!buffer_is_empty(con->uri.query)) {
uwsgi_strsize = con->uri.query->used; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, con->uri.query->ptr, uwsgi_strsize);
uwsgi_add_var(b, "QUERY_STRING", 12, con->uri.query->ptr, con->uri.query->used-1);
} else {
uwsgi_strsize = 0; buffer_append_memory(b, &uwsgi_strsize, 2);
uwsgi_add_var(b, "QUERY_STRING", 12, "", 0);
}
s = get_http_version_name(con->request.http_version);
uwsgi_strsize = 15; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "SERVER_PROTOCOL", uwsgi_strsize);
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_add_var(b, "SERVER_PROTOCOL", 15, (char *) s, strlen(s));
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "SERVER_NAME", uwsgi_strsize);
if (con->server_name->used) {
size_t len = con->server_name->used - 1;
char *colon = strchr(con->server_name->ptr, ':');
if (colon) len = colon - con->server_name->ptr;
uwsgi_strsize = len ;
uwsgi_add_var(b, "SERVER_NAME", 11, con->server_name->ptr, len);
} else {
#ifdef HAVE_IPV6
@@ -457,11 +460,9 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
#else
s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
#endif
uwsgi_strsize = strlen(s);
uwsgi_add_var(b, "SERVER_NAME", 11, (char *)s, strlen(s));
}
buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "SERVER_PORT", uwsgi_strsize);
LI_ltostr(buf,
#ifdef HAVE_IPV6
ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
@@ -470,12 +471,9 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
#endif
);
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_add_var(b, "SERVER_PORT", 11, buf, strlen(buf));
uwsgi_add_var(b, "REQUEST_URI", 11, con->request.orig_uri->ptr, con->request.orig_uri->used-1);
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REQUEST_URI", uwsgi_strsize);
uwsgi_strsize = con->request.orig_uri->used; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, con->request.orig_uri->ptr, uwsgi_strsize);
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REMOTE_PORT", uwsgi_strsize);
LI_ltostr(buf,
#ifdef HAVE_IPV6
ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
@@ -483,23 +481,75 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
ntohs(con->dst_addr.ipv4.sin_port)
#endif
);
uwsgi_add_var(b, "REMOTE_PORT", 11, buf, strlen(buf));
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REMOTE_ADDR", uwsgi_strsize);
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_add_var(b, "REMOTE_ADDR", 11, (char *)s, strlen(s));
if (hctx->path_info_offset > 1) {
uwsgi_add_var(b, "SCRIPT_NAME", 11, con->uri.path->ptr, hctx->path_info_offset);
if (strlen(con->uri.path->ptr + hctx->path_info_offset) > 0) {
uwsgi_add_var(b, "PATH_INFO", 9, con->request.orig_uri->ptr + hctx->path_info_offset, strlen(con->request.orig_uri->ptr + hctx->path_info_offset));
}
else {
uwsgi_add_var(b, "PATH_INFO", 9, "/", 1);
}
}
else {
uwsgi_add_var(b, "SCRIPT_NAME", 11, "", 0) ;
uwsgi_add_var(b, "PATH_INFO", 9, con->request.orig_uri->ptr, con->request.orig_uri->used-1) ;
}
for (i = 0; i < con->request.headers->used; i++) {
data_string *ds;
ds = (data_string *)con->request.headers->data[i];
if (ds->value->used && ds->key->used) {
size_t j;
buffer_reset(srv->tmp_buf);
if (!strcasecmp(ds->key->ptr, "CONTENT-TYPE") || !strcasecmp(ds->key->ptr, "CONTENT-LENGTH")) {
buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
}
else {
buffer_prepare_append(srv->tmp_buf, ds->key->used + 7);
buffer_append_memory(srv->tmp_buf, "HTTP_", 5);
}
for (j = 0; j < ds->key->used - 1; j++) {
srv->tmp_buf->ptr[srv->tmp_buf->used++] = light_isalpha(ds->key->ptr[j]) ? ds->key->ptr[j] & ~32 : '_';
}
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
uwsgi_add_var(b, srv->tmp_buf->ptr, srv->tmp_buf->used-1, ds->value->ptr, ds->value->used-1);
}
}
for (i = 0; i < con->environment->used; i++) {
data_string *ds;
ds = (data_string *)con->environment->data[i];
if (ds->value->used && ds->key->used) {
size_t j;
buffer_reset(srv->tmp_buf);
buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
for (j = 0; j < ds->key->used - 1; j++) {
srv->tmp_buf->ptr[srv->tmp_buf->used++] = light_isalnum((unsigned char)ds->key->ptr[j]) ? toupper((unsigned char)ds->key->ptr[j]) : '_';
}
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
uwsgi_add_var(b, srv->tmp_buf->ptr, srv->tmp_buf->used-1, ds->value->ptr, ds->value->used-1);
}
}
uh = (uwsgi_header *) b->ptr ;
uh->modifier1 = 0 ;
uh->modifier1 = (uint8_t) 0 ;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16((uint16_t) b->used - 4) ;
#else
uh->pktsize = b->used - 4 ;
uh->modifier2 = 0 ;
#endif
uh->modifier2 = (uint8_t) 0 ;
log_error_write(srv, __FILE__, __LINE__, "sd", "uwsgi_header ", b->used - 4);
b->used++; /* fix size */
hctx->wb->bytes_in += b->used -1 ;
@@ -908,7 +958,6 @@ static int mod_uwsgi_patch_connection(server *srv, connection *con, plugin_data
PATCH(extensions);
PATCH(debug);
PATCH(balance);
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
@@ -926,8 +975,6 @@ static int mod_uwsgi_patch_connection(server *srv, connection *con, plugin_data
PATCH(extensions);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("uwsgi.debug"))) {
PATCH(debug);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("uwsgi.balance"))) {
PATCH(balance);
}
}
}
@@ -1097,7 +1144,6 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
static handler_t mod_uwsgi_check_extension(server *srv, connection *con, void *p_d) {
plugin_data *p = p_d;
size_t s_len;
unsigned long last_max = ULONG_MAX;
int max_usage = INT_MAX;
int ndx = -1;
size_t k;
@@ -1143,13 +1189,7 @@ static handler_t mod_uwsgi_check_extension(server *srv, connection *con, void *p
/* check extension in the form "/uwsgi_pattern" */
if (*(ext->key->ptr) == '/') {
if (strncmp(fn->ptr, ext->key->ptr, ct_len) == 0) {
if (s_len > ct_len + 1) {
char *pi_offset;
if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
path_info_offset = pi_offset - fn->ptr;
}
}
path_info_offset = ct_len ;
extension = ext;
break;
}
+177
View File
@@ -0,0 +1,177 @@
#include "uwsgi.h"
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
#include <kvm.h>
#include <sys/user.h>
#elif defined(__sun__)
/* Terrible Hack !!! */
#ifndef _LP64
#undef _FILE_OFFSET_BITS
#endif
#include <procfs.h>
#define _FILE_OFFSET_BITS 64
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#endif
extern struct uwsgi_server uwsgi;
void log_request(struct wsgi_request *wsgi_req) {
// optimize this (please)
char *time_request;
time_t microseconds, microseconds2;
int rlen;
int app_req = -1;
char *msg2 = " ";
char *via = msg2;
char mempkt[4096];
char logpkt[4096];
struct iovec logvec[2] ;
int logvecpos = 0 ;
#ifdef UWSGI_SENDFILE
char *msg1 = " via sendfile() ";
struct uwsgi_app *wi;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi.wsgi_apps[wsgi_req->app_id];
if (wi->requests > 0) {
app_req = wi->requests;
}
}
via = msg2;
if (wsgi_req->sendfile_fd > -1) {
via = msg1;
}
#endif
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
#ifndef UNBIT
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ",
uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
#else
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ",
uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
#endif
logvec[logvecpos].iov_base = mempkt ;
logvec[logvecpos].iov_len = rlen ;
logvecpos++;
}
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld msecs%s(%.*s %d) %d headers in %d bytes (%d async switches on async core %d)\n",
uwsgi.mypid,
wsgi_req->app_id,
app_req,
uwsgi.workers[0].requests,
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
wsgi_req->remote_user_len, wsgi_req->remote_user,
wsgi_req->var_cnt,
wsgi_req->uh.pktsize,
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(uint64_t) wsgi_req->response_size,
(long int) (microseconds - microseconds2) / 1000,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
wsgi_req->status,
wsgi_req->header_cnt,
wsgi_req->headers_size,
wsgi_req->async_switches, wsgi_req->async_id);
logvec[logvecpos].iov_base = logpkt ;
logvec[logvecpos].iov_len = rlen ;
// do not check for errors
rlen = writev(2, logvec, logvecpos+1);
}
void get_memusage() {
#ifdef UNBIT
uwsgi.workers[uwsgi.mywid].vsz_size = 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", &uwsgi.workers[uwsgi.mywid].vsz_size, &uwsgi.workers[uwsgi.mywid].rss_size);
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;
#elif defined (__sun__)
psinfo_t info;
int procfd ;
procfd = open("/proc/self/psinfo", O_RDONLY);
if (procfd >= 0) {
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024 ;
uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024 ;
}
close(procfd);
}
#elif defined( __APPLE__)
/* darwin documentation says that the value are in pages, but they are bytes !!! */
struct task_basic_info t_info;
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
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;
}
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
kvm_t *kv;
int cnt;
kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
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;
}
#elif defined(__NetBSD__) || defined(__OpenBSD__)
struct kinfo_proc2 *kproc2;
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
if (kproc2 && cnt > 0) {
#ifdef __OpenBSD__
uwsgi.workers[uwsgi.mywid].vsz_size = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
#else
uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
#endif
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
}
#endif
kvm_close(kv);
}
#endif
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

+7
View File
@@ -0,0 +1,7 @@
import uwsgi
import struct
import sys
print uwsgi.send_uwsgi_message(sys.argv[1], int(sys.argv[2]), 10, int(sys.argv[3]), struct.pack("i", int(sys.argv[4])))
+51
View File
@@ -0,0 +1,51 @@
#include "uwsgi.h"
void nagios(struct uwsgi_server *uwsgi) {
struct pollfd nagios_poll;
// connect and send
if (uwsgi->socket_name == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
char *tcp_port = strchr(uwsgi->socket_name, ':');
if (tcp_port == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port[0] = 0;
nagios_poll.fd = connect_to_tcp(uwsgi->socket_name, atoi(tcp_port + 1), uwsgi->shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (nagios_poll.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) {
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)) {
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);
exit(1);
}
else {
fprintf(stdout, "UWSGI OK: armed and ready\n");
exit(0);
}
}
// never here
fprintf(stdout, "UWSGI UNKNOWN: probably you hit a bug of uWSGI !!!\n");
exit(3);
}
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
#include "../../uwsgi.h"
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
fprintf(stderr,"i am the example plugin initialization function with arg: %s\n", args);
return 0;
}
int uwsgi_request(struct uwsgi_server *uwsgi, 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));
return 0;
}
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
fprintf(stderr,"i am the example plugin after request function\n");
}
+3
View File
@@ -0,0 +1,3 @@
NAME='example'
CFLAGS = ''
LDFLAGS = ''
+214
View File
@@ -0,0 +1,214 @@
#include <uwsgi.h>
/* gcc -fPIC -shared -o lua_plugin.so `python2.5-config --cflags` -I /usr/include/lua5.1 -llua5.1 lua_plugin.c */
#include <lua.h>
#include <lualib.h>
static struct uwsgi_lua {
struct lua_State *L ;
struct uwsgi_server *uwsgi;
} ulua;
static void *uwsgi_lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
if(nsize == 0) {
free(ptr);
return NULL;
}
return realloc(ptr, nsize);
}
static const char *uwsgi_read_lua(lua_State *L, void *data, size_t *size) {
int fd = *(int *)data;
static char buf[4096];
*size = read(fd, buf, 4096);
if (size == 0) {
return NULL;
}
return buf;
}
static int uwsgi_lua_input(lua_State *L) {
int n = lua_gettop(L);
static char *buf = "" ;
fprintf(stderr,"richiesti %d bytes\n", n);
//sum = read(ulua.uwsgi->poll.fd,);
lua_pushlstring(L, buf, 0);
return 1;
}
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
int fd, i;
fprintf(stderr,"Initializing Lua environment...\n");
ulua.L = lua_newstate(uwsgi_lua_alloc, NULL);
luaL_openlibs(ulua.L);
fd = open(args, O_RDONLY) ;
if (fd < 0) {
perror("open()");
return -1 ;
}
i = lua_load(ulua.L, uwsgi_read_lua, &fd, "uwsgi");
fprintf(stderr,"lua_load: %d\n" ,i);
// use a pcall
lua_call(ulua.L, 0, 1);
fprintf(stderr,"%s\n", lua_typename(ulua.L, lua_type(ulua.L, -1)));
// ok the lua engine is ready
return 0 ;
}
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int i;
const char *http ;
size_t slen ;
char *ptrbuf;
/* Standard WSAPI request */
if (!wsgi_req->uh.pktsize) {
fprintf (stderr, "Invalid WSAPI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
fprintf(stderr,"Invalid WSAPI request. skip.\n");
return -1;
}
// put function in the stack
lua_pushvalue(ulua.L, -1);
lua_getfield(ulua.L, -1, "run");
// put cgi vars in the stack
lua_newtable(ulua.L);
lua_pushstring(ulua.L, "");
lua_setfield(ulua.L, -2, "CONTENT_TYPE");
for(i=0;i<wsgi_req->var_cnt;i++) {
lua_pushlstring(ulua.L, (char *)wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
// transform it in a valid c string TODO this is ugly
ptrbuf = wsgi_req->hvec[i].iov_base+wsgi_req->hvec[i].iov_len ;
*ptrbuf = 0 ;
lua_setfield(ulua.L, -2, (char *)wsgi_req->hvec[i].iov_base);
i++;
}
// put "input" table
lua_newtable(ulua.L);
lua_pushcfunction(ulua.L, uwsgi_lua_input);
lua_setfield(ulua.L, -2, "read");
lua_setfield(ulua.L, -2, "input");
// call function
i = lua_pcall(ulua.L, 1, 3, 0);
if (i != 0) {
fprintf(stderr,"%s\n", lua_tostring(ulua.L, -1));
lua_pop(ulua.L, 1);
return -1 ;
}
fprintf(stderr,"%d %s %s %s\n",i,lua_typename(ulua.L, lua_type(ulua.L, -3)), lua_typename(ulua.L, lua_type(ulua.L, -2)) , lua_typename(ulua.L, lua_type(ulua.L, -1)));
// send status
if (lua_type(ulua.L, -3) == LUA_TSTRING || lua_type(ulua.L, -3) == LUA_TNUMBER) {
http = lua_tolstring(ulua.L, -3, &slen);
if (write(wsgi_req->poll.fd, "HTTP/1.1 ", 9) != 9) {
perror("write()");
return -1 ;
}
if (write(wsgi_req->poll.fd, http, slen) != slen) {
perror("write()");
return -1 ;
}
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
return -1 ;
}
}
// send headers
lua_pushnil(ulua.L);
while(lua_next(ulua.L, -3) != 0) {
http = lua_tolstring(ulua.L, -2, &slen);
if (write(wsgi_req->poll.fd, http, slen) != slen) {
perror("write()");
return -1 ;
}
if (write(wsgi_req->poll.fd, ": ", 2) != 2) {
perror("write()");
return -1 ;
}
http = lua_tolstring(ulua.L, -1, &slen);
if (write(wsgi_req->poll.fd, http, slen) != slen) {
perror("write()");
return -1 ;
}
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
return -1 ;
}
lua_pop(ulua.L, 1);
}
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
return -1 ;
}
// send body with coroutine
lua_pushvalue(ulua.L, -1);
while ( (i = lua_pcall(ulua.L, 0, 1, 0)) == 0) {
if (lua_type(ulua.L, -1) == LUA_TSTRING) {
http = lua_tolstring(ulua.L, -1, &slen);
if (write(wsgi_req->poll.fd, http, slen) != slen) {
perror("write()");
return -1 ;
}
//fprintf(stderr,"%.*s\n", slen, http);
}
lua_pop(ulua.L, 1);
lua_pushvalue(ulua.L, -1);
}
lua_pop(ulua.L, 4);
return 0;
}
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
+5
View File
@@ -0,0 +1,5 @@
import os,sys
NAME='lua'
CFLAGS = '-I /usr/include/lua5.1'
LDFLAGS = '-llua5.1'
+375
View File
@@ -0,0 +1,375 @@
#include <uwsgi.h>
#include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
static SV *psgi_func ;
/* statistically ordered */
static struct http_status_codes hsc[] = {
{"200", "OK"},
{"302", "Found"},
{"404", "Not Found"},
{"500", "Internal Server Error"},
{"301", "Moved Permanently"},
{"304", "Not Modified"},
{"303", "See Other"},
{"403", "Forbidden"},
{"307", "Temporary Redirect"},
{"401", "Unauthorized"},
{"400", "Bad Request"},
{"405", "Method Not Allowed"},
{"408", "Request Timeout"},
{"100", "Continue"},
{"101", "Switching Protocols"},
{"201", "Created"},
{"202", "Accepted"},
{"203", "Non-Authoritative Information"},
{"204", "No Content"},
{"205", "Reset Content"},
{"206", "Partial Content"},
{"300", "Multiple Choices"},
{"305", "Use Proxy"},
{"402", "Payment Required"},
{"406", "Not Acceptable"},
{"407", "Proxy Authentication Required"},
{"409", "Conflict"},
{"410", "Gone"},
{"411", "Length Required"},
{"412", "Precondition Failed"},
{"413", "Request Entity Too Large"},
{"414", "Request-URI Too Long"},
{"415", "Unsupported Media Type"},
{"416", "Requested Range Not Satisfiable"},
{"417", "Expectation Failed"},
{"501", "Not Implemented"},
{"502", "Bad Gateway"},
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{ "", NULL },
};
/* 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);
}
/* end of automagically generated part */
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
char *pargs[2] ;
char *psgibuffer ;
int fd ;
struct stat stat_psgi;
struct http_status_codes *http_sc ;
char *embedding[] = { "", "-e", "0" };
fprintf(stderr,"initializing Perl environment: %s\n", args);
my_perl = perl_alloc();
if (!my_perl) {
fprintf(stderr,"unable to allocate perl interpreter\n");
return -1;
}
pargs[0] = "" ;
pargs[1] = args ;
perl_construct(my_perl);
// filling http status codes
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = strlen(http_sc->message);
}
perl_parse(my_perl, xs_init, 3, embedding, NULL);
perl_eval_pv("use IO::Handle;", 0);
fd = open(args, O_RDONLY);
if (fd < 0) {
perror("open()");
goto clear ;
}
if (fstat(fd, &stat_psgi)) {
perror("fstat()");
close(fd);
goto clear;
}
psgibuffer = malloc(stat_psgi.st_size);
if (!psgibuffer) {
perror("malloc()");
close(fd);
goto clear;
}
if (read(fd, psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) {
perror("read()");
close(fd);
free(psgibuffer);
goto clear;
}
psgibuffer[stat_psgi.st_size] = 0 ;
psgi_func = perl_eval_pv(psgibuffer, 0);
if (!psgi_func) {
fprintf(stderr,"unable to find PSGI function entry point.\n");
close(fd);
free(psgibuffer);
goto clear;
}
free(psgibuffer);
close(fd);
return 0;
clear:
perl_destruct(my_perl);
perl_free(my_perl);
return -1;
}
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
HV *env ;
SV **item ;
AV *response, *headers, *body ;
SV **status_code, **hitem, *io_new, *io_err, *io, *chunk;
char *chitem ;
STRLEN hlen ;
struct http_status_codes *http_sc;
int i,vi, base ;
/* Standard PSGI request */
if (!wsgi_req->uh.pktsize) {
fprintf (stderr, "Invalid PSGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
fprintf(stderr,"Invalid PSGI request. skip.\n");
return -1;
}
dSP;
ENTER;
SAVETMPS;
env = (HV*)sv_2mortal((SV*)newHV());
// 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);
}
else {
item = hv_store(env, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, newSVpv("", 0), 0);
}
i++;
}
item = hv_store(env, "psgi.url_scheme", 15, newSVpv("http", 4), 0);
PUSHMARK(SP);
XPUSHs( sv_2mortal( newSVpv( "IO::Handle", 10 )));
PUTBACK;
perl_call_method( "new", G_SCALAR);
SPAGAIN;
io_new = newSVsv(POPs);
PUSHMARK(SP);
XPUSHs( sv_2mortal(io_new) );
XPUSHs( sv_2mortal( newSViv( wsgi_req->poll.fd)));
XPUSHs( sv_2mortal( newSVpv( "r", 1)));
PUTBACK;
perl_call_method( "fdopen", G_SCALAR);
SPAGAIN;
item = hv_store(env, "psgi.input", 10, newSVsv(POPs), 0);
PUSHMARK(SP);
XPUSHs( sv_2mortal( newSVpv( "IO::Handle", 10 )));
PUTBACK;
perl_call_method( "new", G_SCALAR);
SPAGAIN;
io_err = newSVsv(POPs);
PUSHMARK(SP);
XPUSHs( sv_2mortal(io_err) );
XPUSHs( sv_2mortal( newSViv( 2 )));
XPUSHs( sv_2mortal( newSVpv( "w", 1)));
PUTBACK;
perl_call_method( "fdopen", G_SCALAR);
SPAGAIN;
item = hv_store(env, "psgi.errors", 11, newSVsv(POPs), 0);
PUSHMARK(SP);
XPUSHs( sv_2mortal(newRV((SV *)env )) );
PUTBACK;
perl_call_sv(psgi_func, G_SCALAR);
SPAGAIN;
// dereference output
response = (AV *) SvRV( sv_2mortal(newSVsv(POPs)) ) ;
status_code = av_fetch(response, 0, 0);
wsgi_req->hvec[0].iov_base = "HTTP/1.1 ";
wsgi_req->hvec[0].iov_len = 9 ;
wsgi_req->hvec[1].iov_base = SvPV(*status_code, hlen);
wsgi_req->hvec[1].iov_len = 3 ;
wsgi_req->hvec[2].iov_base = " ";
wsgi_req->hvec[2].iov_len = 1 ;
wsgi_req->hvec[3].iov_len = 0 ;
// get the status code
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
if (!strncmp(http_sc->key, wsgi_req->hvec[1].iov_base, 3)) {
wsgi_req->hvec[3].iov_base = http_sc->message ;
wsgi_req->hvec[3].iov_len = http_sc->message_size ;
break;
}
}
if (wsgi_req->hvec[3].iov_len == 0) {
wsgi_req->hvec[3].iov_base = "Unknown" ;
wsgi_req->hvec[3].iov_len = 7;
}
wsgi_req->hvec[4].iov_base = "\r\n";
wsgi_req->hvec[4].iov_len = 2 ;
hitem = av_fetch(response, 1, 0) ;
headers = (AV *) SvRV(*hitem);
base = 5 ;
// put them in hvec
for(i=0; i<=av_len(headers); i++) {
vi = (i*2)+base ;
hitem = av_fetch(headers,i,0);
chitem = SvPV(*hitem, hlen);
wsgi_req->hvec[vi].iov_base = chitem ; wsgi_req->hvec[vi].iov_len = hlen ;
wsgi_req->hvec[vi+1].iov_base = ": " ; wsgi_req->hvec[vi+1].iov_len = 2 ;
hitem = av_fetch(headers,i+1,0);
chitem = SvPV(*hitem, hlen);
wsgi_req->hvec[vi+2].iov_base = chitem ; wsgi_req->hvec[vi+2].iov_len = hlen ;
wsgi_req->hvec[vi+3].iov_base = "\r\n" ; wsgi_req->hvec[vi+3].iov_len = 2 ;
i++;
}
vi = (i*2)+base ;
wsgi_req->hvec[vi].iov_base = "\r\n" ; wsgi_req->hvec[vi].iov_len = 2 ;
if ( (wsgi_req->response_size = writev(wsgi_req->poll.fd, wsgi_req->hvec, vi+1)) < 0) {
perror("writev()");
}
hitem = av_fetch(response, 2, 0) ;
io = *hitem;
if (SvTYPE(SvRV(io)) == SVt_PVGV) {
for(;;) {
PUSHMARK(SP);
XPUSHs(io) ;
PUTBACK;
perl_call_method("getline", G_SCALAR);
SPAGAIN;
chunk = sv_2mortal(newSVsv(POPs));
chitem = SvPV(chunk, hlen);
if (hlen <= 0) {
break;
}
wsgi_req->response_size += write(wsgi_req->poll.fd, chitem, hlen);
}
}
else if (SvTYPE(SvRV(io)) == SVt_PVAV) {
body = (AV *) SvRV(io);
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);
}
}
FREETMPS;
LEAVE;
return 0;
}
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
+5
View File
@@ -0,0 +1,5 @@
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()
+417 -163
View File
@@ -2,208 +2,462 @@
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
int fd ;
struct sockaddr_in udp_addr;
char *udp_port ;
ssize_t ret;
char udpbuff[1024];
if (message_size + 4 > 1024)
return -1;
udp_port = strchr(host, ':');
if (udp_port == NULL) {
return -1 ;
}
udp_port[0] = 0 ;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("socket()");
return -1 ;
}
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
udp_addr.sin_family = AF_INET;
udp_addr.sin_port = htons(atoi(udp_port));
udp_addr.sin_addr.s_addr = inet_addr(host);
udpbuff[0] = modifier1 ;
#ifdef __BIG_ENDIAN__
message_size = uwsgi_swap16(message_size);
#endif
memcpy(udpbuff+1, &message_size, 2);
udpbuff[3] = 0 ;
#ifdef __BIG_ENDIAN__
message_size = uwsgi_swap16(message_size);
#endif
memcpy(udpbuff+4, message, message_size);
ret = sendto(fd, udpbuff, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
if (ret < 0) {
uwsgi_error("sendto()");
}
close(fd);
return ret;
}
#endif
int uwsgi_enqueue_message(char *host, int port, uint8_t modifier1, uint8_t modifier2, char *message, int size, int timeout) {
int uwsgi_fd;
struct pollfd uwsgi_poll;
struct sockaddr_in uws_addr;
int cnt ;
struct uwsgi_header uh;
if (size > 0xFFFF) {
fprintf(stderr,"invalid object (marshalled) size\n");
return -1 ;
}
uwsgi_fd = socket(AF_INET, SOCK_STREAM, 0);
if (uwsgi_fd < 0) {
perror("socket()");
return -1 ;
}
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(port);
uws_addr.sin_addr.s_addr = inet_addr(host);
if (connect(uwsgi_fd, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in))) {
perror("connect()");
close(uwsgi_fd);
return -1 ;
}
uh.modifier1 = modifier1;
uh.pktsize = (uint16_t) size ;
uh.modifier2 = modifier2;
cnt = write(uwsgi_fd, &uh, 4) ;
if (cnt != 4) {
perror("write()");
close(uwsgi_fd);
return -1;
}
cnt = write(uwsgi_fd, message, size) ;
if (cnt != size) {
perror("write()");
close(uwsgi_fd);
return -1;
}
return uwsgi_fd;
}
PyObject *uwsgi_send_message(char *host, int port, uint8_t modifier1, uint8_t modifier2, char *message, int size, int timeout) {
struct pollfd uwsgi_mpoll ;
struct sockaddr_in uws_addr;
int cnt ;
int cnt;
struct uwsgi_header uh;
char buffer[0xFFFF];
if (!timeout)
timeout = 1;
if (size > 0xFFFF) {
fprintf(stderr,"invalid object (marshalled) size\n");
Py_INCREF(Py_None);
return Py_None;
uwsgi_log( "invalid object (marshalled) size\n");
return -1;
}
uwsgi_mpoll.events = POLLIN ;
uwsgi_mpoll.fd = socket(AF_INET, SOCK_STREAM, 0);
if (uwsgi_mpoll.fd < 0) {
perror("socket()");
Py_INCREF(Py_None);
return Py_None;
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
if (uwsgi_poll.fd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(port);
uws_addr.sin_port = htons(port);
uws_addr.sin_addr.s_addr = inet_addr(host);
uwsgi_poll.events = POLLIN;
if (connect(uwsgi_mpoll.fd, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in))) {
perror("connect()");
close(uwsgi_mpoll.fd);
Py_INCREF(Py_None);
return Py_None;
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in), timeout)) {
uwsgi_error("connect()");
close(uwsgi_poll.fd);
return -1;
}
uh.modifier1 = modifier1;
uh.pktsize = (uint16_t) size ;
uh.pktsize = (uint16_t) size;
uh.modifier2 = modifier2;
cnt = write(uwsgi_mpoll.fd, &uh, 4) ;
cnt = write(uwsgi_poll.fd, &uh, 4);
if (cnt != 4) {
perror("write()");
close(uwsgi_mpoll.fd);
Py_INCREF(Py_None);
return Py_None;
}
cnt = write(uwsgi_mpoll.fd, message, size) ;
uwsgi_error("write()");
close(uwsgi_poll.fd);
return -1;
}
cnt = write(uwsgi_poll.fd, message, size);
if (cnt != size) {
perror("write()");
uwsgi_error("write()");
close(uwsgi_poll.fd);
return -1;
}
return uwsgi_poll.fd;
}
PyObject *uwsgi_send_message(const char *host, int port, uint8_t modifier1, uint8_t modifier2, char *message, int size, int timeout) {
struct pollfd uwsgi_mpoll;
struct sockaddr_in uws_addr;
int cnt;
struct uwsgi_header uh;
char buffer[0xFFFF];
if (!timeout)
timeout = 1;
if (size > 0xFFFF) {
uwsgi_log( "invalid object (marshalled) size\n");
Py_INCREF(Py_None);
return Py_None;
}
uwsgi_mpoll.events = POLLIN;
uwsgi_mpoll.fd = socket(AF_INET, SOCK_STREAM, 0);
if (uwsgi_mpoll.fd < 0) {
uwsgi_error("socket()");
Py_INCREF(Py_None);
return Py_None;
}
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(port);
uws_addr.sin_addr.s_addr = inet_addr(host);
UWSGI_SET_BLOCKING;
if (timed_connect(&uwsgi_mpoll, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in), timeout)) {
uwsgi_error("connect()");
close(uwsgi_mpoll.fd);
Py_INCREF(Py_None);
return Py_None;
}
if (!uwsgi_parse_response(&uwsgi_mpoll, timeout, &uh, buffer)) {
uh.modifier1 = modifier1;
uh.pktsize = (uint16_t) size;
uh.modifier2 = modifier2;
cnt = write(uwsgi_mpoll.fd, &uh, 4);
if (cnt != 4) {
uwsgi_error("write()");
close(uwsgi_mpoll.fd);
Py_INCREF(Py_None);
return Py_None;
return Py_None;
}
cnt = write(uwsgi_mpoll.fd, message, size);
if (cnt != size) {
uwsgi_error("write()");
close(uwsgi_mpoll.fd);
Py_INCREF(Py_None);
return Py_None;
}
if (!uwsgi_parse_response(&uwsgi_mpoll, timeout, &uh, buffer)) {
UWSGI_UNSET_BLOCKING;
Py_INCREF(Py_None);
return Py_None;
}
UWSGI_UNSET_BLOCKING;
close(uwsgi_mpoll.fd);
return PyMarshal_ReadObjectFromString(buffer, uh.pktsize);
if (uh.modifier1 == UWSGI_MODIFIER_RESPONSE) {
if (!uh.modifier2) {
Py_INCREF(Py_None);
return Py_None;
}
else {
Py_INCREF(Py_True);
return Py_True;
}
}
return PyMarshal_ReadObjectFromString(buffer, uh.pktsize);
}
int uwsgi_parse_response(struct pollfd * upoll, int timeout, struct uwsgi_header *uh, char *buffer) {
int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header *uh, char *buffer) {
int rlen, i;
if (!timeout)
timeout = 1;
/* first 4 byte header */
rlen = poll(upoll, 1, timeout*1000) ;
if (rlen < 0) {
perror("poll()");
exit(1);
}
else if (rlen == 0) {
fprintf(stderr, "timeout. skip request\n");
close(upoll->fd);
return 0 ;
}
rlen = read(upoll->fd, uh, 4) ;
if (rlen > 0 && rlen < 4) {
i = rlen ;
while(i < 4) {
rlen = poll(upoll, 1, timeout*1000) ;
if (rlen < 0) {
perror("poll()");
exit(1);
}
else if (rlen == 0) {
fprintf(stderr, "timeout waiting for header. skip request.\n");
close(upoll->fd);
break ;
}
rlen = read(upoll->fd, (char *)(uh)+i, 4-i);
if (rlen <= 0) {
fprintf(stderr, "broken header. skip request.\n");
close(upoll->fd);
break ;
}
i += rlen;
}
if (i < 4) {
return 0;
}
}
else if (rlen <= 0){
fprintf(stderr,"invalid request header size: %d...skip\n", rlen);
close(upoll->fd);
return 0;
}
/* big endian ? */
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(uh->pktsize);
#endif
/* check for max buffer size */
if (uh->pktsize > uwsgi.buffer_size) {
fprintf(stderr,"invalid request block size: %d...skip\n", uh->pktsize);
close(upoll->fd);
rlen = poll(upoll, 1, timeout * 1000);
if (rlen < 0) {
uwsgi_error("poll()");
exit(1);
}
else if (rlen == 0) {
uwsgi_log( "timeout. skip request\n");
close(upoll->fd);
return 0;
}
rlen = read(upoll->fd, uh, 4);
if (rlen > 0 && rlen < 4) {
i = rlen;
while (i < 4) {
rlen = poll(upoll, 1, timeout * 1000);
if (rlen < 0) {
uwsgi_error("poll()");
exit(1);
}
else if (rlen == 0) {
uwsgi_log( "timeout waiting for header. skip request.\n");
close(upoll->fd);
break;
}
rlen = read(upoll->fd, (char *) (uh) + i, 4 - i);
if (rlen <= 0) {
uwsgi_log( "broken header. skip request.\n");
close(upoll->fd);
break;
}
i += rlen;
}
if (i < 4) {
return 0;
}
}
}
else if (rlen <= 0) {
uwsgi_log( "invalid request header size: %d...skip\n", rlen);
close(upoll->fd);
return 0;
}
/* big endian ? */
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(uh->pktsize);
#endif
//fprintf(stderr,"ready for reading %d bytes\n", wsgi_req.size);
/* check for max buffer size */
if (uh->pktsize > uwsgi.buffer_size) {
uwsgi_log( "invalid request block size: %d...skip\n", uh->pktsize);
close(upoll->fd);
return 0;
}
i = 0 ;
while(i < uh->pktsize) {
rlen = poll(upoll, 1, timeout*1000) ;
if (rlen < 0) {
perror("poll()");
exit(1);
}
else if (rlen == 0) {
fprintf(stderr, "timeout. skip request. (expecting %d bytes, got %d)\n", uh->pktsize, i);
close(upoll->fd);
break ;
}
rlen = read(upoll->fd, buffer+i, uh->pktsize-i);
if (rlen <= 0) {
fprintf(stderr, "broken vars. skip request.\n");
close(upoll->fd);
break ;
}
i += rlen ;
}
//uwsgi_log("ready for reading %d bytes\n", wsgi_req.size);
i = 0;
while (i < uh->pktsize) {
rlen = poll(upoll, 1, timeout * 1000);
if (rlen < 0) {
uwsgi_error("poll()");
exit(1);
}
else if (rlen == 0) {
uwsgi_log( "timeout. skip request. (expecting %d bytes, got %d)\n", uh->pktsize, i);
close(upoll->fd);
break;
}
rlen = read(upoll->fd, buffer + i, uh->pktsize - i);
if (rlen <= 0) {
uwsgi_log( "broken vars. skip request.\n");
close(upoll->fd);
break;
}
i += rlen;
}
if (i < uh->pktsize) {
return 0;
}
if (i < uh->pktsize) {
return 0;
}
return 1;
return 1;
}
int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
char *buffer = wsgi_req->buffer;
char *ptrbuf, *bufferend;
uint16_t strsize = 0;
ptrbuf = buffer;
bufferend = ptrbuf + wsgi_req->uh.pktsize;
/* set an HTTP 500 status as default */
wsgi_req->status = 500;
while (ptrbuf < bufferend) {
if (ptrbuf + 2 < bufferend) {
memcpy(&strsize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
strsize = uwsgi_swap16(strsize);
#endif
/* key cannot be null */
if (!strsize) {
uwsgi_log( "uwsgi key cannot be null. skip this request.\n");
return -1;
}
ptrbuf += 2;
if (ptrbuf + strsize < bufferend) {
// var key
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
ptrbuf += strsize;
if (ptrbuf + 2 < bufferend) {
memcpy(&strsize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
strsize = uwsgi_swap16(strsize);
#endif
ptrbuf += 2;
if (ptrbuf + strsize <= bufferend) {
if (!strncmp("SCRIPT_NAME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->script_name = ptrbuf;
wsgi_req->script_name_len = strsize;
}
else if (!strncmp("SERVER_PROTOCOL", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->protocol = ptrbuf;
wsgi_req->protocol_len = strsize;
}
else if (!strncmp("REQUEST_URI", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->uri = ptrbuf;
wsgi_req->uri_len = strsize;
}
else if (!strncmp("QUERY_STRING", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->query_string = ptrbuf;
wsgi_req->query_string_len = strsize;
}
else if (!strncmp("REQUEST_METHOD", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->method = ptrbuf;
wsgi_req->method_len = strsize;
}
else if (!strncmp("REMOTE_ADDR", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_addr = ptrbuf;
wsgi_req->remote_addr_len = strsize;
}
else if (!strncmp("REMOTE_USER", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_user = ptrbuf;
wsgi_req->remote_user_len = strsize;
}
else if (!strncmp("UWSGI_SCHEME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->scheme = ptrbuf;
wsgi_req->scheme_len = strsize;
}
else if (!strncmp("UWSGI_SCRIPT",wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len )) {
wsgi_req->wsgi_script = ptrbuf;
wsgi_req->wsgi_script_len = strsize;
}
else if (!strncmp("UWSGI_MODULE", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->wsgi_module = ptrbuf;
wsgi_req->wsgi_module_len = strsize;
}
else if (!strncmp("UWSGI_CALLABLE", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->wsgi_callable = ptrbuf;
wsgi_req->wsgi_callable_len = strsize;
}
else if (!strncmp("HTTPS", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->https = ptrbuf;
wsgi_req->https_len = strsize;
}
#ifdef UNBIT
else if (!strncmp("UNBIT_FLAGS", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->unbit_flags = *(unsigned long long *) ptrbuf;
}
#endif
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this header.\n");
return -1;
}
// var value
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
//uwsgi_log("%.*s = %.*s\n", wsgi_req->hvec[wsgi_req->var_cnt-1].iov_len, wsgi_req->hvec[wsgi_req->var_cnt-1].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len, wsgi_req->hvec[wsgi_req->var_cnt].iov_base);
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this header.\n");
return -1;
}
ptrbuf += strsize;
}
else {
return -1;
}
}
else {
return -1;
}
}
}
else {
return -1;
}
}
return 0;
}
int uwsgi_ping_node(int node, struct wsgi_request *wsgi_req) {
struct pollfd uwsgi_poll;
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[node];
if (ucn->name[0] == 0) {
return 0;
}
if (ucn->status == UWSGI_NODE_OK) {
return 0;
}
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
if (uwsgi_poll.fd < 0) {
uwsgi_error("socket()");
return -1;
}
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &ucn->ucn_addr, sizeof(struct sockaddr_in), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
close(uwsgi_poll.fd);
return -1;
}
wsgi_req->uh.modifier1 = UWSGI_MODIFIER_PING;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
if (write(uwsgi_poll.fd, wsgi_req, 4) != 4) {
uwsgi_error("write()");
return -1;
}
uwsgi_poll.events = POLLIN;
if (!uwsgi_parse_response(&uwsgi_poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) wsgi_req, wsgi_req->buffer)) {
return -1;
}
return 0;
}
+406
View File
@@ -0,0 +1,406 @@
#ifdef UWSGI_PROXY
/*
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 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 uwsgi_proxy(int proxyfd) {
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;
uwsgi_log( "spawned uWSGI proxy (pid: %d)\n", getpid());
uwsgi_log( "allocating space for %d concurrent proxy connections\n", max_connections);
// 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);
efd = async_queue_init(proxyfd);
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 (eevents[i].ASYNC_FD == proxyfd) {
if (eevents[i].ASYNC_IS_IN) {
// new connection, accept it
ev.ASYNC_FD = accept(proxyfd, (struct sockaddr *) &upc_addr, &upc_len);
if (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);
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);
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;
}
}
}
}
}
#else
#warning "*** PROXY support is disabled ***"
#endif
+3
View File
@@ -0,0 +1,3 @@
import uwsgi
uwsgi.load_plugin(0, "plugins/psgi/psgi_plugin.so", "test.psgi")
+145
View File
@@ -0,0 +1,145 @@
#include "uwsgi.h"
int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
PyObject *pychunk ;
ssize_t wsize ;
#ifdef UWSGI_SENDFILE
ssize_t sf_len = 0 ;
#endif
// return or yield ?
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
uwsgi_error("write()");
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
#ifdef PYTHREE
if (PyBytes_Check((PyObject *)wsgi_req->async_result)) {
if ((wsize = write(wsgi_req->poll.fd, PyBytes_AsString(wsgi_req->async_result), PyBytes_Size(wsgi_req->async_result))) < 0) {
uwsgi_error("write()");
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
#endif
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd != -1) {
sf_len = uwsgi_sendfile(uwsgi, wsgi_req);
if (sf_len < 1) goto clear;
wsgi_req->response_size += sf_len ;
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
if (wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
return UWSGI_AGAIN;
}
}
#endif
goto clear;
}
#endif
// ok its a yield
if (!wsgi_req->async_placeholder) {
wsgi_req->async_placeholder = PyObject_GetIter(wsgi_req->async_result);
if (!wsgi_req->async_placeholder) {
goto clear2;
}
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
}
pychunk = PyIter_Next(wsgi_req->async_placeholder) ;
if (!pychunk) {
if (PyErr_Occurred()) PyErr_Print();
goto clear;
}
if (PyString_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
uwsgi_error("write()");
Py_DECREF(pychunk);
goto clear;
}
wsgi_req->response_size += wsize;
}
#ifdef PYTHREE
if (PyBytes_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyBytes_AsString(pychunk), PyBytes_Size(pychunk))) < 0) {
uwsgi_error("write()");
Py_DECREF(pychunk);
goto clear;
}
wsgi_req->response_size += wsize;
}
#endif
Py_DECREF(pychunk);
return UWSGI_AGAIN ;
clear:
if (wsgi_req->sendfile_fd != -1) {
Py_DECREF((PyObject *)wsgi_req->async_sendfile);
}
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
if (wsgi_req->async_post && !wsgi_req->fd_closed) {
fclose(wsgi_req->async_post);
wsgi_req->fd_closed = 1 ;
}
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
clear2:
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
return UWSGI_OK;
}
PyObject *python_call(PyObject *callable, PyObject *args) {
PyObject *pyret;
pyret = PyEval_CallObject(callable, args);
if (PyErr_Occurred()) {
PyErr_Print();
}
return pyret;
}
int uwsgi_python_call(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, PyObject *callable, PyObject *args) {
wsgi_req->async_result = python_call(callable, args);
if (wsgi_req->async_result) {
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
}
}
return UWSGI_OK;
}
+160
View File
@@ -0,0 +1,160 @@
#ifdef UWSGI_SENDFILE
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "Oi:uwsgi_sendfile", &wsgi_req->async_sendfile, &wsgi_req->sendfile_fd_chunk)) {
return NULL;
}
#ifdef PYTHREE
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
#else
if (PyFile_Check((PyObject *)wsgi_req->async_sendfile)) {
Py_INCREF((PyObject *)wsgi_req->async_sendfile);
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
}
#endif
return PyTuple_New(0);
}
ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int fd = wsgi_req->sendfile_fd ;
int sockfd = wsgi_req->poll.fd ;
struct stat stat_buf;
int sf_ret;
if (!wsgi_req->sendfile_fd_size) {
if (fstat(fd, &stat_buf)) {
uwsgi_error("fstat()");
return 0;
}
else {
wsgi_req->sendfile_fd_size = stat_buf.st_size;
}
}
if (wsgi_req->sendfile_fd_size) {
if (!wsgi_req->sendfile_fd_chunk) wsgi_req->sendfile_fd_chunk = 4096 ;
#if defined(__FreeBSD__) || defined(__DragonFly__)
off_t sf_len = wsgi_req->sendfile_fd_size ;
if (uwsgi->async > 1) {
sf_len = wsgi_req->sendfile_fd_chunk;
sf_ret = sendfile(fd, sockfd, wsgi_req->sendfile_fd_pos, 0, NULL, &sf_len, 0);
wsgi_req->sendfile_fd_pos += sf_len ;
}
else {
sf_ret = sendfile(fd, sockfd, 0, 0, NULL, &sf_len, 0);
}
if (sf_ret) {
uwsgi_error("sendfile()");
return 0;
}
return sf_len;
#elif __APPLE__
off_t sf_len = wsgi_req->sendfile_fd_size ;
if (uwsgi->async > 1) {
sf_len = wsgi_req->sendfile_fd_chunk;
sf_ret = sendfile(fd, sockfd, wsgi_req->sendfile_fd_pos, &sf_len, NULL, 0);
wsgi_req->sendfile_fd_pos += sf_len ;
}
else {
sf_ret = sendfile(fd, sockfd, 0, &sf_len, NULL, 0);
}
if (sf_ret) {
uwsgi_error("sendfile()");
return 0;
}
return sf_len;
#elif defined(__linux__) || defined(__sun__)
if (uwsgi->async > 1) {
sf_ret = sendfile(sockfd, fd, &wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_chunk);
}
else {
sf_ret = sendfile(sockfd, fd, &wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_size);
}
if (sf_ret < 0) {
uwsgi_error("sendfile()");
return 0;
}
return sf_ret ;
#else
static nosf_buf_size = 0 ;
static char *nosf_buf ;
ssize_t jlen = 0;
ssize_t rlen = 0;
ssize_t i = 0;
if (!nosf_buf) {
nosf_buf = malloc(wsgi_req->sendfile_fd_chunk);
}
else if (wsgi_req->sendfile_fd_chunk != nosf_buf_size) {
nosf_buf = realloc(nosf_buf, wsgi_req->sendfile_fd_chunk);
}
nosf_buf_size = wsgi_req->sendfile_fd_chunk ;
if (uwsgi->async > 1) {
jlen = read(fd, nosf_buf, wsgi_req->sendfile_fd_chunk);
if (jlen <= 0) {
uwsgi_error("read()");
return 0;
}
jlen = write(sockfd, nosf_buf, jlen);
if (jlen <= 0) {
uwsgi_error("write()");
return 0;
}
return jlen ;
}
while (i < wsgi_req->sendfile_fd_size) {
jlen = read(fd, nosf_buf, wsgi_req->sendfile_fd_chunk);
if (jlen <= 0) {
uwsgi_error("read()");
break;
}
i += jlen;
jlen = write(sockfd, nosf_buf, jlen);
if (jlen <= 0) {
uwsgi_error("write()");
break;
}
rlen += jlen ;
}
return rlen;
#endif
}
return 0;
}
#endif
+47
View File
@@ -0,0 +1,47 @@
import os
import sys
import uwsgiconfig as uc
import shutil
from setuptools import setup
from setuptools.dist import Distribution
from setuptools.command.install import install
from setuptools.command.build_ext import build_ext
class uWSGIBuilder(build_ext):
def run(self):
uc.parse_vars()
uc.build_uwsgi(sys.prefix + '/bin/' + uc.UWSGI_BIN_NAME)
class uWSGIInstall(install):
def run(self):
# hack, hack and still hack. We need to find a solution for 0.9.6
if self.record:
record_file = open(self.record,'w')
uc.parse_vars()
uc.build_uwsgi(sys.prefix + '/bin/' + uc.UWSGI_BIN_NAME)
class uWSGIDistribution(Distribution):
def __init__(self, *attrs):
Distribution.__init__(self, *attrs)
self.cmdclass['install'] = uWSGIInstall
self.cmdclass['build_ext'] = uWSGIBuilder
setup(name='uWSGI',
version='0.9.5',
description='The uWSGI server',
author='Unbit',
author_email='info@unbit.it',
url='http://projects.unbit.it/uwsgi/',
license='GPL2',
distclass = uWSGIDistribution,
)
+8
View File
@@ -0,0 +1,8 @@
def application(env, start_response):
#print env
start_response('200 Ok', [('Content-type', 'text/plain')])
yield "hello world"
yield "hello world2"
for i in xrange(1,1000):
yield str(i)
+6
View File
@@ -0,0 +1,6 @@
import uwsgi
def print_logs(ip, port, message):
print(ip, port, message)
uwsgi.udp_callable = print_logs
+455
View File
@@ -0,0 +1,455 @@
#ifdef UWSGI_SNMP
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#define SNMP_SEQUENCE 0x30
#define SNMP_INTEGER 0x02
#define SNMP_STRING 0x04
#define SNMP_NULL 0x05
#define SNMP_GET 0xA0
#define SNMP_RES 0xA2
#define SNMP_OID 0x06
#define SNMP_WATERMARK (127-8)
/* 1.3.6.1.4.1.35156.17.X.X */
#define SNMP_UWSGI_BASE "\x2B\x06\x01\x04\x01\x82\x92\x54\x11"
static int get_snmp_integer(uint8_t *, uint64_t *);
static uint64_t get_uwsgi_snmp_value(uint64_t, uint8_t *);
static uint64_t get_uwsgi_custom_snmp_value(uint64_t, uint8_t *);
static uint8_t snmp_int_to_snmp(uint64_t, uint8_t, uint8_t *);
static ssize_t build_snmp_response(uint8_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_addr) {
uint16_t asnlen;
uint16_t oidlen;
uint8_t oid_part[2];
int ptrdelta;
uint8_t *ptr = buffer, *seq1, *seq2, *seq3;
uint8_t community_len;
uint64_t snmp_int;
uint64_t request_id;
uint64_t version;
// KISS for memory management
if (size > SNMP_WATERMARK)
return;
ptr++;
// check total sequence size
if (*ptr > SNMP_WATERMARK || *ptr < 13)
return;
ptr++;
// check snmp version
if (*ptr != SNMP_INTEGER)
return;
ptr++;
ptrdelta = get_snmp_integer(ptr, &version);
if (version > 2)
return;
ptr += ptrdelta;
// check for community string (this must be set from the python vm using uwsgi.snmp_community or with --snmp-community arg)
if (*ptr != SNMP_STRING)
return;
ptr++;
community_len = *ptr;
if (community_len > 72 || community_len < 1)
return;
ptr++;
// check for community string
if (strlen(uwsgi.shared->snmp_community) != community_len)
return;
if (memcmp(ptr, uwsgi.shared->snmp_community, community_len))
return;
ptr += community_len;
// check for get request
if (*ptr != SNMP_GET)
return;
*ptr = SNMP_RES;
ptr++;
seq1 = ptr;
if (*ptr != ((size - community_len) - 9))
return;
ptr++;
// get request_id
if (*ptr != SNMP_INTEGER)
return;
ptr++;
ptrdelta = get_snmp_integer(ptr, &request_id);
if (ptrdelta <= 0)
return;
// check here
if (ptr + ptrdelta >= buffer + size)
return;
ptr += ptrdelta;
// get error
if (*ptr != SNMP_INTEGER)
return;
ptr++;
ptrdelta = get_snmp_integer(ptr, &snmp_int);
if (ptrdelta <= 0)
return;
if (ptr + ptrdelta >= buffer + size)
return;
if (snmp_int != 0)
return;
ptr += ptrdelta;
// get index
if (*ptr != SNMP_INTEGER)
return;
ptr++;
ptrdelta = get_snmp_integer(ptr, &snmp_int);
if (ptrdelta <= 0)
return;
if (ptr + ptrdelta >= buffer + size)
return;
if (snmp_int != 0)
return;
ptr += ptrdelta;
// check for sequence
if (*ptr != SNMP_SEQUENCE)
return;
ptr++;
if (*ptr > SNMP_WATERMARK)
return;
seq2 = ptr;
ptr++;
// now the interesting stuff: OID management
if (*ptr != SNMP_SEQUENCE)
return;
ptr++;
// check for normal OID uWSGI size: |1.3|.6|.1|.4|.1.|35156|.17|.1/2|.x| + OID_NULL
asnlen = *ptr;
if (asnlen < 15)
return;
seq3 = ptr;
ptr++;
// is it an OID ?
if (*ptr != SNMP_OID)
return;
ptr++;
oidlen = *ptr;
if (oidlen != 11)
return;
ptr++;
// and now parse the OID !!!
if (memcmp(ptr, SNMP_UWSGI_BASE, 9))
return;
ptr += 9;
oid_part[0] = *ptr;
if (oid_part[0] != 1 && oid_part[0] != 2)
return;
ptr++;
oid_part[1] = *ptr;
if (oid_part[1] < 1 || oid_part[1] > 100)
return;
ptr++;
// check for null
if (memcmp((char *) ptr, "\x05\x00", 2))
return;
ptr += 2;
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
if (size > 0) {
if (sendto(fd, buffer, size, 0, (struct sockaddr *) client_addr, sizeof(struct sockaddr_in)) < 0) {
uwsgi_error("sendto()");
}
}
}
static uint64_t get_uwsgi_snmp_value(uint64_t val, uint8_t * oid_t) {
val--;
if (uwsgi.shared->snmp_gvalue[val].type) {
*oid_t = uwsgi.shared->snmp_gvalue[val].type;
return *uwsgi.shared->snmp_gvalue[val].val;
}
*oid_t = SNMP_NULL;
return 0;
}
static uint64_t get_uwsgi_custom_snmp_value(uint64_t val, uint8_t * oid_t) {
val--;
if (uwsgi.shared->snmp_value[val].type) {
*oid_t = uwsgi.shared->snmp_value[val].type;
return uwsgi.shared->snmp_value[val].val;
}
*oid_t = SNMP_NULL;
return 0;
}
static int get_snmp_integer(uint8_t * ptr, uint64_t * val) {
uint16_t tlen;
int i, j;
tlen = *ptr;
if (tlen > 4)
return -1;
j = 0;
#ifdef __BIG_ENDIAN__
for (i = 0; i < tlen; i++) {
#else
for (i = tlen - 1; i >= 0; i--) {
#endif
val[j] = ptr[1 + i];
j++;
}
return tlen + 1;
}
static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * buffer) {
uint8_t tlen;
int i, j;
uint8_t *ptr = (uint8_t *) &snmp_val;
// check for counter, counter64 or gauge
if (oid_type == SNMP_COUNTER64) {
tlen = 8;
}
else if (oid_type == SNMP_NULL || oid_type == 0) {
tlen = 0;
}
else {
tlen = 4;
}
buffer[0] = tlen;
j = 1;
#ifdef __BIG_ENDIAN__
for (i = 0; i < tlen; i++) {
#else
for (i = tlen - 1; i >= 0; i--) {
#endif
buffer[j] = ptr[i];
j++;
}
return tlen + 1;
}
static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
uint64_t snmp_val;
uint8_t oid_sz;
uint8_t oid_type;
if (oid1 == 1) {
snmp_val = get_uwsgi_snmp_value(oid2, &oid_type);
}
else if (oid1 == 2) {
snmp_val = get_uwsgi_custom_snmp_value(oid2, &oid_type);
}
else {
return -1;
}
buffer[size - 2] = oid_type;
oid_sz = snmp_int_to_snmp(snmp_val, oid_type, buffer + (size - 1));
if (oid_sz < 1)
return -1;
oid_sz--;
buffer[1] += oid_sz;
*seq1 += oid_sz;
*seq2 += oid_sz;
*seq3 += oid_sz;
return size + oid_sz;
}
PyObject *py_snmp_counter32(PyObject * self, PyObject * args) {
uint8_t oid_num;
uint32_t oid_val = 0;
if (!PyArg_ParseTuple(args, "bI:snmp_set_counter32", &oid_num, &oid_val)) {
return NULL;
}
if (oid_num > 100 || oid_num < 1)
goto clear;
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER32;
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
Py_INCREF(Py_True);
return Py_True;
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_snmp_counter64(PyObject * self, PyObject * args) {
uint8_t oid_num;
uint64_t oid_val = 0;
if (!PyArg_ParseTuple(args, "bK:snmp_set_counter64", &oid_num, &oid_val)) {
return NULL;
}
if (oid_num > 100 || oid_num < 1)
goto clear;
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER64;
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
Py_INCREF(Py_True);
return Py_True;
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_snmp_gauge(PyObject * self, PyObject * args) {
uint8_t oid_num;
uint32_t oid_val = 0;
if (!PyArg_ParseTuple(args, "bI:snmp_set_gauge", &oid_num, &oid_val)) {
return NULL;
}
if (oid_num > 100 || oid_num < 1)
goto clear;
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_GAUGE;
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
Py_INCREF(Py_True);
return Py_True;
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_snmp_community(PyObject * self, PyObject * args) {
char *snmp_community;
if (!PyArg_ParseTuple(args, "s:snmp_set_community", &snmp_community)) {
return NULL;
}
if (strlen(snmp_community) > 72) {
uwsgi_log( "*** warning the supplied SNMP community string will be truncated to 72 chars ***\n");
memcpy(uwsgi.shared->snmp_community, snmp_community, 72);
}
else {
strlcpy(uwsgi.shared->snmp_community, snmp_community, 73);
}
Py_INCREF(Py_True);
return Py_True;
}
static PyMethodDef uwsgi_snmp_methods[] = {
{"snmp_set_counter32", py_snmp_counter32, METH_VARARGS, ""},
{"snmp_set_counter64", py_snmp_counter64, METH_VARARGS, ""},
{"snmp_set_gauge", py_snmp_gauge, METH_VARARGS, ""},
{"snmp_set_community", py_snmp_community, METH_VARARGS, ""},
{NULL, NULL},
};
void snmp_init() {
PyMethodDef *uwsgi_function;
for (uwsgi_function = uwsgi_snmp_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(uwsgi.embedded_dict, uwsgi_function->ml_name, func);
Py_DECREF(func);
}
uwsgi_log( "SNMP python functions initialized.\n");
}
#else
#warning "*** SNMP support is disabled ***"
#endif
+301 -51
View File
@@ -1,75 +1,241 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abstract_socket) {
int serverfd;
struct sockaddr_un *uws_addr;
fprintf(stderr, "binding on UNIX socket: %s\n", socket_name);
uwsgi_log( "binding on UNIX socket: %s\n", socket_name);
// leave 1 byte for abstract namespace (108 linux -> 104 bsd/mac)
if (strlen(socket_name) > 102) {
fprintf(stderr, "invalid socket name\n");
exit(1);
}
// leave 1 byte for abstract namespace (108 linux -> 104 bsd/mac)
if (strlen(socket_name) > 102) {
uwsgi_log( "invalid socket name\n");
exit(1);
}
uws_addr = malloc(sizeof(struct sockaddr_un));
if (uws_addr == NULL) {
perror("malloc()");
exit(1);
}
uws_addr = malloc(sizeof(struct sockaddr_un));
if (uws_addr == NULL) {
uwsgi_error("malloc()");
exit(1);
}
memset(uws_addr, 0, sizeof(struct sockaddr_un)) ;
serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (serverfd < 0) {
perror("socket()");
exit(1);
}
if (abstract_socket == 0) {
if (unlink(socket_name) != 0) {
perror("unlink()");
}
}
memset(uws_addr, 0, sizeof(struct sockaddr_un));
serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (serverfd < 0) {
uwsgi_error("socket()");
exit(1);
}
if (abstract_socket == 0) {
if (unlink(socket_name) != 0 && errno != ENOENT) {
uwsgi_error("unlink()");
}
}
if (abstract_socket ==1) {
fprintf(stderr, "setting abstract socket mode (warning: only Linux supports this)\n");
}
if (abstract_socket == 1) {
uwsgi_log( "setting abstract socket mode (warning: only Linux supports this)\n");
}
uws_addr->sun_family = AF_UNIX;
strcpy(uws_addr->sun_path+abstract_socket, socket_name);
strlcpy(uws_addr->sun_path + abstract_socket, socket_name, 102+1);
if (bind(serverfd, (struct sockaddr *) uws_addr, strlen(socket_name)+ abstract_socket + ( (void *)uws_addr->sun_path - (void *)uws_addr) ) != 0) {
perror("bind()");
if (bind(serverfd, (struct sockaddr *) uws_addr, strlen(socket_name) + abstract_socket + ((void *) uws_addr->sun_path - (void *) uws_addr)) != 0) {
uwsgi_error("bind()");
exit(1);
}
if (listen(serverfd, listen_queue) != 0) {
perror("listen()");
exit(1);
uwsgi_error("listen()");
exit(1);
}
// chmod unix socket for lazy users
if (chmod_socket == 1 && abstract_socket == 0) {
fprintf(stderr, "chmod() socket to 666 for lazy and brave users\n");
if (chmod(socket_name, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 0) {
perror("chmod()");
}
uwsgi_log( "chmod() socket to 666 for lazy and brave users\n");
if (chmod(socket_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0) {
uwsgi_error("chmod()");
}
}
return serverfd;
}
#ifdef UWSGI_SCTP
#define MAX_SCTP_ADDRESS 4
/* sctp address format sctp:127.0.0.1,192.168.0.17:3031 */
int bind_to_sctp(char *socket_name, int listen_queue, char *sctp_port) {
int serverfd;
struct sockaddr_in uws_addr[MAX_SCTP_ADDRESS];
int num_ip = 0;
struct sctp_initmsg sctp_im;
sctp_port[0] = 0;
memset(uws_addr, 0, sizeof(struct sockaddr_in) * MAX_SCTP_ADDRESS);
memset(&sctp_im, 0, sizeof(struct sctp_initmsg));
while (socket_name != NULL && num_ip < MAX_SCTP_ADDRESS) {
char *ap;
while ((ap = strsep(&socket_name, ",")) != NULL) {
if (*ap != '\0') {
uws_addr[num_ip].sin_family = AF_INET;
uws_addr[num_ip].sin_port = htons(atoi(sctp_port + 1));
uws_addr[num_ip].sin_addr.s_addr = inet_addr(ap);
num_ip++;
}
}
}
serverfd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
if (serverfd < 0) {
uwsgi_error("socket()");
exit(1);
}
uwsgi_log( "binding on %d SCTP interfaces on port: %d\n", num_ip, ntohs(uws_addr[0].sin_port));
if (sctp_bindx(serverfd, (struct sockaddr *) uws_addr, num_ip, SCTP_BINDX_ADD_ADDR) != 0) {
uwsgi_error("sctp_bindx()");
exit(1);
}
sctp_im.sinit_max_instreams = 0xFFFF;
sctp_im.sinit_num_ostreams = 0xFFFF;
if (setsockopt(serverfd, IPPROTO_SCTP, SCTP_INITMSG, &sctp_im, sizeof(sctp_im))) {
uwsgi_error("setsockopt()");
}
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
exit(1);
}
return serverfd;
}
#endif
#ifdef UWSGI_UDP
int bind_to_udp(char *socket_name) {
int serverfd;
struct sockaddr_in uws_addr;
char *udp_port;
#ifdef UWSGI_MULTICAST
struct ip_mreq mc;
#endif
udp_port = strchr(socket_name, ':');
if (udp_port == NULL) {
return -1;
}
udp_port[0] = 0;
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(atoi(udp_port + 1));
if (socket_name[0] != 0) {
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
}
else {
uws_addr.sin_addr.s_addr = INADDR_ANY;
}
serverfd = socket(AF_INET, SOCK_DGRAM, 0);
if (serverfd < 0) {
uwsgi_error("socket()");
return -1;
}
#ifdef UWSGI_MULTICAST
if (uwsgi.multicast_group) {
uws_addr.sin_addr.s_addr = INADDR_ANY;
// if multicast is enabled remember to bind to INADDR_ANY
mc.imr_multiaddr.s_addr = inet_addr(uwsgi.multicast_group);
if (socket_name[0] == 0) {
mc.imr_interface.s_addr = INADDR_ANY;
}
else {
mc.imr_interface.s_addr = inet_addr(socket_name);
}
}
#endif
uwsgi_log( "binding on UDP port: %d\n", ntohs(uws_addr.sin_port));
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
uwsgi_error("bind()");
close(serverfd);
return -1;
}
#ifdef UWSGI_MULTICAST
if (uwsgi.multicast_group) {
uwsgi_log( "joining uWSGI multicast group: %s:%d\n", uwsgi.multicast_group, ntohs(uws_addr.sin_port));
if (setsockopt(serverfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc, sizeof(mc))) {
uwsgi_error("setsockopt()");
}
}
#endif
return serverfd;
}
#endif
int connect_to_tcp(char *socket_name, int port, int timeout) {
struct pollfd uwsgi_poll;
struct sockaddr_in uws_addr;
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(port);
if (socket_name[0] == 0) {
uws_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
}
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
if (uwsgi_poll.fd < 0) {
uwsgi_error("socket()");
return -1;
}
uwsgi_poll.events = POLLIN;
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in), timeout)) {
uwsgi_error("connect()");
close(uwsgi_poll.fd);
return -1;
}
return uwsgi_poll.fd;
}
int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
int serverfd;
struct sockaddr_in uws_addr;
int reuse = 1 ;
tcp_port[0] = 0 ;
int reuse = 1;
tcp_port[0] = 0;
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(atoi(tcp_port+1));
uws_addr.sin_port = htons(atoi(tcp_port + 1));
if (socket_name[0] == 0) {
@@ -79,29 +245,113 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
}
serverfd = socket(AF_INET, SOCK_STREAM, 0);
if (serverfd < 0) {
perror("socket()");
exit(1);
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&reuse , sizeof(int)) < 0) {
perror("setsockopt()");
serverfd = socket(AF_INET, SOCK_STREAM, 0);
if (serverfd < 0) {
uwsgi_error("socket()");
exit(1);
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
exit(1);
}
fprintf(stderr,"binding on TCP port: %d\n", ntohs(uws_addr.sin_port));
if (!uwsgi.no_defer_accept) {
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr) ) != 0) {
perror("bind()");
#ifdef __linux__
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
uwsgi_error("setsockopt()");
}
#elif defined(__apple__) || defined(__freebsd__)
struct accept_filter_arg afa;
strcpy(afa.af_name, "dataready");
afa.af_arg[0] = 0;
if (setsockopt(serverfd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(struct accept_filter_arg))) {
uwsgi_error("setsockopt()");
}
#endif
}
uwsgi_log( "binding on TCP port: %d\n", ntohs(uws_addr.sin_port));
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
uwsgi_error("bind()");
exit(1);
}
if (listen(serverfd, listen_queue) != 0) {
perror("listen()");
exit(1);
uwsgi_error("listen()");
exit(1);
}
return serverfd;
}
int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_size, int timeout) {
int arg, ret;
int soopt;
socklen_t solen = sizeof(int);
int cnt;
/* set non-blocking socket */
arg = fcntl(fdpoll->fd, F_GETFL, NULL);
if (arg < 0) {
uwsgi_error("fcntl()");
return -1;
}
arg |= O_NONBLOCK;
if (fcntl(fdpoll->fd, F_SETFL, arg) < 0) {
uwsgi_error("fcntl()");
return -1;
}
ret = connect(fdpoll->fd, addr, addr_size);
if (ret < 0) {
/* check what happened */
// in progress ?
if (errno == EINPROGRESS) {
if (timeout < 1)
timeout = 3;
fdpoll->events = POLLOUT;
cnt = poll(fdpoll, 1, timeout * 1000);
/* check for errors */
if (cnt < 0 && errno != EINTR) {
uwsgi_error("poll()");
return -1;
}
/* something hapened on the socket ... */
else if (cnt > 0) {
if (getsockopt(fdpoll->fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
return -1;
}
/* is something bad ? */
if (soopt) {
return -1;
}
}
/* timeout */
else {
return -1;
}
}
else {
return -1;
}
}
/* re-set blocking socket */
arg &= (~O_NONBLOCK);
if (fcntl(fdpoll->fd, F_SETFL, arg) < 0) {
uwsgi_error("fcntl()");
return -1;
}
return 0;
}
+148 -108
View File
@@ -1,116 +1,105 @@
#ifdef UWSGI_SPOOLER
#include "uwsgi.h"
#include <dirent.h>
extern char *spool_dir;
struct uwsgi_packet_header {
uint8_t modifier1;
uint16_t datasize;
uint8_t modifier2;
};
int spool_request(struct uwsgi_server *uwsgi, char *filename, int rn, char *buffer, int size) {
int spool_request(char *filename, int rn, char *buffer, int size) {
char hostname[256+1];
struct timeval tv;
char hostname[256 + 1];
struct timeval tv;
int fd;
struct uwsgi_packet_header uh ;
struct uwsgi_header uh;
if (gethostname(hostname,256)) {
perror("gethostname()");
return 0 ;
}
gettimeofday(&tv, NULL);
hostname[256] = 0 ;
if (snprintf(filename,1024,"%s/uwsgi_spoolfile_on_%s_%d_%d_%llu_%llu", spool_dir, hostname, getpid(), rn, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec ) <= 0) {
if (gethostname(hostname, 256)) {
uwsgi_error("gethostname()");
return 0;
}
fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
gettimeofday(&tv, NULL);
hostname[256] = 0;
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%llu_%llu", uwsgi->spool_dir, hostname, getpid(), rn, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
return 0;
}
fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
perror("open()");
return 0 ;
uwsgi_error("open()");
return 0;
}
#ifdef __sun__
if (lockf(fd, F_LOCK, 0)) {
perror("lockf()");
uwsgi_error("lockf()");
#else
if (flock(fd, LOCK_EX)) {
perror("flock()");
uwsgi_error("flock()");
#endif
close(fd);
return 0;
}
uh.modifier1 = 17 ;
uh.modifier2 = 0 ;
uh.datasize = (uint16_t) size ;
uh.modifier1 = 17;
uh.modifier2 = 0;
uh.pktsize = (uint16_t) size;
#ifdef __BIG_ENDIAN__
uh.datasize= uwsgi_swap16(uh.datasize);
uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif
if (write(fd, &uh, 4) != 4) {
goto clear ;
goto clear;
}
if (write(fd, buffer, size) != size) {
goto clear ;
goto clear;
}
close(fd);
fprintf(stderr,"written %d bytes to spool file %s.\n",size + 4, filename);
uwsgi_log( "written %d bytes to spool file %s.\n", size + 4, filename);
return 1;
clear:
perror("write()");
clear:
uwsgi_error("write()");
unlink(filename);
close(fd);
return 0;
}
void spooler(PyObject *uwsgi_module) {
DIR *sdir ;
void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
DIR *sdir;
struct dirent *dp;
PyObject *uwsgi_module_dict, *spooler_callable, *spool_result, *spool_tuple, *spool_env ;
int spool_fd ;
uint16_t uwstrlen ;
PyObject *spooler_callable, *spool_result, *spool_tuple, *spool_env;
int spool_fd;
uint16_t uwstrlen;
int rlen = 0;
int datasize ;
int datasize;
struct uwsgi_packet_header uh ;
struct uwsgi_header uh;
char *key;
char *val;
uwsgi_module_dict = PyModule_GetDict(uwsgi_module);
if (!uwsgi_module_dict) {
fprintf(stderr,"could not get uwsgi module __dict__\n");
exit(1);
}
// spool every 30 seconds by default
uwsgi->shared->spooler_frequency = 30 ;
spool_tuple = PyTuple_New(1);
if (!spool_tuple) {
fprintf(stderr,"could not create spooler tuple.\n");
uwsgi_log( "could not create spooler tuple.\n");
exit(1);
}
spool_env = PyDict_New();
if (!spool_env) {
fprintf(stderr,"could not create spooler env.\n");
uwsgi_log( "could not create spooler env.\n");
exit(1);
}
@@ -119,18 +108,22 @@ void spooler(PyObject *uwsgi_module) {
exit(1);
}
if (chdir(spool_dir)) {
perror("chdir()");
if (chdir(uwsgi->spool_dir)) {
uwsgi_error("chdir()");
exit(1);
}
for(;;) {
sdir = opendir(".");
// asked by Marco Beri
uwsgi_log( "lowering spooler priority to %d\n", PRIO_MAX);
setpriority(PRIO_PROCESS, getpid(), PRIO_MAX);
for (;;) {
sleep(uwsgi->shared->spooler_frequency);
sdir = opendir(uwsgi->spool_dir);
if (sdir) {
while((dp = readdir(sdir)) != NULL) {
#ifndef __sun__
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19) && dp->d_type == DT_REG) {
#else
while ((dp = readdir(sdir)) != NULL) {
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19)) {
struct stat sf_lstat;
if (lstat(dp->d_name, &sf_lstat)) {
@@ -139,94 +132,93 @@ void spooler(PyObject *uwsgi_module) {
if (!S_ISREG(sf_lstat.st_mode)) {
continue;
}
#endif
if (!access(dp->d_name, R_OK|W_OK)) {
fprintf(stderr,"managing spool request %s...\n", dp->d_name);
if (!access(dp->d_name, R_OK | W_OK)) {
uwsgi_log( "managing spool request %s...\n", dp->d_name);
spooler_callable = PyDict_GetItemString(uwsgi_module_dict, "spooler");
if (!spooler_callable) {
fprintf(stderr,"you have to define uwsgi.spooler to use the spooler !!!\n");
uwsgi_log( "you have to define uwsgi.spooler to use the spooler !!!\n");
continue;
}
spool_fd = open(dp->d_name, O_RDONLY) ;
spool_fd = open(dp->d_name, O_RDONLY);
if (spool_fd < 0) {
perror("open()");
uwsgi_error("open()");
continue;
}
}
#ifdef __sun__
if (lockf(spool_fd, F_LOCK, 0)) {
perror("lockf()");
uwsgi_error("lockf()");
#else
if (flock(spool_fd, LOCK_EX)) {
perror("flock()");
uwsgi_error("flock()");
#endif
close(spool_fd);
continue;
}
if (read(spool_fd, &uh, 4) != 4) {
perror("read()");
uwsgi_error("read()");
close(spool_fd);
continue;
}
#ifdef __BIG_ENDIAN__
uh.datasize= uwsgi_swap16(uh.datasize);
#endif
datasize = 0 ;
#ifdef __BIG_ENDIAN__
uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif
while( datasize < uh.datasize) {
rlen = read(spool_fd, &uwstrlen, 2) ;
datasize = 0;
while (datasize < uh.pktsize) {
rlen = read(spool_fd, &uwstrlen, 2);
if (rlen != 2) {
perror("read()");
goto next_spool ;
uwsgi_error("read()");
goto next_spool;
}
datasize += rlen ;
datasize += rlen;
key = NULL;
val = NULL;
if (uwstrlen > 0) {
key = malloc(uwstrlen+1);
key = malloc(uwstrlen + 1);
if (!key) {
perror("malloc()");
uwsgi_error("malloc()");
goto retry_later;
}
rlen = read(spool_fd, key, uwstrlen);
if (rlen != uwstrlen) {
perror("read()");
uwsgi_error("read()");
free(key);
goto next_spool;
}
datasize += rlen ;
key[rlen] = 0 ;
datasize += rlen;
key[rlen] = 0;
rlen = read(spool_fd, &uwstrlen, 2);
if (rlen != 2) {
perror("read()");
uwsgi_error("read()");
free(key);
goto next_spool;
}
datasize += rlen ;
datasize += rlen;
if (uwstrlen > 0) {
val = malloc(uwstrlen+1);
val = malloc(uwstrlen + 1);
if (!val) {
free(key);
perror("malloc()");
uwsgi_error("malloc()");
goto retry_later;
}
rlen = read(spool_fd, val, uwstrlen);
if (rlen != uwstrlen) {
perror("read()");
free(key);
goto next_spool;
}
datasize += rlen ;
val[rlen] = 0 ;
uwsgi_error("read()");
free(key);
goto next_spool;
}
datasize += rlen;
val[rlen] = 0;
/* ready to add item to the dict */
}
@@ -234,7 +226,7 @@ void spooler(PyObject *uwsgi_module) {
PyErr_Print();
free(key);
free(val);
goto retry_later ;
goto retry_later;
}
free(key);
@@ -244,33 +236,33 @@ void spooler(PyObject *uwsgi_module) {
break;
}
}
spool_result = PyEval_CallObject(spooler_callable, spool_tuple);
spool_result = python_call(spooler_callable, spool_tuple);
if (!spool_result) {
PyErr_Print();
fprintf(stderr,"error detected. spool request canceled.\n");
uwsgi_log( "error detected. spool request canceled.\n");
goto next_spool;
}
if (PyInt_Check(spool_result)) {
if (PyInt_AsLong(spool_result) == 17) {
Py_DECREF(spool_result);
fprintf(stderr,"retry this task later...\n");
uwsgi_log( "retry this task later...\n");
goto retry_later;
}
}
Py_DECREF(spool_result);
fprintf(stderr,"done with task/spool %s\n", dp->d_name);
next_spool:
uwsgi_log( "done with task/spool %s\n", dp->d_name);
next_spool:
if (unlink(dp->d_name)) {
perror("unlink");
fprintf(stderr,"something horrible happened to the spooler. Better to kill it.\n");
uwsgi_error("unlink");
uwsgi_log( "something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
retry_later:
retry_later:
PyDict_Clear(spool_env);
close(spool_fd);
}
@@ -279,10 +271,58 @@ retry_later:
closedir(sdir);
}
else {
perror("opendir()");
uwsgi_error("opendir()");
}
/* TODO spooler frequency user-configurable */
sleep(5);
}
}
int uwsgi_request_spooler(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int i;
char spool_filename[1024];
if (uwsgi->spool_dir == NULL) {
uwsgi_log( "the spooler is inactive !!!...skip\n");
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
i = write(wsgi_req->poll.fd, wsgi_req, 4);
if (i != 4) {
uwsgi_error("write()");
}
return -1;
}
uwsgi_log( "managing spool request...\n");
i = spool_request(uwsgi, spool_filename, uwsgi->workers[0].requests + 1, wsgi_req->buffer, wsgi_req->uh.pktsize);
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
if (i > 0) {
wsgi_req->uh.modifier2 = 1;
if (write(wsgi_req->poll.fd, wsgi_req, 4) != 4) {
uwsgi_log( "disconnected client, remove spool file.\n");
/* client disconnect, remove spool file */
if (unlink(spool_filename)) {
uwsgi_error("unlink()");
uwsgi_log( "something horrible happened !!! check your spooler ASAP !!!\n");
goodbye_cruel_world();
}
}
return 0;
}
else {
/* announce a failed spool request */
wsgi_req->uh.modifier2 = 0;
i = write(wsgi_req->poll.fd, wsgi_req, 4);
if (i != 4) {
uwsgi_error("write()");
}
}
return -1;
}
#else
#warning "*** Spooler support is disabled ***"
#endif
+143
View File
@@ -0,0 +1,143 @@
#ifdef UWSGI_STACKLESS
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct wsgi_request* find_request_by_tasklet(PyTaskletObject *tasklet) {
int i ;
for(i=0;i<uwsgi.async;i++) {
if (uwsgi.stackless_table[i]->tasklet == tasklet) {
return uwsgi.stackless_table[i]->wsgi_req;
}
}
return NULL;
}
PyObject *py_uwsgi_stackless_worker(PyObject * self, PyObject * args) {
PyThreadState *ts = PyThreadState_GET();
struct wsgi_request *wsgi_req = find_request_by_tasklet(ts->st.current);
PyObject *zero;
int async_id = wsgi_req->async_id;
//uwsgi_log("i am the tasklet worker\n");
for(;;) {
// wait for request
zero = PyChannel_Receive(uwsgi.workers_channel);
wsgi_req_setup(wsgi_req, async_id);
if (wsgi_req_accept(uwsgi.serverfd, wsgi_req)) {
continue;
}
if (wsgi_req_recv(wsgi_req)) {
continue;
}
uwsgi_close_request(&uwsgi, wsgi_req);
}
}
PyMethodDef uwsgi_stackless_worker[] = { {"uwsgi_stackless_worker", py_uwsgi_stackless_worker, METH_VARARGS, ""} };
void stackless_init(struct uwsgi_server *uwsgi) {
int i;
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
PyObject *tasklet_worker = PyCFunction_New(uwsgi_stackless_worker, NULL);
uwsgi->workers_channel = PyChannel_New(NULL);
uwsgi->stackless_table = malloc( sizeof(struct stackless_req*) * uwsgi->async);
if (!uwsgi->stackless_table) {
uwsgi_error("malloc()");
exit(1);
}
for(i=0;i<uwsgi->async;i++) {
uwsgi->stackless_table[i] = malloc(sizeof(struct stackless_req));
if (!uwsgi->stackless_table[i]) {
uwsgi_error("malloc()");
exit(1);
}
memset(uwsgi->stackless_table[i], 0, sizeof(struct stackless_req));
}
uwsgi_log("initializing %d tasklet...", uwsgi->async);
// creating uwsgi->async tasklets
for(i=0;i<uwsgi->async;i++) {
wsgi_req->tasklet = PyTasklet_New(NULL, tasklet_worker);
uwsgi->stackless_table[i]->tasklet = wsgi_req->tasklet;
uwsgi->stackless_table[i]->wsgi_req = wsgi_req;
// useless for now, it will be used for I/O or other messaging
uwsgi->stackless_table[i]->channel = NULL;
wsgi_req->async_id = i ;
PyTasklet_Setup(wsgi_req->tasklet, PyTuple_New(0), NULL);
//PyTasklet_Run(wsgi_req->tasklet);
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
uwsgi_log("done\n");
}
void stackless_loop(struct uwsgi_server *uwsgi) {
int i;
PyTaskletObject *int_tasklet;
// tasklets main loop
for(;;) {
//uwsgi->async_running = -1 ;
//if (PyStackless_GetRunCount() > 0) {
uwsgi->async_running = 0 ;
//}
uwsgi->async_nevents = async_wait(uwsgi->async_queue, uwsgi->async_events, uwsgi->async, uwsgi->async_running, 0);
if (uwsgi->async_nevents < 0) {
continue;
}
for(i=0; i<uwsgi->async_nevents;i++) {
if (uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
//pass the connection to the first available tasklet
uwsgi_log("sending new connection...\n");
PyChannel_Send(uwsgi->workers_channel, Py_True);
}
}
/*
if (PyStackless_GetRunCount() > 0) {
PyStackless_Schedule(Py_None, 0);
}
*/
PyStackless_RunWatchdogEx( 10, PY_WATCHDOG_TOTALTIMEOUT);
//int_tasklet = (PyTaskletObject *) PyStackless_RunWatchdog( 1000 );
/*
uwsgi_log("done watchdog %p\n", int_tasklet);
if (!PyTasklet_IsCurrent(int_tasklet)) {
uwsgi_log("re-insert: %d\n", 1);// PyTasklet_Insert(int_tasklet));
}
uwsgi_log("recycle\n");
*/
}
}
#endif
+13
View File
@@ -0,0 +1,13 @@
import uwsgi
counter = 0
uwsgi.snmp_set_counter64(1, counter)
def application(environ, start_response):
global counter
start_response('200 OK', [('Content-Type', 'image/png')])
fd = open('logo_uWSGI.png','r')
counter = counter+1
uwsgi.snmp_set_counter64(1, counter)
return environ['wsgi.file_wrapper'](fd, 4096)
+12
View File
@@ -0,0 +1,12 @@
use strict;
use warnings;
my $app = sub {
my $env = shift;
return [
'200',
[ 'Content-Type' => 'text/plain' ],
[ "Hello World\r\n", $env->{'REQUEST_URI'} ],
];
};
+38 -17
View File
@@ -10,6 +10,7 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
#import django.core.handlers.wsgi
#uwsgi.load_plugin(0, "plugins/example/example_plugin.so", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa")
from threading import Thread
@@ -88,6 +89,10 @@ def djangohomepage():
def reload(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
#uwsgi.sorry_i_need_to_block()
#time.sleep(1)
#uwsgi.reload()
# print str(uwsgi.masterpid()) + "\n"
@@ -115,31 +120,47 @@ def reload(env, start_response):
# yield 4/0
out = '<h1>uWSGI status</h1>' ;
out += 'masterpid: <b>' + str(uwsgi.masterpid()) + '</b><br/>'
yield '<h1>uWSGI status ('+env['SCRIPT_NAME']+')</h1>' ;
yield 'masterpid: <b>' + str(uwsgi.masterpid()) + '</b><br/>'
out += 'started on: <b>' + time.ctime(uwsgi.started_on) + '</b><br/>'
yield 'started on: <b>' + time.ctime(uwsgi.started_on) + '</b><br/>'
out += 'buffer size: <b>' + str(uwsgi.buffer_size) + '</b><br/>'
yield 'buffer size: <b>' + str(uwsgi.buffer_size) + '</b><br/>'
out += 'total_requests: <b>' + str(uwsgi.total_requests()) + '</b><br/>'
yield 'total_requests: <b>' + str(uwsgi.total_requests()) + '</b><br/>'
out += 'workers: <b>' + str(uwsgi.numproc) + '</b><br/>'
yield 'workers: <b>' + str(uwsgi.numproc) + '</b><br/>'
out += '<table border="1">'
out += '<th>worker id</th><th>pid</th><th>requests</th><th>address space</th><th>rss</th>'
yield '<h2>dynamic options</h2>'
yield '<b>logging</b>: ' + str(uwsgi.get_option(0)) + '<br/>'
yield '<b>max_requests</b>: ' + str(uwsgi.getoption(1)) + '<br/>'
yield '<b>socket_timeout</b>: ' + str(uwsgi.getoption(2)) + '<br/>'
yield '<b>memory_debug</b>: ' + str(uwsgi.getoption(3)) + '<br/>'
yield '<b>master_interval</b>: ' + str(uwsgi.getoption(4)) + '<br/>'
yield '<b>harakiri</b>: ' + str(uwsgi.getoption(5)) + '<br/>'
yield '<b>cgi_mode</b>: ' + str(uwsgi.get_option(6)) + '<br/>'
yield '<b>threads</b>: ' + str(uwsgi.get_option(7)) + '<br/>'
yield '<b>process_reaper</b>: ' + str(uwsgi.get_option(8)) + '<br/>'
yield '<table border="1">'
yield '<th>worker id</th><th>pid</th><th>in request</th><th>requests</th><th>running time</th><th>address space</th><th>rss</th>'
workers = uwsgi.workers();
for w in workers:
print w
if w is not None:
out += '<tr><td>'+ str(w['id']) +'</td><td>' + str(w['pid']) + '</td><td>' + str(w['requests']) + '</td><td>' + str(w['vsz']) + '</td><td>' + str(w['rss']) + '</td></tr>'
out += '</table>'
yield '<h2>workers</h2>'
yield out
print "FATTOfattoFATTO"
for w in workers:
#print w
#print w['running_time']
if w is not None:
yield '<tr><td>'+ str(w['id']) +'</td><td>' + str(w['pid']) + '</td><td>' + str(w['pid']) + '</td><td>' + str(w['requests']) + '</td><td>' + str(w['running_time']) + '</td><td>' + str(w['vsz']) + '</td><td>' + str(w['rss']) + '</td></tr>'
print w
yield '</table>'
#yield out
#print "FATTOfattoFATTO"
def remotemako(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
@@ -162,7 +183,7 @@ uwsgi.fastfuncs.insert(17, djangohomepage)
#djangoapp = django.core.handlers.wsgi.WSGIHandler()
#applications = { '/':django.core.handlers.wsgi.WSGIHandler() }
uwsgi.applications = { '/':reload }
uwsgi.applications = { '/':reload, '/pippo':reload }
print uwsgi.applications
print uwsgi.applist
View File
+6
View File
@@ -0,0 +1,6 @@
import time
def application(env, start_response):
start_response( '200 OK', [ ('Content-Type','text/html') ])
for i in range(1,1000):
yield "<h1>%s at %s</h1>" % (i, str(time.time()))
+15
View File
@@ -0,0 +1,15 @@
import uwsgi
import time
def application(env, start_response):
counter = 0
start_response( '200 OK', [ ('Content-Type','text/html') ])
start_time = time.time()
for i in range(1,100000):
uwsgi.green_schedule()
# print every 100
if i % 100 == 0:
yield "<h1>%d</h1>\n" % i
counter = counter + i
yield "<h1>%d cycles after %d</h1>\n" % (counter, time.time() - start_time)
+14
View File
@@ -0,0 +1,14 @@
import time
import stackless
def application(env, start_response):
start_response( '200 OK', [ ('Content-Type','text/html') ])
#print env
for i in range(1,100000):
#print i
yield "<h1>%s at %s</h1>\n" % (i, str(time.time()))
#schedule every 2
if i % 2 == 0:
stackless.schedule()
print "DONE AT %d" % i
+17
View File
@@ -0,0 +1,17 @@
import sys
import mimetypes
basedir = sys.argv[1]
mimetypes.init()
def application(environ, start_response):
filename = basedir + environ['PATH_INFO']
(content_type, encoding) = mimetypes.guess_type(filename)
if not content_type:
content_type = 'text/plain'
start_response('200 OK', [('Content-Type', content_type)])
fd = open(filename,'r')
yield environ['wsgi.file_wrapper'](fd, 32*1024)
+43
View File
@@ -0,0 +1,43 @@
import socket
import select
import errno
def send_request(env, client):
client.setblocking(1)
client.send(b"GET /intl/it_it/images/logo.gif HTTP/1.0\r\n")
client.send(b"Host: www.google.it\r\n\r\n")
while 1:
yield env['x-wsgiorg.fdevent.readable'](client.fileno(), 10)
buf = client.recv(4096)
if len(buf) == 0:
break
else:
yield buf
def application(env, start_response):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
#env['x-wsgiorg.fdevent.readable'] = lambda fd,t: ""
#env['x-wsgiorg.fdevent.writable'] = lambda fd,t: ""
#yield ""
c = s.connect_ex(('www.google.it', 80))
if c == errno.EINPROGRESS:
yield env['x-wsgiorg.fdevent.writable'](s.fileno(), 10)
for r in send_request(env, s):
yield r
elif c == errno.EISCONN:
for r in send_request(env, s):
yield r
else:
start_response( '500 Internal Server Error', [ ('Content-Type', 'text/html')])
yield "Internal Server Error"
s.close()
+41
View File
@@ -0,0 +1,41 @@
import uwsgi
import socket
import errno
def send_request(env, client):
client.setblocking(1)
client.send(b"GET /intl/it_it/images/logo.gif HTTP/1.0\r\n")
client.send(b"Host: www.google.it\r\n\r\n")
uwsgi.green_schedule()
while 1:
uwsgi.green_wait_fdread(client.fileno(), 10)
buf = client.recv(4096)
if len(buf) == 0:
break
else:
yield buf
def application(env, start_response):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
c = s.connect_ex(('74.125.77.104', 80))
if c == errno.EINPROGRESS:
uwsgi.green_wait_fdwrite(s.fileno(), 10)
for r in send_request(env, s):
yield r
elif c == errno.EISCONN:
for r in send_request(env, s):
yield r
else:
uwsgi.green_schedule()
start_response( '500 Internal Server Error', [ ('Content-Type', 'text/html')])
yield "Internal Server Error"
s.close()
+19
View File
@@ -0,0 +1,19 @@
import uwsgi
from mako.template import Template
import time
def application(env, start_response):
start_response( '200 OK', [ ('Content-Type','text/html') ])
mytemplate = Template("<h1>I am Mako at ${thetime}</h1>")
uwsgi.green_schedule()
yield mytemplate.render(thetime = time.time() )
for i in range(1, 100):
mytemplate = Template("Iteration ${thei} at ${thetime}<br/>")
uwsgi.green_schedule()
yield mytemplate.render(thei = i, thetime = time.time() )
+45
View File
@@ -0,0 +1,45 @@
import uwsgi
import psycopg2
def ugreen_wait_callback(conn, timeout=-1):
"""A wait callback useful to allow uWSGI/uGreen to work with Psycopg."""
while True:
state = conn.poll()
if state == psycopg2.extensions.POLL_OK:
break
elif state == psycopg2.extensions.POLL_READ:
uwsgi.green_wait_fdread(conn.fileno())
elif state == psycopg2.extensions.POLL_WRITE:
uwsgi.green_wait_fdwrite(conn.fileno())
else:
raise Exception("Unexpected result from poll: %r", state)
# set the wait callback
psycopg2.extensions.set_wait_callback(ugreen_wait_callback)
def application(env, start_response):
start_response('200 Ok', [('Content-type', 'text/html')])
# connect
conn = psycopg2.connect("dbname=prova user=postgres")
# get cursor
curs = conn.cursor()
yield "<table>"
# run query
curs.execute("SELECT * FROM tests")
while True:
row = curs.fetchone()
if not row: break
yield "<tr><td>%s</td></tr>" % str(row)
yield "</table>"
conn.close()
+50
View File
@@ -0,0 +1,50 @@
import uwsgi
import psycopg2
def async_wait(conn):
# conn can be a connection or a cursor
if not hasattr(conn, 'poll'):
conn = conn.connection
# interesting part: suspend until ready
while True:
state = conn.poll()
if state == psycopg2.extensions.POLL_OK:
break
elif state == psycopg2.extensions.POLL_READ:
uwsgi.green_wait_fdread(conn.fileno())
elif state == psycopg2.extensions.POLL_WRITE:
uwsgi.green_wait_fdwrite(conn.fileno())
else:
raise Exception("Unexpected result from poll: %r", state)
def application(env, start_response):
start_response('200 Ok', [('Content-type', 'text/html')])
conn = psycopg2.connect("dbname=prova user=postgres", async=True)
# suspend until connection
async_wait(conn)
curs = conn.cursor()
yield "<table>"
curs.execute("SELECT * FROM tests")
# suspend until result
async_wait(curs)
while True:
row = curs.fetchone()
if not row: break
yield "<tr><td>%s</td></tr>" % str(row)
yield "</table>"
conn.close()
+9
View File
@@ -0,0 +1,9 @@
import uwsgi
sleepvalue = 5 ;
def application(env, start_response):
start_response('200 Ok', [('Content-type', 'text/html')])
yield uwsgi.async_sleep(sleepvalue)
#print "TIMEOUT: ", env['x-wsgiorg.fdevent.timeout']
yield "<h1>Hello World after %d seconds</h1>" % sleepvalue
+14
View File
@@ -0,0 +1,14 @@
import uwsgi
import time
def application(env, start_response):
sleepvalue = 5 ;
if env.has_key('QUERY_STRING'):
if env['QUERY_STRING'] != '':
sleepvalue = int(env['QUERY_STRING'])
start_response('200 Ok', [('Content-type', 'text/html')])
start_at = time.time()
uwsgi.green_sleep(sleepvalue)
#print "TIMEOUT: ", env['x-wsgiorg.fdevent.timeout']
yield "<h1>Hello World after %s seconds</h1>" % str(time.time() - start_at)
+20
View File
@@ -0,0 +1,20 @@
import sys
content_type = 'image/png'
filename = 'logo_uWSGI.png'
try:
filename = sys.argv[1]
except:
pass
try:
content_type = sys.argv[2]
except:
pass
def application(environ, start_response):
start_response('200 OK', [('Content-Type', content_type)])
fd = open(filename,'r')
yield environ['wsgi.file_wrapper'](fd, 32*1024)
+456
View File
@@ -0,0 +1,456 @@
#ifdef UWSGI_UGREEN
/* uGreen -> uWSGI green threads */
#include "uwsgi.h"
#define UGREEN_DEFAULT_STACKSIZE 256*1024
extern struct uwsgi_server uwsgi;
void u_green_write_all(struct uwsgi_server *uwsgi, char *data, size_t len) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
ssize_t rlen ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
uwsgi_error("write()");
// mark core as plagued
wsgi_req->async_plagued = 1 ;
}
else {
wsgi_req->response_size += rlen ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
void u_green_unpause_all(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
wsgi_req->async_timeout = 0;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
static int u_green_blocking(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status != UWSGI_ACCEPTING && wsgi_req->async_status != UWSGI_PAUSED && wsgi_req->async_waiting_fd == -1 && !wsgi_req->async_timeout) {
return 0 ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return -1 ;
}
inline static void u_green_schedule_to_main(struct uwsgi_server *uwsgi, int async_id) {
int py_current_recursion_depth;
struct _frame* py_current_frame;
PyThreadState* tstate = PyThreadState_GET();
py_current_recursion_depth = tstate->recursion_depth;
py_current_frame = tstate->frame;
swapcontext(uwsgi->ugreen_contexts[async_id], &uwsgi->ugreenmain);
tstate = PyThreadState_GET();
tstate->recursion_depth = py_current_recursion_depth;
tstate->frame = py_current_frame ;
}
inline static void u_green_schedule_to_req(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int py_current_recursion_depth;
struct _frame* py_current_frame;
PyThreadState* tstate = PyThreadState_GET();
py_current_recursion_depth = tstate->recursion_depth;
py_current_frame = tstate->frame;
uwsgi->wsgi_req = wsgi_req;
wsgi_req->async_switches++;
swapcontext(&uwsgi->ugreenmain, uwsgi->ugreen_contexts[wsgi_req->async_id] );
tstate = PyThreadState_GET();
tstate->recursion_depth = py_current_recursion_depth;
tstate->frame = py_current_frame ;
}
static void u_green_wait_for_fd(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, int fd, int etype, int timeout) {
if (fd < 0) return;
if (async_add(uwsgi->async_queue, fd, etype)) return ;
wsgi_req->async_waiting_fd = fd ;
wsgi_req->async_waiting_fd_type = etype;
wsgi_req->async_timeout = time(NULL) + timeout ;
u_green_schedule_to_main(uwsgi, wsgi_req->async_id);
async_del(uwsgi->async_queue, wsgi_req->async_waiting_fd, wsgi_req->async_waiting_fd_type);
wsgi_req->async_waiting_fd = -1;
wsgi_req->async_timeout = 0 ;
}
PyObject *py_uwsgi_green_pause(PyObject * self, PyObject * args) {
int timeout = 0 ;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "i", &timeout)) {
return NULL;
}
wsgi_req->async_status = UWSGI_PAUSED;
if (timeout) {
wsgi_req->async_timeout = time(NULL) + timeout ;
}
u_green_schedule_to_main(&uwsgi, wsgi_req->async_id);
// something bad happened during pause ?
if (wsgi_req->async_plagued) {
Py_INCREF(Py_None);
return Py_None;
}
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_green_write_all(PyObject * self, PyObject * args) {
char *data;
if (!PyArg_ParseTuple(args, "s", &data)) {
return NULL;
}
u_green_write_all(&uwsgi, data, strlen(data));
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_green_unpause_all(PyObject * self, PyObject * args) {
if (uwsgi.async > 1) {
u_green_unpause_all(&uwsgi);
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_green_schedule(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
u_green_schedule_to_main(&uwsgi, wsgi_req->async_id);
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_green_wait_fdread(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
int fd,timeout;
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}
u_green_wait_for_fd(&uwsgi, wsgi_req, fd, ASYNC_IN, timeout);
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_green_wait_fdwrite(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
int fd,timeout;
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}
u_green_wait_for_fd(&uwsgi, wsgi_req, fd, ASYNC_OUT, timeout);
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_green_sleep(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
int timeout;
if (!PyArg_ParseTuple(args, "i", &timeout)) {
return NULL;
}
wsgi_req->async_timeout = time(NULL) + timeout ;
u_green_schedule_to_main(&uwsgi, wsgi_req->async_id);
wsgi_req->async_timeout = 0 ;
Py_INCREF(Py_True);
return Py_True;
}
PyMethodDef uwsgi_green_methods[] = {
{"green_schedule", py_uwsgi_green_schedule, METH_VARARGS, ""},
{"green_wait_fdread", py_uwsgi_green_wait_fdread, METH_VARARGS, ""},
{"green_wait_fdwrite", py_uwsgi_green_wait_fdwrite, METH_VARARGS, ""},
{"green_sleep", py_uwsgi_green_sleep, METH_VARARGS, ""},
{"green_pause", py_uwsgi_green_pause, METH_VARARGS, ""},
{"green_unpause_all", py_uwsgi_green_unpause_all, METH_VARARGS, ""},
{"green_write_all", py_uwsgi_green_write_all, METH_VARARGS, ""},
{ NULL, NULL }
};
static struct wsgi_request *find_first_accepting_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_ACCEPTING) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return NULL ;
}
static void u_green_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, int async_id) {
for(;;) {
wsgi_req_setup(wsgi_req, async_id);
wsgi_req->async_status = UWSGI_ACCEPTING;
u_green_schedule_to_main(uwsgi, async_id);
if (wsgi_req_accept(uwsgi->serverfd, wsgi_req)) {
continue;
}
wsgi_req->async_status = UWSGI_OK;
u_green_schedule_to_main(uwsgi, async_id);
if (wsgi_req_recv(wsgi_req)) {
continue;
}
while(wsgi_req->async_status == UWSGI_AGAIN) {
u_green_schedule_to_main(uwsgi, async_id);
wsgi_req->async_status = (*uwsgi->shared->hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
}
u_green_schedule_to_main(uwsgi, async_id);
uwsgi_close_request(uwsgi, wsgi_req);
}
}
void u_green_init(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
size_t u_stack_size = UGREEN_DEFAULT_STACKSIZE ;
PyMethodDef *uwsgi_function;
if (uwsgi->ugreen_stackpages > 0) {
u_stack_size = uwsgi->ugreen_stackpages * uwsgi->page_size ;
}
uwsgi_log("initializing %d uGreen threads with stack size of %lu (%lu KB)\n", uwsgi->async, (unsigned long) u_stack_size, (unsigned long) u_stack_size/1024);
uwsgi->ugreen_contexts = malloc( sizeof(ucontext_t*) * uwsgi->async);
if (!uwsgi->ugreen_contexts) {
uwsgi_error("malloc()\n");
exit(1);
}
for(i=0;i<uwsgi->async;i++) {
uwsgi->ugreen_contexts[i] = malloc( sizeof(ucontext_t) );
if (!uwsgi->ugreen_contexts[i]) {
uwsgi_error("malloc()");
exit(1);
}
getcontext(uwsgi->ugreen_contexts[i]);
uwsgi->ugreen_contexts[i]->uc_stack.ss_sp = mmap(NULL, u_stack_size + (uwsgi->page_size*2) , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0) + uwsgi->page_size;
if (!uwsgi->ugreen_contexts[i]->uc_stack.ss_sp) {
uwsgi_error("mmap()");
exit(1);
}
// set guard pages for stack
if (mprotect(uwsgi->ugreen_contexts[i]->uc_stack.ss_sp - uwsgi->page_size, uwsgi->page_size, PROT_NONE)) {
uwsgi_error("mprotect()");
exit(1);
}
if (mprotect(uwsgi->ugreen_contexts[i]->uc_stack.ss_sp + u_stack_size, uwsgi->page_size, PROT_NONE)) {
uwsgi_error("mprotect()");
exit(1);
}
uwsgi->ugreen_contexts[i]->uc_stack.ss_size = u_stack_size ;
uwsgi->ugreen_contexts[i]->uc_link = NULL;
makecontext(uwsgi->ugreen_contexts[i], (void (*) (void)) &u_green_request, 3, uwsgi, wsgi_req, i);
wsgi_req->async_status = UWSGI_ACCEPTING;
wsgi_req->async_id = i;
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
for (uwsgi_function = uwsgi_green_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(uwsgi->embedded_dict, uwsgi_function->ml_name, func);
Py_DECREF(func);
}
}
void u_green_expire_timeouts(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t deadline = time(NULL);
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_status = UWSGI_AGAIN ;
wsgi_req->async_timeout = 0 ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
static int u_green_get_timeout(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
if (!uwsgi->async_running) return 0;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return 0;
}
void u_green_loop(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i, current = 0, timeout ;
while(uwsgi->workers[uwsgi->mywid].manage_next_request) {
uwsgi->async_running = u_green_blocking(uwsgi) ;
timeout = u_green_get_timeout(uwsgi);
uwsgi->async_nevents = async_wait(uwsgi->async_queue, uwsgi->async_events, uwsgi->async, uwsgi->async_running, timeout);
u_green_expire_timeouts(uwsgi);
if (uwsgi->async_nevents < 0) {
continue;
}
for(i=0; i<uwsgi->async_nevents;i++) {
if (uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
wsgi_req = find_first_accepting_wsgi_req(uwsgi);
if (!wsgi_req) goto cycle;
u_green_schedule_to_req(uwsgi, wsgi_req);
}
else {
wsgi_req = find_wsgi_req_by_fd(uwsgi, uwsgi->async_events[i].ASYNC_FD, -1);
if (wsgi_req) {
u_green_schedule_to_req(uwsgi, wsgi_req);
}
else {
async_del(uwsgi->async_queue, uwsgi->async_events[i].ASYNC_FD, uwsgi->async_events[i].ASYNC_EV);
}
}
}
cycle:
wsgi_req = find_wsgi_req_by_id(uwsgi, current) ;
if (wsgi_req->async_status != UWSGI_ACCEPTING && wsgi_req->async_status != UWSGI_PAUSED && wsgi_req->async_waiting_fd == -1 && !wsgi_req->async_timeout) {
u_green_schedule_to_req(uwsgi, wsgi_req);
}
current++;
if (current >= uwsgi->async) current = 0;
}
if (uwsgi->workers[uwsgi->mywid].manage_next_request == 0) {
reload_me();
}
else {
goodbye_cruel_world();
}
// never here
}
#endif
Executable
+45
View File
@@ -0,0 +1,45 @@
#!./uwsgi
import uwsgi
from bottle import route, default_app, request, response, redirect
@route('/')
def chat():
return """<iframe src="/recv"></iframe>
<iframe src="/sender"></iframe>"""
@route('/sender')
def sender():
return """<form method="GET" action="/send">
<textarea name="message"></textarea><br/>
<input type="submit" value="send" />
</form>"""
@route('/recv')
def recv():
response.header['Transfer-Encoding'] = 'chunked'
# this will flush headers
yield ""
running = True
while running:
# this will put the core in pause (for max 10 seconds) and remove it from the sched queue, so the /send can write to its socket
if not uwsgi.green_pause(10):
running = False
# this will maintain the connection opened if no data arrives
yield "<span/>"
@route('/send')
def send():
# this will write to all the core in PAUSED state
uwsgi.green_write_all(request.GET['message'] + "<br/>")
# this will unpause all the paused cores, so they will be re-inserted in the sched queue
uwsgi.green_unpause_all()
redirect('/sender')
application = default_app()
+36 -36
View File
@@ -1,50 +1,50 @@
/* taken from http://wiki.unbit.it/UnbitKernel */
struct uidsec_struct {
/* network limits */
unsigned short ipv4_tcp_port;
unsigned short ipv4_udp_port;
unsigned short ipv4_tcp_control_port;
/* network limits */
unsigned short ipv4_tcp_port;
unsigned short ipv4_udp_port;
unsigned short ipv4_tcp_control_port;
int ipv4_tcp_socket_protection;
unsigned long long ipv4_firewall_mask;
int ipv4_tcp_socket_protection;
unsigned long long ipv4_firewall_mask;
/* limits */
int fs_readonly;
/* limits */
int fs_readonly;
/* process markers */
int domain_id;
int fcgi_id;
int scgi_id;
int apps_id;
int wapp_id;
int ssh_id;
int cron_id;
/* process markers */
int domain_id;
int fcgi_id;
int scgi_id;
int apps_id;
int wapp_id;
int ssh_id;
int cron_id;
/* thread ?*/
int cloned_vm;
/* thread ? */
int cloned_vm;
/* process limit */
int max_dom_proc;
int max_apps_proc;
int max_apps_thread;
int max_ssh_proc;
int max_cron_proc;
/* process limit */
int max_dom_proc;
int max_apps_proc;
int max_apps_thread;
int max_ssh_proc;
int max_cron_proc;
/* misc */
int control_uid;
int listen_backlog;
int errors ;
/* misc */
int control_uid;
int listen_backlog;
int errors;
/* counters */
int accept_cnt ;
int accept_last;
/* counters */
int accept_cnt;
int accept_last;
int fork_cnt ;
int fork_last;
int fork_cnt;
int fork_last;
unsigned long long bio_read;
unsigned long long bio_write;
unsigned long long bio_read;
unsigned long long bio_write;
int memory_errors;
int memory_errors;
};
-403
View File
@@ -1,403 +0,0 @@
# Copyright 2009 Unbit S.a.s. <info@unbit.it>
# see the COPYRIGHT file
$stdout.sync = true
options = {}
if Process.uid == 0
puts "Never run uRack as root !!!"
exit
end
$stderr.puts "[#{Time.new}] starting uRack"
def human_round(float)
(float * (10 ** 2)).round / (10 ** 2).to_f
end
unless ENV.has_key?('UNBIT_RACK_PATH')
if File.exists?("#{ARGV.last}/config/environment.rb")
RAILS_ROOT = String.new(ARGV.last)
else
RAILS_ROOT = String.new(Dir.getwd)
end
options[:sockname] = '/tmp/uwsgi.sock'
options[:sock_chmod] = 0
options[:stderr_logfile] = nil
else
$domain = ARGV.last.gsub('[','').gsub(']','')
$unbit_log_base = "[uRack/Unbit on #{$domain}]"
RAILS_ROOT = String.new(ENV['UNBIT_RACK_PATH'])
options[:unbit] = true
$limit_as = human_round(Process.getrlimit(Process::RLIMIT_AS)[1].to_f/1024/1024)
puts "#{$unbit_log_base} process address space limit is #{$limit_as} MB"
$uidsec_size = syscall(357,0,0)
puts "#{$unbit_log_base} need #{$uidsec_size} bytes to store uidsec_struct..."
$uidsec = '1' * $uidsec_size
puts "#{$unbit_log_base} uidsec_struct allocated."
end
options[:environment] = (ENV['RAILS_ENV'] || "development").dup
options[:processes] = 1
options[:serve_file] = nil
options[:max_input_size] = 8
options[:unbit_debug] = false
options[:master] = true
options[:gc_freq] = nil
require 'optparse'
ARGV.clone.options do |opts|
opts.on('-s', '--socket=socket', String, 'Unix socket path.', 'Default: /tmp/uwsgi.sock') { |v|
options[:sockname] = v
}
opts.on('-C','--chmod','chmod to 666 the unix socket.') {
options[:sock_chmod] = true
}
opts.on('-F','--serve-file','serve static file.') {
options[:serve_file] = true
}
opts.on('-p', '--processes=processes', Integer, 'Number of processes to spawn.', 'Default: 1') {|v|
options[:processes] = v
}
opts.on('-g', '--gc-freq=requests', Integer, 'Number of requests between GC.', 'Default: 1') {|v|
options[:gc_freq] = v
}
opts.on('-d', '--daemon=logfile', 'Put processes in background.', 'Default: all processes stay in foreground') {|v|
options[:stderr_logfile] = v
}
opts.on('-i', '--max-input-size=size', 'Max POST data size (in Kbyte). Bigger data goes into a temporary file.', 'Default: 8') {|v|
options[:max_input_size] = v
}
opts.on('-D', '--unbit-debug', 'Enable debug-level logging.', 'Default: disabled') {|v|
options[:unbit_debug] = true
}
opts.on('-M', '--master-process', 'Enable the master process manager.', 'Default: disabled') {|v|
options[:master] = true
}
opts.on("-e", '--environment=name', String, 'Specifies the environment to run this server under (test/development/production).','Default: development') { |v|
options[:environment] = v
}
opts.separator ""
opts.parse!
end
puts "[#{Time.new}] uRack: loading app [#{RAILS_ROOT}]..."
starttime = Time.now
require RAILS_ROOT + "/config/environment"
options[:app_name] = RAILS_ROOT
require 'socket'
require 'rubygems'
require 'rack'
require 'rack/utils'
require 'rack/content_length'
module Rack
module Handler
class Unbit
class Tempfile < ::Tempfile
def _close
@tmpfile.close if @tmpfile
@data[1] = nil if @data
@tmpfile = nil
end
end
def self.run(app, options={})
# parse the socket options
# note: on unbit we use the stdin as communication socket
server = nil
master_pid = Process.pid
options[:processes] ||= 1
unless options[:unbit]
begin
::File.delete(options[:sockname])
rescue
end
server = UNIXServer.new(options[:sockname])
if options[:sock_chmod]
::File.chmod(0666, options[:sockname])
end
if options[:stderr_logfile]
cwd = Dir.getwd
Process.daemon
Dir.chdir(cwd)
$stdout.reopen(options[:stderr_logfile],'a')
$stderr.reopen(options[:stderr_logfile],'a')
# log files need to be unbuffered !
$stdout.sync = true
$stderr.sync = true
# pid is changed after the .daemon call
master_pid = Process.pid
end
else
server = UNIXServer.for_fd($stdin.fileno)
end
$workers = Array.new
if options[:master]
$0 = "uRack #{ARGV.last}"
pid = Process.fork
if pid.to_i > 0
puts "[#{Time.new}] uRack: spawned rack worker 1 (pid: #{pid})"
$workers[1] = pid ;
end
end
# the check on master pid is necessary
# without it the first worker will execute this part
if options[:processes] > 1 and Process.pid == master_pid
for p in 2..options[:processes]
pid = Process.fork
break if pid.to_i == 0
puts "[#{Time.new}] uRack: spawned rack worker #{p} (pid: #{pid})"
$workers[p] = pid ;
end
end
# am i the master ?
if options[:master] and Process.pid == master_pid
Signal.trap('TERM') do
puts "[#{Time.new}] uRack: gracefully killing uRack"
for wid in 1..options[:processes]
Process.kill('TERM', $workers[wid]);
end
exit 0;
end
Signal.trap('QUIT') do
puts "[#{Time.new}] uRack: brutally killing uRack"
for wid in 1..options[:processes]
Process.kill('INT', $workers[wid]);
end
exit 0;
end
puts "[#{Time.new}] uRack: the master process manager is alive."
while 1
pid = Process.waitpid
puts "[#{Time.new}] uRack: worker died ! (pid: #{pid})"
newpid = Process.fork
break if newpid.to_i == 0
puts "[#{Time.new}] uRack: respawned rack worker (pid: #{newpid})"
for wid in 1..options[:processes]
if $workers[wid] == pid
$workers[wid] = newpid
break
end
end
end
end
if Process.pid != master_pid
$0 = $0.gsub(/^uRack/,'urack')
Signal.trap("TERM") do
puts "[#{Time.new}] uRack: grecefully killing process #{Process.pid}..."
if $in_request == 0
puts "[#{Time.new}] uRack: goodbye to process #{Process.pid}"
exit 0
end
$manage_next_request = nil
end
Signal.trap('INT') do
puts "[#{Time.new}] uRack: brutally killing process #{Process.pid}..."
exit 0
end
Signal.trap('PIPE') do
puts "[#{Time.new}] uRack: the webserver (or the client) has closed the connection with process #{Process.pid} !!!"
end
end
max_input_size = options[:max_input_size].to_i * 1024
requests = 0
null_post = StringIO.new('')
options[:app_name] ||= Dir.getwd
app = Rack::ContentLength.new(app)
$manage_next_request = true
if options[:gc_freq].to_i > 1
GC.disable
end
while $manage_next_request
$in_request = 0
client = server.accept
$in_request = 1
timed_out = false
ver, size, arg1 = client.recvfrom(4)[0].unpack('CvC')
vars = client.recvfrom(size)[0]
env = Hash.new
i = 0
while i < size
kl = vars[i, 2].unpack('v')[0]
i = i + 2
key = vars[i, kl]
i = i + kl
vl = vars[i, 2].unpack('v')[0]
i = i + 2
value = vars[i, vl]
i = i + vl
env[key] = value
end
rack_input = null_post
env.delete 'CONTENT_LENGTH' if env['CONTENT_LENGTH'] == ''
if env['CONTENT_LENGTH'].to_i > 0
cl = env['CONTENT_LENGTH'].to_i
if cl <= max_input_size
poststr = ''
while poststr.size < cl
poststr = poststr + client.recvfrom(cl-poststr.size)[0] ;
end
rack_input = StringIO.new(poststr)
else
rack_input = Tempfile.new('UnbitRack')
rack_input.chmod(0000)
bytes_read = 0
while bytes_read < cl
buf = client.recvfrom(4096)[0]
rack_input.write(buf)
bytes_read += buf.size
end
rack_input.rewind
end
end
env["SCRIPT_NAME"] = ""
env.update({"rack.version" => [0,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => "http"
})
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
begin
#puts env.inspect
$start_of_request = Time.new
status, headers, body = app.call(env)
$speed = Time.new - $start_of_request
client.print "#{env["HTTP_VERSION"]} #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}\r\n"
headers.each {|k,vs|
vs.split("\n").each { |v|
client.print "#{k}: #{v}\r\n"
}
}
client.print "\r\n"
client.flush
body.each {|part|
client.print part
client.flush
}
rescue Errno::EPIPE
puts "[#{Time.new}] uRack: the webserver (or the client) has closed the connection with process #{Process.pid} !!!"
timed_out = true
ensure
if rack_input.respond_to? :unlink
rack_input.unlink
end
unless rack_input.closed?
rack_input.close
end
client.close
requests = requests+1
# logging
begin
# the syscall 356 is only available on unbit kernels
# other systems need to use the proc file way
# stat = ::File.open('/proc/self/stat', 'r')
# procline = stat.readline
# statd = procline.split /\s+/
# stat.close
$stderr.puts "[#{Time.new}] uRack: [#{options[:app_name]}] req: #{requests} ip: #{env['REMOTE_ADDR']} pid: #{Process.pid} as: #{human_round(syscall(356).to_f/1024/1024)} MB => #{env['REQUEST_METHOD']} #{env['REQUEST_URI']} in #{$speed} secs [#{status}]#{' TIMED OUT !!!' if timed_out}"
rescue
$stderr.puts "[#{Time.new}] uRack: [#{options[:app_name]}] req: #{requests} unable to get /proc/self/stat or syscall 356"
end
if syscall(357, $uidsec, 0) == $uidsec_size
if $uidsec[120..123].unpack('i')[0] > 0
$stderr.puts "[#{Time.new}] uRack: found a memory allocation error for request #{requests} (pid: #{Process.pid}). Better to kill myself..."
$manage_next_request = nil
end
end
$uidsec = '1' * $uidsec_size
if options[:unbit_debug]
current_as = human_round( (syscall(356).to_f/1024/1024) - $last_as )
$stderr.puts "#{$unbit_log_base} resource status after request #{requests}: AS for this request: #{current_as} MB | OBJ for this request: #{ObjectSpace.each_object {} - $last_obj} | OBJ total: #{ObjectSpace.each_object {}}"
$last_as = human_round(syscall(356).to_f/1024/1024) ;
$last_obj = ObjectSpace.each_object {}
end
if options[:gc_freq].to_i > 1
if requests % options[:gc_freq].to_i == 0
$stderr.puts "[#{Time.new}] uRack: [#{options[:app_name]}] calling GC for pid #{Process.pid} after #{requests} requests."
GC.enable ; GC.start ; GC.disable
end
end
end
end
puts "[#{Time.new}] uRack: goodbye to process #{Process.pid}"
end
end
end
end
server = Rack::Handler.get('Unbit')
app = Rack::Builder.new {
if options[:serve_file]
puts "[#{Time.new}] uRack: file serving enabled."
use Rails::Rack::Static
end
if ActionController.const_defined?(:Dispatcher) && (ActionController::Dispatcher.instance_methods.include?(:call) || ActionController::Dispatcher.instance_methods.include?("call"))
run ActionController::Dispatcher.new
else
require 'thin'
run Rack::Adapter::Rails.new(:environment => ENV['RAILS_ENV'])
end
}.to_app
if options[:unbit]
$after_spawn_used_as = human_round(syscall(356).to_f/1024/1024)
$stderr.puts "#{$unbit_log_base} now you have #{$limit_as-$after_spawn_used_as} MB of address space available (used #{$after_spawn_used_as}MB after app startup)"
end
secs = Time.now-starttime
puts "[#{Time.new}] uRack: ready to serve requests after #{secs.to_i} secs (pid: #{Process.pid})"
if options[:unbit_debug]
$last_as = $after_spawn_used_as ;
$last_obj = ObjectSpace.each_object {}
end
server.run(app, options)
+395 -68
View File
@@ -1,20 +1,39 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef __BIG_ENDIAN__
uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
uint32_t uwsgi_swap32(uint32_t x) {
x = ( (x<<8) & 0xFF00FF00 ) | ( (x>>8) & 0x00FF00FF );
return (x>>16) | (x<<16);
}
// thanks to ffmpeg project for this idea :P
uint64_t uwsgi_swap64(uint64_t x) {
union {
uint64_t ll;
uint32_t l[2];
} w, r;
w.ll = x;
r.l[0] = uwsgi_swap32(w.l[1]);
r.l[1] = uwsgi_swap32(w.l[0]);
return r.ll;
}
#endif
void set_harakiri(int sec) {
if (uwsgi.workers) {
if (uwsgi.master_process) {
if (sec == 0) {
uwsgi.workers[uwsgi.mywid].harakiri = 0 ;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
}
else {
uwsgi.workers[uwsgi.mywid].harakiri = time(NULL) + sec ;
uwsgi.workers[uwsgi.mywid].harakiri = time(NULL) + sec;
}
}
else {
@@ -25,76 +44,114 @@ void set_harakiri(int sec) {
#ifndef UNBIT
void daemonize(char *logfile) {
pid_t pid;
int fd, fdin;
pid_t pid;
int fd, fdin;
#ifdef UWSGI_UDP
char *udp_port;
struct sockaddr_in udp_addr;
#endif
pid = fork();
if (pid < 0) {
perror("fork()");
exit(1) ;
}
if (pid != 0) {
exit(0);
}
if (setsid() < 0) {
perror("setsid()");
exit(1) ;
}
pid = fork();
if (pid < 0) {
uwsgi_error("fork()");
exit(1);
}
if (pid != 0) {
exit(0);
}
if (setsid() < 0) {
uwsgi_error("setsid()");
exit(1);
}
/* refork... */
pid = fork();
if (pid < 0) {
perror("fork()");
exit(1) ;
}
if (pid != 0) {
exit(0);
}
/* refork... */
pid = fork();
if (pid < 0) {
uwsgi_error("fork()");
exit(1);
}
if (pid != 0) {
exit(0);
}
umask(0);
umask(0);
/*if (chdir("/") != 0) {
perror("chdir()");
exit(1);
}*/
/*if (chdir("/") != 0) {
uwsgi_error("chdir()");
exit(1);
} */
fdin = open("/dev/null", O_RDWR);
if (fdin < 0) {
perror("open()");
exit(1);
}
fd = open(logfile, O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP );
if (fd < 0) {
perror("open()");
exit(1);
}
/* stdin */
if (dup2(fdin,0) < 0) {
perror("dup2()");
exit(1);
}
fdin = open("/dev/null", O_RDWR);
if (fdin < 0) {
uwsgi_error("open()");
exit(1);
}
#ifdef UWSGI_UDP
udp_port = strchr(logfile, ':');
if (udp_port) {
udp_port[0] = 0 ;
if ( !udp_port[1] || !logfile[0] ) {
uwsgi_log("invalid udp address\n");
exit(1);
}
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("socket()");
exit(1);
}
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
udp_addr.sin_family = AF_INET;
udp_addr.sin_port = htons(atoi(udp_port+1));
udp_addr.sin_addr.s_addr = inet_addr(logfile);
if (connect(fd, (const struct sockaddr *) &udp_addr, sizeof(struct sockaddr_in)) < 0) {
uwsgi_error("connect()");
exit(1);
}
}
else {
#endif
fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error("open()");
exit(1);
}
#ifdef UWSGI_UDP
}
#endif
/* stdin */
if (dup2(fdin, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
/* stdout */
if (dup2(fd,1) < 0) {
perror("dup2()");
exit(1);
}
if (dup2(fd, 1) < 0) {
uwsgi_error("dup2()");
exit(1);
}
/* stderr */
if (dup2(fd,2) < 0) {
perror("dup2()");
exit(1);
}
/* stderr */
if (dup2(fd, 2) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
close(fd);
}
@@ -102,32 +159,302 @@ void daemonize(char *logfile) {
#endif
char * uwsgi_get_cwd() {
char *uwsgi_get_cwd() {
int newsize = 256 ;
char *cwd ;
int newsize = 256;
char *cwd;
cwd = malloc(newsize);
if (cwd == NULL) {
perror("malloc()");
uwsgi_error("malloc()");
exit(1);
}
}
if (getcwd(cwd, newsize) == NULL) {
newsize = errno;
fprintf(stderr,"need a bigger buffer (%d bytes) for getcwd(). doing reallocation.\n", newsize);
uwsgi_log("need a bigger buffer (%d bytes) for getcwd(). doing reallocation.\n", newsize);
free(cwd);
cwd = malloc(newsize);
if (cwd == NULL) {
perror("malloc()");
uwsgi_error("malloc()");
exit(1);
}
}
if (getcwd(cwd, newsize) == NULL) {
perror("getcwd()");
uwsgi_error("getcwd()");
exit(1);
}
}
return cwd;
}
void internal_server_error(int fd, char *message) {
#ifndef UNBIT
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
#endif
uwsgi.wsgi_req->headers_size = write(fd, "HTTP/1.1 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 63);
#ifndef UNBIT
}
else {
uwsgi.wsgi_req->headers_size = write(fd, "Status: 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 62);
}
uwsgi.wsgi_req->header_cnt = 2;
#endif
uwsgi.wsgi_req->response_size = write(fd, "<h1>uWSGI Error</h1>", 20);
uwsgi.wsgi_req->response_size += write(fd, message, strlen(message));
}
void uwsgi_as_root() {
if (!getuid()) {
uwsgi_log("uWSGI running as root, you can use --uid/--gid/--chroot options\n");
if (uwsgi.chroot) {
uwsgi_log("chroot() to %s\n", uwsgi.chroot);
if (chroot(uwsgi.chroot)) {
uwsgi_error("chroot()");
exit(1);
}
#ifdef __linux__
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
}
#endif
}
if (uwsgi.gid) {
uwsgi_log("setgid() to %d\n", uwsgi.gid);
if (setgid(uwsgi.gid)) {
uwsgi_error("setgid()");
exit(1);
}
}
if (uwsgi.uid) {
uwsgi_log("setuid() to %d\n", uwsgi.uid);
if (setuid(uwsgi.uid)) {
uwsgi_error("setuid()");
exit(1);
}
}
if (!getuid()) {
uwsgi_log(" *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n");
}
}
else {
if (uwsgi.chroot) {
uwsgi_log("cannot chroot() as non-root user\n");
exit(1);
}
if (uwsgi.gid) {
uwsgi_log("cannot setgid() as non-root user\n");
exit(1);
}
if (uwsgi.uid) {
uwsgi_log("cannot setuid() as non-root user\n");
exit(1);
}
}
}
void uwsgi_close_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int waitpid_status ;
gettimeofday(&wsgi_req->end_of_request, NULL);
uwsgi->workers[uwsgi->mywid].running_time += (double) (((double) (wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec) - (double) (wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec)) / (double) 1000.0);
// get memory usage
if (uwsgi->shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1)
get_memusage();
// close the connection with the webserver
if (!wsgi_req->fd_closed) {
close(wsgi_req->poll.fd);
}
uwsgi->workers[0].requests++;
uwsgi->workers[uwsgi->mywid].requests++;
// after_request hook
(*uwsgi->shared->after_hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
// leave harakiri mode
if (uwsgi->workers[uwsgi->mywid].harakiri > 0) {
set_harakiri(0);
}
// defunct process reaper
if (uwsgi->shared->options[UWSGI_OPTION_REAPER] == 1) {
waitpid(-1, &waitpid_status, WNOHANG);
}
// reset request
memset(wsgi_req, 0, sizeof(struct wsgi_request));
if (uwsgi->shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi->workers[uwsgi->mywid].requests >= uwsgi->shared->options[UWSGI_OPTION_MAX_REQUESTS]) {
goodbye_cruel_world();
}
}
void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id) {
wsgi_req->poll.events = POLLIN;
wsgi_req->app_id = uwsgi.default_app;
wsgi_req->async_id = async_id;
#ifdef UWSGI_SENDFILE
wsgi_req->sendfile_fd = -1;
#endif
#ifdef UWSGI_ASYNC
wsgi_req->async_waiting_fd = -1;
#endif
wsgi_req->hvec = &uwsgi.async_hvec[wsgi_req->async_id];
wsgi_req->buffer = uwsgi.async_buf[wsgi_req->async_id];
}
int wsgi_req_recv(struct wsgi_request *wsgi_req) {
UWSGI_SET_IN_REQUEST;
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING]) gettimeofday(&wsgi_req->start_of_request, NULL);
if (!uwsgi_parse_response(&wsgi_req->poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) wsgi_req, wsgi_req->buffer)) {
return -1;
}
// enter harakiri mode
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
wsgi_req->async_status = (*uwsgi.shared->hooks[wsgi_req->uh.modifier1]) (&uwsgi, wsgi_req);
return 0;
}
int wsgi_req_accept(int fd, struct wsgi_request *wsgi_req) {
wsgi_req->poll.fd = accept(fd, (struct sockaddr *) &wsgi_req->c_addr, (socklen_t *) &wsgi_req->c_len);
if (wsgi_req->poll.fd < 0) {
uwsgi_error("accept()");
return -1;
}
return 0;
}
inline struct wsgi_request *current_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_req;
#ifdef UWSGI_STACKLESS
if (uwsgi->stackless && uwsgi->async >1) {
PyThreadState *ts = PyThreadState_GET();
wsgi_req = find_request_by_tasklet(ts->st.current);
}
#endif
return wsgi_req;
}
void sanitize_args(struct uwsgi_server *uwsgi) {
#ifdef UWSGI_PROFILER
if (uwsgi->enable_profiler) {
uwsgi_log("*** Profiler enabled, do not use it in production environment !!! ***\n");
uwsgi->async = 1;
}
#endif
#ifdef UWSGI_UGREEN
#ifdef UWSGI_THREADING
if (uwsgi->ugreen) {
if (uwsgi->has_threads) {
uwsgi_log("--- python threads will be disabled in uGreen mode ---\n");
uwsgi->has_threads = 0;
}
}
#endif
#endif
}
void env_to_arg(char *src, char *dst) {
int i;
for(i=0;i<strlen(src);i++) {
dst[i] = tolower(src[i]);
if (dst[i] == '_') {
dst[i] = '-';
}
}
dst[strlen(src)] = 0;
}
void parse_sys_envs(char **envs, struct option *long_options) {
struct option *lopt, *aopt;
char **uenvs = envs;
char *earg, *eq_pos ;
while(*uenvs) {
if (!strncmp(*uenvs, "UWSGI_", 6)) {
earg = malloc(strlen(*uenvs+6)+1);
if (!earg) {
uwsgi_error("malloc()");
exit(1);
}
env_to_arg(*uenvs+6, earg);
eq_pos = strchr(earg, '=');
if (!eq_pos) {
break;
}
eq_pos[0] = 0 ;
lopt = long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(earg, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
}
else {
if (eq_pos[1] != 0) {
manage_opt(aopt->val, eq_pos+1);
}
else {
manage_opt(aopt->val, NULL);
}
}
}
lopt++;
}
}
uenvs++;
}
}
//use this instead of fprintf to avoid buffering mess with udp logging
void uwsgi_log(const char *fmt, ...) {
va_list ap;
char logpkt[4096];
int rlen;
va_start (ap, fmt);
rlen = vsnprintf(logpkt, 4096, fmt, ap );
va_end(ap);
// do not check for errors
rlen = write(2, logpkt, rlen);
}
+2049 -1905
View File
File diff suppressed because it is too large Load Diff
+650 -161
View File
@@ -1,21 +1,43 @@
/* uWSGI */
/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs */
#define UWSGI_VERSION "0.9.5-dev"
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdarg.h>
// linux has not strlcpy
#ifdef __linux
#define strlcpy(x, y, z) strcpy(x, y)
#endif
#ifdef UWSGI_SCTP
#include <netinet/sctp.h>
#endif
#ifdef UWSGI_UGREEN
#include <ucontext.h>
#endif
#include <arpa/inet.h>
#include <sys/mman.h>
#include <sys/file.h>
#include <stdint.h>
#include <sys/wait.h>
#include <dlfcn.h>
#include <poll.h>
#include <sys/uio.h>
@@ -28,260 +50,565 @@
#include <sys/resource.h>
#ifndef UNBIT
#ifndef ROCK_SOLID
#include <getopt.h>
#endif
#endif
#ifdef __APPLE__
#include <libkern/OSAtomic.h>
#include <mach/task.h>
#include <mach/mach_init.h>
#include <libkern/OSAtomic.h>
#include <mach/task.h>
#include <mach/mach_init.h>
#endif
#ifdef UNBIT
#undef _XOPEN_SOURCE
#include "unbit.h"
#endif
#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
#endif
#ifdef __sun__
#undef _FILE_OFFSET_BITS
#define WAIT_ANY (-1)
#include <sys/filio.h>
#define PRIO_MAX 20
#endif
#define MAX_PYARGV 10
#include <sys/ioctl.h>
#ifdef __linux__
#include <sys/sendfile.h>
#include <sys/epoll.h>
#elif defined(__sun__)
#include <sys/devpoll.h>
#else
#include <sys/event.h>
#endif
#undef _XOPEN_SOURCE
#include <Python.h>
#ifdef UWSGI_STACKLESS
#include <stackless_api.h>
#endif
#if PY_MINOR_VERSION == 4 && PY_MAJOR_VERSION == 2
#define Py_ssize_t ssize_t
#endif
#if PY_MAJOR_VERSION > 2
#define PYTHREE
#endif
/* this value are taken from nginx */
#if defined(__apple__) || defined(__freebsd__)
#define UWSGI_LISTEN_QUEUE -1
#else
#define UWSGI_LISTEN_QUEUE 511
#endif
PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int);
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define MAX_CLUSTER_NODES 100
#define UWSGI_NODE_OK 0
#define UWSGI_NODE_FAILED 1
#define LONG_ARGS_PIDFILE 17001
#define LONG_ARGS_CHROOT 17002
#define LONG_ARGS_GID 17003
#define LONG_ARGS_UID 17004
#define LONG_ARGS_PYTHONPATH 17005
#define LONG_ARGS_PASTE 17006
#define LONG_ARGS_CHECK_INTERVAL 17007
#define LONG_ARGS_PYARGV 17008
#define LONG_ARGS_LIMIT_AS 17009
#define LONG_ARGS_UDP 17010
#define LONG_ARGS_WSGI_FILE 17011
#define LONG_ARGS_ERLANG 17012
#define LONG_ARGS_ERLANG_COOKIE 17013
#define LONG_ARGS_BINARY_PATH 17014
#define LONG_ARGS_PROXY 17015
#define LONG_ARGS_PROXY_NODE 17016
#define LONG_ARGS_PROXY_MAX_CONNECTIONS 17017
#define LONG_ARGS_VERSION 17018
#define LONG_ARGS_SNMP 17019
#define LONG_ARGS_SNMP_COMMUNITY 17020
#define LONG_ARGS_ASYNC 17021
#define LONG_ARGS_UGREEN_PAGES 17022
#define LONG_ARGS_FILE_CONFIG 17023
#define LONG_ARGS_MULTICAST 17024
#define UWSGI_OK 0
#define UWSGI_AGAIN 1
#define UWSGI_ACCEPTING 2
#define UWSGI_PAUSED 3
#define UWSGI_CLEAR_STATUS uwsgi.workers[uwsgi.mywid].status = 0
#define UWSGI_STATUS_IN_REQUEST 1 << 0
#define UWSGI_IS_IN_REQUEST uwsgi.workers[uwsgi.mywid].status & UWSGI_STATUS_IN_REQUEST
#define UWSGI_SET_IN_REQUEST uwsgi.workers[uwsgi.mywid].status |= UWSGI_STATUS_IN_REQUEST
#define UWSGI_UNSET_IN_REQUEST uwsgi.workers[uwsgi.mywid].status ^= UWSGI_STATUS_IN_REQUEST
#define UWSGI_STATUS_BLOCKING 1 << 1
#define UWSGI_IS_BLOCKING uwsgi.workers[uwsgi.mywid].status & UWSGI_STATUS_BLOCKING
#define UWSGI_SET_BLOCKING uwsgi.workers[uwsgi.mywid].status |= UWSGI_STATUS_BLOCKING
#define UWSGI_UNSET_BLOCKING uwsgi.workers[uwsgi.mywid].status ^= UWSGI_STATUS_BLOCKING
#define UWSGI_STATUS_LOCKING 1 << 2
#define UWSGI_IS_LOCKING uwsgi.workers[uwsgi.mywid].status & UWSGI_STATUS_LOCKING
#define UWSGI_SET_LOCKING uwsgi.workers[uwsgi.mywid].status |= UWSGI_STATUS_LOCKING
#define UWSGI_UNSET_LOCKING uwsgi.workers[uwsgi.mywid].status ^= UWSGI_STATUS_LOCKING
#define UWSGI_STATUS_ERLANGING 1 << 3
#define UWSGI_IS_ERLANGING uwsgi.workers[uwsgi.mywid].status & UWSGI_STATUS_ERLANGING
#define UWSGI_SET_ERLANGING uwsgi.workers[uwsgi.mywid].status |= UWSGI_STATUS_ERLANGING
#define UWSGI_UNSET_ERLANGING uwsgi.workers[uwsgi.mywid].status ^= UWSGI_STATUS_ERLANGING
#ifdef __linux__
#include <endian.h>
#elif __sun__
#include <sys/byteorder.h>
#ifdef _BIG_ENDIAN
#define __BIG_ENDIAN__ 1
#endif
#elif __apple__
#include <libkern/OSByteOrder.h>
#else
#include <machine/endian.h>
#endif
#define UWSGI_OPTION_LOGGING 0
#define UWSGI_OPTION_MAX_REQUESTS 1
#define UWSGI_OPTION_SOCKET_TIMEOUT 2
#define UWSGI_OPTION_MEMORY_DEBUG 3
#define UWSGI_OPTION_MASTER_INTERVAL 4
#define UWSGI_OPTION_HARAKIRI 5
#define UWSGI_OPTION_CGI_MODE 6
#define UWSGI_OPTION_THREADS 7
#define UWSGI_OPTION_REAPER 8
#ifdef UNBIT
#define UWSGI_MODIFIER_HT_S 1
#define UWSGI_MODIFIER_HT_M 2
#define UWSGI_MODIFIER_HT_H 3
#undef _XOPEN_SOURCE
#endif
#define UWSGI_MODIFIER_SPOOL_REQUEST 17
#define UWSGI_MODIFIER_FASTFUNC 26
#define UWSGI_MODIFIER_MANAGE_PATH_INFO 30
#define UWSGI_MODIFIER_MESSAGE 31
#define UWSGI_MODIFIER_MESSAGE_ARRAY 32
#define UWSGI_MODIFIER_MESSAGE_MARSHAL 33
#define UWSGI_MODIFIER_PING 100
#define UWSGI_MODIFIER_ADMIN_REQUEST 10
#define UWSGI_MODIFIER_SPOOL_REQUEST 17
#define UWSGI_MODIFIER_FASTFUNC 26
#define UWSGI_MODIFIER_MANAGE_PATH_INFO 30
#define UWSGI_MODIFIER_MESSAGE 31
#define UWSGI_MODIFIER_MESSAGE_ARRAY 32
#define UWSGI_MODIFIER_MESSAGE_MARSHAL 33
#define UWSGI_MODIFIER_MULTICAST_ANNOUNCE 73
#define UWSGI_MODIFIER_MULTICAST 74
#define UWSGI_MODIFIER_PING 100
#define UWSGI_MODIFIER_RESPONSE 255
#ifdef PYTHREE
#define PyInt_FromLong PyLong_FromLong
#define PyInt_AsLong PyLong_AsLong
#define PyInt_Check PyLong_Check
#define PyString_Check PyUnicode_Check
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#define PyString_FromFormat PyUnicode_FromFormat
#define PyString_FromString PyUnicode_FromString
#define PyString_Size PyUnicode_GET_DATA_SIZE
#define PyString_AsString (char *) PyUnicode_AS_UNICODE
#define PyFile_FromFile(A,B,C,D) PyFile_FromFd(fileno((A)), (B), (C), -1, NULL, NULL, NULL, 0)
#define PyInt_FromLong PyLong_FromLong
#define PyInt_AsLong PyLong_AsLong
#define PyInt_Check PyLong_Check
#define PyString_Check PyUnicode_Check
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#define PyString_FromFormat PyUnicode_FromFormat
#define PyString_FromString PyUnicode_FromString
#define PyString_Size PyUnicode_GET_DATA_SIZE
#define PyString_AsString (char *) PyUnicode_AS_UNICODE
#define PyFile_FromFile(A,B,C,D) PyFile_FromFd(fileno((A)), (B), (C), -1, NULL, NULL, NULL, 0)
#endif
#define NL_SIZE 2
#define H_SEP_SIZE 2
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#define UWSGI_RELOAD_CODE 17
#define UWSGI_END_CODE 30
#define MAX_VARS 64
struct uwsgi_app {
#ifndef ROCK_SOLID
PyThreadState *interpreter ;
PyObject *pymain_dict ;
PyThreadState *interpreter;
PyObject *pymain_dict;
PyObject *wsgi_callable;
#ifdef UWSGI_ASYNC
PyObject **wsgi_args;
PyObject **wsgi_environ;
#else
PyObject *wsgi_args;
PyObject *wsgi_environ;
#endif
PyObject *wsgi_harakiri;
PyObject *wsgi_sendfile;
PyObject *wsgi_cprofile_run;
#ifdef UWSGI_ASYNC
PyObject *wsgi_eventfd_read;
PyObject *wsgi_eventfd_write;
#endif
#ifdef ROCK_SOLID
PyObject *wsgi_module;
PyObject *wsgi_dict;
#endif
PyObject *wsgi_callable ;
PyObject *wsgi_environ ;
PyObject *wsgi_args;
PyObject *wsgi_harakiri;
#ifndef ROCK_SOLID
PyObject *wsgi_sendfile;
PyObject *wsgi_cprofile_run;
int requests ;
#endif
int requests;
};
struct __attribute__ ((packed)) uwsgi_header {
uint8_t modifier1;
uint16_t pktsize;
uint8_t modifier2;
};
struct wsgi_request {
struct uwsgi_header uh;
// temporary attr
int app_id;
struct pollfd poll;
// this is big enough to contain sockaddr_in
struct sockaddr_un c_addr;
int c_len;
// iovec
struct iovec *hvec;
struct timeval start_of_request;
struct timeval end_of_request;
char *uri;
uint16_t uri_len;
char *remote_addr;
uint16_t remote_addr_len;
char *remote_user;
uint16_t remote_user_len;
char *query_string;
uint16_t query_string_len;
char *protocol;
uint16_t protocol_len;
char *method;
uint16_t method_len;
char *scheme;
uint16_t scheme_len;
char *https;
uint16_t https_len;
char *script_name;
uint16_t script_name_len;
char *wsgi_script;
uint16_t wsgi_script_len;
char *wsgi_module;
uint16_t wsgi_module_len;
char *wsgi_callable;
uint16_t wsgi_callable_len;
#ifdef UNBIT
unsigned long long unbit_flags;
#endif
int fd_closed;
int sendfile_fd;
size_t sendfile_fd_chunk;
size_t sendfile_fd_size;
off_t sendfile_fd_pos;
uint16_t var_cnt;
uint16_t header_cnt;
int status;
size_t response_size;
int headers_size;
int async_id;
int async_status ;
int async_waiting_fd;
int async_waiting_fd_type;
int async_waiting_fd_monitored;
int async_switches;
time_t async_timeout ;
int async_timeout_expired ;
void *async_app;
void *async_result;
void *async_placeholder;
void *async_args;
void *async_environ;
void *async_post;
void *async_sendfile;
int async_plagued;
#ifdef UWSGI_STACKLESS
PyTaskletObject* tasklet;
#endif
char *buffer;
};
struct uwsgi_server {
char *pyhome;
#ifndef ROCK_SOLID
int has_threads;
int wsgi_cnt;
int default_app;
int enable_profiler;
// base for all the requests (even on async mode)
struct wsgi_request *wsgi_requests ;
struct wsgi_request *wsgi_req ;
PyThreadState *_save;
#ifndef UNBIT
char *chroot;
gid_t gid;
uid_t uid;
#endif
int manage_next_request;
int in_request;
int serverfd;
#ifdef UWSGI_PROXY
int proxyfd;
char *proxy_socket_name;
#endif
struct iovec *async_hvec;
char **async_buf;
struct rlimit rl;
char *binary_path;
int is_a_reload;
char *socket_name;
#ifdef UWSGI_UDP
char *udp_socket;
#endif
#ifdef UWSGI_MULTICAST
char *multicast_group;
#endif
#ifdef UWSGI_SPOOLER
char *spool_dir;
#endif
#ifdef UWSGI_ERLANG
char *erlang_node;
char *erlang_cookie;
#endif
#ifdef UWSGI_NAGIOS
int nagios;
#endif
#ifdef UWSGI_SNMP
int snmp;
char *snmp_community;
#endif
int to_heaven;
int to_hell;
int buffer_size;
int master_process;
int no_defer_accept;
int page_size;
char *test_module;
char *pidfile;
int numproc;
int async;
int async_running;
int async_queue ;
int async_nevents ;
int max_vars ;
int vec_size ;
int stackless;
int request_logging;
char *sharedarea ;
#ifndef __OpenBSD__
void *sharedareamutex ;
#ifdef UWSGI_UGREEN
int ugreen;
int ugreen_stackpages;
ucontext_t ugreenmain;
ucontext_t **ugreen_contexts;
#endif
int sharedareasize ;
#ifdef __linux__
struct epoll_event *async_events;
#elif defined(__sun__)
struct pollfd *async_events;
#else
struct kevent *async_events;
#endif
int max_vars;
int vec_size;
char *sharedarea;
void *sharedareamutex;
int sharedareasize;
/* the list of workers */
struct uwsgi_worker *workers ;
struct uwsgi_worker *workers;
pid_t mypid;
int mywid;
struct timeval start_tv;
#ifndef UNBIT
#ifndef ROCK_SOLID
int cgi_mode;
#endif
int abstract_socket;
int chmod_socket;
int listen_queue;
#ifndef ROCK_SOLID
#ifdef UWSGI_XML
char *xml_config;
#endif
char *file_config;
char *python_path[64];
int python_path_cnt;
#endif
char *pyargv;
#endif
#ifndef ROCK_SOLID
char *wsgi_config;
#endif
char *paste;
char *wsgi_file;
#ifndef ROCK_SOLID
int single_interpreter;
int py_optimize;
PyObject *py_sendfile ;
PyObject *embedded_dict ;
PyObject *embedded_args ;
PyObject *fastfuncslist ;
PyObject *embedded_dict;
PyObject *embedded_args;
PyObject *fastfuncslist;
PyObject *workers_tuple ;
PyObject *wsgi_writeout;
PyThreadState *main_thread ;
#ifdef UWSGI_STACKLESS
PyObject *wsgi_stackless;
PyChannelObject *workers_channel;
struct stackless_req **stackless_table;
#endif
struct pollfd poll;
PyObject *workers_tuple;
int harakiri_timeout;
int socket_timeout;
PyThreadState *main_thread;
#ifndef ROCK_SOLID
int memory_debug;
#endif
#ifndef ROCK_SOLID
struct uwsgi_shared *shared;
struct uwsgi_app wsgi_apps[64];
PyObject *py_apps;
#ifdef UWSGI_ERLANG
int erlang_nodes;
int erlangfd;
#endif
};
struct uwsgi_cluster_node {
char name[101];
struct __attribute__((packed)) uwsgi_worker {
int id ;
struct sockaddr_in ucn_addr;
int workers;
int connections;
int status;
time_t last_seen;
int errors;
};
#ifdef UWSGI_SNMP
struct uwsgi_snmp_custom_value {
uint8_t type;
uint64_t val;
};
struct uwsgi_snmp_server_value {
uint8_t type;
uint64_t *val;
};
#endif
struct uwsgi_shared {
// vga 80x25 specific !
char warning_message[81];
int (*hooks[256]) (struct uwsgi_server *, struct wsgi_request *);
void (*after_hooks[256]) (struct uwsgi_server *, struct wsgi_request *);
uint32_t options[256];
struct uwsgi_cluster_node nodes[MAX_CLUSTER_NODES];
#ifdef UWSGI_SPOOLER
pid_t spooler_pid;
int spooler_frequency;
#endif
#ifdef UWSGI_PROXY
pid_t proxy_pid;
#endif
#ifdef UWSGI_SNMP
char snmp_community[72 + 1];
struct uwsgi_snmp_server_value snmp_gvalue[100];
struct uwsgi_snmp_custom_value snmp_value[100];
#define SNMP_COUNTER32 0x41
#define SNMP_GAUGE 0x42
#define SNMP_COUNTER64 0x46
#endif
};
struct uwsgi_worker {
int id;
pid_t pid;
uint64_t status;
int i_have_gil;
time_t last_spawn;
unsigned long long requests;
unsigned long long failed_requests;
uint64_t respawn_count;
uint64_t requests;
uint64_t failed_requests;
time_t harakiri;
unsigned long long respawn_count;
unsigned long long vsz_size;
unsigned long long rss_size;
uint64_t vsz_size;
uint64_t rss_size;
double running_time;
double last_running_time;
int manage_next_request;
};
struct __attribute__((packed)) uwsgi_header {
uint8_t modifier1;
uint16_t pktsize ;
uint8_t modifier2;
};
struct __attribute__((packed)) wsgi_request {
uint8_t modifier;
uint16_t size ;
uint8_t modifier_arg;
// temporary attr
#ifndef ROCK_SOLID
int app_id ;
#endif
struct timeval start_of_request ;
char *uri;
unsigned short uri_len;
char *remote_addr;
unsigned short remote_addr_len;
char *remote_user;
unsigned short remote_user_len;
char *query_string;
unsigned short query_string_len;
char *protocol;
unsigned short protocol_len;
char *method;
unsigned short method_len;
#ifdef UNBIT
unsigned long long unbit_flags;
#endif
#ifndef ROCK_SOLID
char *wsgi_script;
unsigned short wsgi_script_len;
char *wsgi_module;
unsigned short wsgi_module_len;
char *wsgi_callable;
unsigned short wsgi_callable_len;
char *script_name;
unsigned short script_name_len;
int sendfile_fd;
#endif
unsigned short var_cnt;
unsigned short header_cnt;
int status;
int response_size;
int headers_size;
};
char *uwsgi_get_cwd(void);
void warn_pipe(void);
void goodbye_cruel_world(void);
void gracefully_kill(void);
void reap_them_all(void);
@@ -289,52 +616,214 @@ void kill_them_all(void);
void grace_them_all(void);
void reload_me(void);
void end_me(void);
int bind_to_unix(char *, int, int , int );
int bind_to_tcp(char *, int , char *);
int bind_to_unix(char *, int, int, int);
int bind_to_tcp(char *, int, char *);
int bind_to_udp(char *);
int timed_connect(struct pollfd *, const struct sockaddr *, int, int);
int connect_to_tcp(char *, int, int);
#ifdef UWSGI_SCTP
int bind_to_sctp(char *, int, char *);
#endif
#ifndef UNBIT
void daemonize(char *);
#endif
void log_request(void) ;
#ifndef ROCK_SOLID
void get_memusage(void) ;
#endif
void harakiri(void) ;
void log_request(struct wsgi_request *);
void get_memusage(void);
void harakiri(void);
#ifndef UNBIT
void stats(void) ;
void stats(void);
#endif
void init_uwsgi_vars(void);
void init_uwsgi_embedded_module(void);
#ifndef UNBIT
void uwsgi_xml_config(void);
#ifdef UWSGI_XML
void uwsgi_xml_config(struct wsgi_request *, struct option *);
#endif
#ifndef ROCK_SOLID
void uwsgi_wsgi_config(void);
#endif
void uwsgi_wsgi_config(char *);
void uwsgi_paste_config(void);
void uwsgi_wsgi_file_config(void);
void internal_server_error(int, char *);
void init_uwsgi_module_sharedarea(PyObject *);
void init_uwsgi_module_advanced(PyObject *);
#ifdef UWSGI_SPOOLER
void init_uwsgi_module_spooler(PyObject *);
#endif
#ifndef ROCK_SOLID
int spool_request(char *, int, char *, int);
void spooler(PyObject *);
#ifdef UWSGI_SNMP
void manage_snmp(int, uint8_t *, int, struct sockaddr_in *);
void snmp_init(void);
#endif
#ifdef UWSGI_SPOOLER
int spool_request(struct uwsgi_server *, char *, int, char *, int);
void spooler(struct uwsgi_server *, PyObject *);
pid_t spooler_start(int, PyObject *);
#endif
void set_harakiri(int);
#ifdef __BIG_ENDIAN__
uint16_t uwsgi_swap16( uint16_t );
uint16_t uwsgi_swap16(uint16_t);
uint32_t uwsgi_swap32(uint32_t);
uint64_t uwsgi_swap64(uint64_t);
#endif
#ifndef ROCK_SOLID
int init_uwsgi_app(PyObject *, PyObject *) ;
int init_uwsgi_app(PyObject *, PyObject *);
PyObject *uwsgi_send_message(const char *, int, uint8_t, uint8_t, char *, int, int);
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t, char *, char *, uint16_t);
#endif
PyObject *uwsgi_send_message(char *, int, uint8_t, uint8_t, char *, int, int);
int uwsgi_parse_response(struct pollfd*, int, struct uwsgi_header *, char *);
int uwsgi_parse_response(struct pollfd *, int, struct uwsgi_header *, char *);
int uwsgi_parse_vars(struct uwsgi_server *, struct wsgi_request *);
int uwsgi_enqueue_message(char *, int, uint8_t, uint8_t, char *, int, int);
/* included HOOKS */
int uwsgi_request_wsgi(struct uwsgi_server *, struct wsgi_request *);
void uwsgi_after_request_wsgi(struct uwsgi_server *, struct wsgi_request *);
int uwsgi_request_admin(struct uwsgi_server *, struct wsgi_request *);
#ifdef UWSGI_SPOOLER
int uwsgi_request_spooler(struct uwsgi_server *, struct wsgi_request *);
#endif
int uwsgi_request_fastfunc(struct uwsgi_server *, struct wsgi_request *);
int uwsgi_request_marshal(struct uwsgi_server *, struct wsgi_request *);
int uwsgi_request_ping(struct uwsgi_server *, struct wsgi_request *);
#ifdef UWSGI_ERLANG
#include <erl_interface.h>
#include <ei.h>
int init_erlang(char *, char *);
void erlang_loop(struct wsgi_request *);
PyObject *eterm_to_py(ETERM *);
ETERM *py_to_eterm(PyObject *);
#endif
void manage_opt(int, char *);
#ifdef UWSGI_PROXY
void uwsgi_proxy(int);
pid_t proxy_start(int);
#endif
void uwsgi_cluster_add_node(char *, int);
int uwsgi_ping_node(int, struct wsgi_request *);
struct http_status_codes {
char key[3];
char *message;
int message_size;
};
#ifdef UWSGI_ASYNC
struct wsgi_request *async_loop(struct uwsgi_server *);
struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *);
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *, int, int);
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *, int);
inline struct wsgi_request *next_wsgi_req(struct uwsgi_server *, struct wsgi_request *);
int async_add(int, int , int) ;
int async_mod(int, int , int) ;
int async_wait(int, void *, int, int, int);
int async_del(int, int , int) ;
int async_queue_init(int);
int async_get_timeout(struct uwsgi_server *);
void async_set_timeout(struct wsgi_request *, time_t);
void async_expire_timeouts(struct uwsgi_server *);
void async_write_all(struct uwsgi_server *, char *, size_t);
void async_unpause_all(struct uwsgi_server *);
#ifdef __linux__
#define ASYNC_FD data.fd
#define ASYNC_EV events
#define ASYNC_IN EPOLLIN
#define ASYNC_OUT EPOLLOUT
#define ASYNC_IS_IN ASYNC_EV & ASYNC_IN
#define ASYNC_IS_OUT ASYNC_EV & ASYNC_OUT
#elif defined(__sun__)
#define ASYNC_FD fd
#define ASYNC_EV revents
#define ASYNC_IN POLLIN
#define ASYNC_OUT POLLOUT
#define ASYNC_IS_IN ASYNC_EV & ASYNC_IN
#define ASYNC_IS_OUT ASYNC_EV & ASYNC_OUT
#else
#define ASYNC_FD ident
#define ASYNC_EV filter
#define ASYNC_IN EVFILT_READ
#define ASYNC_OUT EVFILT_WRITE
#define ASYNC_IS_IN ASYNC_EV == ASYNC_IN
#define ASYNC_IS_OUT ASYNC_EV == ASYNC_OUT
#endif
PyObject *py_eventfd_read(PyObject *, PyObject *) ;
PyObject *py_eventfd_write(PyObject *, PyObject *) ;
#endif
#ifdef UWSGI_STACKLESS
PyObject *py_uwsgi_stackless(PyObject *, PyObject *) ;
#endif
int manage_python_response(struct uwsgi_server *, struct wsgi_request *);
int uwsgi_python_call(struct uwsgi_server *, struct wsgi_request *, PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *);
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *) ;
ssize_t uwsgi_sendfile(struct uwsgi_server *, struct wsgi_request *);
#endif
PyObject *py_uwsgi_write(PyObject *, PyObject *) ;
PyObject *py_uwsgi_spit(PyObject *, PyObject *) ;
void uwsgi_as_root(void);
#ifdef UWSGI_NAGIOS
void nagios(struct uwsgi_server *);
#endif
#ifdef UWSGI_STACKLESS
struct stackless_req {
PyTaskletObject *tasklet;
struct wsgi_request *wsgi_req;
PyChannelObject *channel;
};
struct wsgi_request *find_request_by_tasklet(PyTaskletObject *);
void stackless_init(struct uwsgi_server *);
void stackless_loop(struct uwsgi_server *);
#endif
void uwsgi_close_request(struct uwsgi_server *, struct wsgi_request *) ;
void wsgi_req_setup(struct wsgi_request *, int);
int wsgi_req_recv(struct wsgi_request *);
int wsgi_req_accept(int, struct wsgi_request *);
#ifdef UWSGI_UGREEN
void u_green_init(struct uwsgi_server *);
void u_green_loop(struct uwsgi_server *);
#endif
inline struct wsgi_request *current_wsgi_req(struct uwsgi_server *);
void sanitize_args(struct uwsgi_server *);
void env_to_arg(char *, char *);
void parse_sys_envs(char **, struct option *);
void uwsgi_log(const char *, ...);
+127
View File
@@ -0,0 +1,127 @@
#include "uwsgi.h"
/* uwsgi PING|100 */
int uwsgi_request_ping(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
char len;
uwsgi_log( "PING\n");
wsgi_req->uh.modifier2 = 1;
wsgi_req->uh.pktsize = 0;
len = strlen(uwsgi->shared->warning_message);
if (len > 0) {
// TODO: check endianess ?
wsgi_req->uh.pktsize = len;
}
if (write(wsgi_req->poll.fd, wsgi_req, 4) != 4) {
uwsgi_error("write()");
}
if (len > 0) {
if (write(wsgi_req->poll.fd, uwsgi->shared->warning_message, len)
!= len) {
uwsgi_error("write()");
}
}
return UWSGI_OK;
}
/* uwsgi ADMIN|10 */
int uwsgi_request_admin(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
uint32_t opt_value = 0;
int i;
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()");
}
return UWSGI_OK;
}
/* uwsgi FASTFUNC|26 */
int uwsgi_request_fastfunc(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
PyObject *ffunc;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
return manage_python_response(uwsgi, wsgi_req);
}
#endif
ffunc = PyList_GetItem(uwsgi->fastfuncslist, wsgi_req->uh.modifier2);
if (ffunc) {
uwsgi_log( "managing fastfunc %d\n", wsgi_req->uh.modifier2);
return uwsgi_python_call(uwsgi, wsgi_req, ffunc, NULL);
}
return UWSGI_OK;
}
/* uwsgi MARSHAL|33 */
int uwsgi_request_marshal(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
PyObject *func_result;
PyObject *umm = PyDict_GetItemString(uwsgi->embedded_dict,
"message_manager_marshal");
if (umm) {
PyObject *ummo = PyMarshal_ReadObjectFromString(wsgi_req->buffer,
wsgi_req->uh.pktsize);
if (ummo) {
if (!PyTuple_SetItem(uwsgi->embedded_args, 0, ummo)) {
if (!PyTuple_SetItem(uwsgi->embedded_args, 1, PyInt_FromLong(wsgi_req->uh.modifier2))) {
func_result = PyEval_CallObject(umm, uwsgi->embedded_args);
if (PyErr_Occurred()) {
PyErr_Print();
}
if (func_result) {
PyObject *marshalled = PyMarshal_WriteObjectToString(func_result, 1);
if (!marshalled) {
PyErr_Print();
}
else {
if (PyString_Size(marshalled) <= 0xFFFF) {
wsgi_req->uh.pktsize = (uint16_t)
PyString_Size(marshalled);
if (write(wsgi_req->poll.fd, wsgi_req, 4) == 4) {
if (write(wsgi_req->poll.fd, PyString_AsString(marshalled), wsgi_req->uh.pktsize) != wsgi_req->uh.pktsize) {
uwsgi_error("write()");
}
}
else {
uwsgi_error("write()");
}
}
else {
uwsgi_log( "marshalled object is too big. skip\n");
}
Py_DECREF(marshalled);
}
Py_DECREF(func_result);
}
}
}
//Py_DECREF(ummo);
}
}
PyErr_Clear();
return 0;
}
+648 -444
View File
File diff suppressed because it is too large Load Diff
+313
View File
@@ -0,0 +1,313 @@
# uWSGI configuration
XML=True
SNMP=True
SCTP=False
ERLANG=False
SPOOLER=True
EMBEDDED=True
UDP=True
MULTICAST=True
THREADING=True
SENDFILE=True
PROFILER=True
NAGIOS=True
PROXY=True
MINTERPRETERS=True
ASYNC=True
UGREEN=True
STACKLESS=False
PLUGINS = []
UNBIT=False
UWSGI_BIN_NAME = 'uwsgi'
GCC='gcc'
# specific compilation flags
# libxml2 or expat
XML_IMPLEMENTATION = 'libxml2'
# if you want to use alternative python lib, specifiy its path here
#PYLIB_PATH = '/home/roberto/uwsgi/STACKLESS/slp/lib'
PYLIB_PATH = ''
ERLANG_CFLAGS = ''
ERLANG_LDFLAGS = '-lerl_interface -lei'
# for source distribution installed in /usr/local
#ERLANG_CFLAGS = '-I /usr/local/lib/erlang/lib/erl_interface-3.6.5/include/'
#ERLANG_LDFLAGS = '-L/usr/local/lib/erlang/lib/erl_interface-3.6.5/lib -lerl_interface -lei'
# end of configuration
import os
uwsgi_os = os.uname()[0]
import sys
import subprocess
from distutils import sysconfig
gcc_list = ['utils', 'pyutils', 'protocol', 'socket', 'logging', 'wsgi_handlers', 'wsgi_headers', 'uwsgi_handlers', 'uwsgi']
# large file support
try:
cflags = ['-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + sysconfig.get_config_var('CFLAGS').split()
except:
print("You need python headers to build uWSGI.")
sys.exit(1)
cflags = cflags + ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
ldflags = ['-lpthread', '-rdynamic'] + sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
def depends_on(what, dep):
for d in dep:
if not globals()[d]:
print("%s needs %s support." % (what, d))
sys.exit(1)
def spcall(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
if p.wait() == 0:
return p.stdout.read().rstrip().decode()
else:
return None
def add_o(x):
if x == 'uwsgi':
x = 'main'
x = x + '.o'
return x
def build_uwsgi(bin_name):
print("*** uWSGI compiling ***")
for file in gcc_list:
objfile = file
if objfile == 'uwsgi':
objfile = 'main'
cmdline = "%s -c %s -o %s %s" % (GCC, ' '.join(cflags), objfile + '.o', file + '.c')
print(cmdline)
ret = os.system(cmdline)
if ret != 0:
sys.exit(1)
if len(PLUGINS) > 0:
print("*** uWSGI embedding plugin ***")
for plugin in PLUGINS:
print(plugin)
print("*** uWSGI linking ***")
ldline = "%s -o %s %s %s" % (GCC, bin_name, ' '.join(map(add_o, gcc_list)), ' '.join(ldflags))
print(ldline)
ret = os.system(ldline)
if ret != 0:
print("*** error linking uWSGI ***")
sys.exit(1)
if bin_name.find("/") < 0:
bin_name = './' + bin_name
print("*** uWSGI is ready, launch it with %s ***" % bin_name)
def unbit_setup():
global XML, SNMP, SCTP, ERLANG, SPOOLER
global EMBEDDED, UDP, MULTICAST, THREADING
global SENDFILE, PROFILER, NAGIOS, PROXY
global UWSGI_BIN_NAME
XML=False
SNMP=False
SCTP=False
ERLANG=False
UDP=False
MULTICAST=False
NAGIOS=False
PROXY=False
EMBEDDED=True
SPOOLER=True
THREADING=True
SENDFILE=True
PROFILER=True
UNBIT=True
UWSGI_BIN_NAME='/usr/share/unbit/uwsgi26'
def parse_vars():
global UGREEN
version = sys.version_info
uver = "%d.%d" % (version[0], version[1])
ldflags.append('-lpython' + uver)
if str(PYLIB_PATH) != '':
ldflags.insert(0,'-L' + PYLIB_PATH)
kvm_list = ['FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly']
if uwsgi_os == 'SunOS':
ldflags.append('-lsendfile')
ldflags.remove('-rdynamic')
if uwsgi_os in kvm_list:
ldflags.append('-lkvm')
if uwsgi_os == 'OpenBSD':
UGREEN = False
if EMBEDDED:
cflags.append('-DUWSGI_EMBEDDED')
gcc_list.append('uwsgi_pymodule')
if UDP:
cflags.append("-DUWSGI_UDP")
if ASYNC:
cflags.append("-DUWSGI_ASYNC")
gcc_list.append('async')
if MULTICAST:
depends_on("MULTICAST", ['UDP'])
cflags.append("-DUWSGI_MULTICAST")
if STACKLESS:
if not cflags.__contains__('-DSTACKLESS_FRHACK=1'):
print("you need Stackless Python to use Tasklet")
sys.exit(1)
cflags.append("-DUWSGI_STACKLESS")
gcc_list.append('stackless')
if MINTERPRETERS:
cflags.append("-DUWSGI_MINTERPRETERS")
if NAGIOS:
cflags.append("-DUWSGI_NAGIOS")
gcc_list.append('nagios')
if PROXY:
depends_on("PROXY", ['ASYNC'])
cflags.append("-DUWSGI_PROXY")
gcc_list.append('proxy')
if UGREEN:
if uwsgi_os == 'Darwin':
cflags.append("-D_XOPEN_SOURCE")
depends_on("UGREEN", ['ASYNC'])
cflags.append("-DUWSGI_UGREEN")
gcc_list.append('ugreen')
if SNMP:
depends_on("SNMP", ['UDP'])
cflags.append("-DUWSGI_SNMP")
gcc_list.append('snmp')
if THREADING:
cflags.append("-DUWSGI_THREADING")
if PROFILER:
cflags.append("-DUWSGI_PROFILER")
if SENDFILE:
cflags.append("-DUWSGI_SENDFILE")
gcc_list.append('sendfile')
if XML:
if XML_IMPLEMENTATION == 'libxml2':
xmlconf = spcall('xml2-config --libs')
if xmlconf is None:
print("*** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML")
sys.exit(1)
else:
ldflags.append(xmlconf)
xmlconf = spcall("xml2-config --cflags")
if xmlconf is None:
print("*** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML")
sys.exit(1)
else:
cflags.append(xmlconf)
cflags.append("-DUWSGI_XML -DUWSGI_XML_LIBXML2")
gcc_list.append('xmlconf')
elif XML_IMPLEMENTATION == 'expat':
cflags.append("-DUWSGI_XML -DUWSGI_XML_EXPAT")
ldflags.append('-lexpat')
gcc_list.append('xmlconf')
if ERLANG:
depends_on("ERLANG", ['EMBEDDED'])
cflags.append("-DUWSGI_ERLANG")
ldflags.append(ERLANG_LDFLAGS)
if str(ERLANG_CFLAGS) != '':
cflags.append(ERLANG_CFLAGS)
gcc_list.append('erlang')
if SCTP:
ldflags.append("-lsctp")
cflags.append("-DUWSGI_SCTP")
if SPOOLER:
depends_on("SPOOLER", ['EMBEDDED'])
cflags.append("-DUWSGI_SPOOLER")
gcc_list.append('spooler')
if UNBIT:
cflags.append("-DUWSGI_UNBIT")
def build_plugin(path):
path = path.rstrip('/')
sys.path.insert(0, path)
import uwsgiplugin as up
cflags.append(up.CFLAGS)
ldflags.append(up.LDFLAGS)
cflags.insert(0, '-I.')
plugin_base = path + '/' + up.NAME + '_plugin'
gccline = "%s -fPIC -shared -o %s.so %s %s.c %s" % (GCC, plugin_base, ' '.join(cflags), plugin_base, ' '.join(ldflags))
print(gccline)
ret = os.system(gccline)
if ret != 0:
print("*** unable to build %s plugin ***" % up.NAME)
sys.exit(1)
print("*** %s plugin built and available in %s ***" % (up.NAME, plugin_base + '.so'))
if __name__ == "__main__":
try:
cmd = sys.argv[1]
except:
print("please specify an argument")
sys.exit(1)
if cmd == '--cflags':
print(' '.join(cflags))
if cmd == '--ldflags':
print(' '.join(ldflags))
elif cmd == '--build':
parse_vars()
build_uwsgi(UWSGI_BIN_NAME)
elif cmd == '--unbit':
unbit_setup()
parse_vars()
build_uwsgi(UWSGI_BIN_NAME)
elif cmd == '--plugin':
parse_vars()
build_plugin(sys.argv[2])
else:
print("unknown uwsgiconfig command")
sys.exit(1)
+325
View File
@@ -0,0 +1,325 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
PyObject *py_uwsgi_write(PyObject * self, PyObject * args) {
PyObject *data;
char *content;
int len;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
data = PyTuple_GetItem(args, 0);
if (PyString_Check(data)) {
content = PyString_AsString(data);
len = PyString_Size(data);
#ifdef UWSGI_THREADING
if (uwsgi.has_threads && uwsgi.shared->options[UWSGI_OPTION_THREADS] == 1) {
Py_BEGIN_ALLOW_THREADS wsgi_req->response_size = write(wsgi_req->poll.fd, content, len);
Py_END_ALLOW_THREADS}
else {
#endif
wsgi_req->response_size = write(wsgi_req->poll.fd, content, len);
#ifdef UWSGI_THREADING
}
#endif
}
Py_INCREF(Py_None);
return Py_None;
}
#ifdef UWSGI_ASYNC
PyObject *py_eventfd_read(PyObject * self, PyObject * args) {
int fd, timeout;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}
if (fd >= 0) {
wsgi_req->async_waiting_fd = fd ;
wsgi_req->async_waiting_fd_type = ASYNC_IN ;
wsgi_req->async_waiting_fd_monitored = 0 ;
}
return PyString_FromString("") ;
}
PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
int fd, timeout;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}
if (fd >= 0) {
wsgi_req->async_waiting_fd = fd ;
wsgi_req->async_waiting_fd_type = ASYNC_OUT ;
wsgi_req->async_waiting_fd_monitored = 0 ;
}
return PyString_FromString("") ;
}
#endif
int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int i;
PyObject *zero, *wsgi_socket;
PyObject *pydictkey, *pydictvalue;
char *path_info;
struct uwsgi_app *wi ;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
// get rid of timeout
if (wsgi_req->async_timeout_expired) {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_True);
wsgi_req->async_timeout_expired = 0 ;
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
}
return manage_python_response(uwsgi, wsgi_req);
}
#endif
/* Standard WSGI request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log( "Invalid WSGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
uwsgi_log("Invalid WSGI request. skip.\n");
return -1;
}
#ifdef UWSGI_THREADING
if (uwsgi->has_threads && !uwsgi->workers[uwsgi->mywid].i_have_gil) {
PyEval_RestoreThread(uwsgi->_save);
uwsgi->workers[uwsgi->mywid].i_have_gil = 1;
}
#endif
if (wsgi_req->script_name_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->script_name, wsgi_req->script_name_len);
if (PyDict_Contains(uwsgi->py_apps, zero)) {
wsgi_req->app_id = PyInt_AsLong(PyDict_GetItem(uwsgi->py_apps, zero));
}
else {
/* unavailable app for this SCRIPT_NAME */
wsgi_req->app_id = -1;
if (wsgi_req->wsgi_script_len > 0 || (wsgi_req->wsgi_callable_len > 0 && wsgi_req->wsgi_module_len > 0)) {
if ((wsgi_req->app_id = init_uwsgi_app(NULL, NULL)) == -1) {
internal_server_error(wsgi_req->poll.fd, "wsgi application not found");
Py_DECREF(zero);
goto clear2;
}
}
}
Py_DECREF(zero);
}
if (wsgi_req->app_id == -1) {
internal_server_error(wsgi_req->poll.fd, "wsgi application not found");
goto clear2;
}
wi = &uwsgi->wsgi_apps[wsgi_req->app_id];
if (uwsgi->single_interpreter == 0) {
if (!wi->interpreter) {
internal_server_error(wsgi_req->poll.fd, "wsgi application's %d interpreter not found");
goto clear2;
}
// set the interpreter
PyThreadState_Swap(wi->interpreter);
}
wi->requests++;
if (wsgi_req->protocol_len < 5) {
uwsgi_log( "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
goto clear;
}
if (strncmp(wsgi_req->protocol, "HTTP/", 5)) {
uwsgi_log( "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
goto clear;
}
#ifdef UWSGI_ASYNC
wsgi_req->async_environ = wi->wsgi_environ[wsgi_req->async_id];
wsgi_req->async_args = wi->wsgi_args[wsgi_req->async_id];
#else
wsgi_req->async_environ = wi->wsgi_environ;
wsgi_req->async_args = wi->wsgi_args;
#endif
Py_INCREF((PyObject *)wsgi_req->async_environ);
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
//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);
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
if (pydictvalue) {
if (PyString_Check(pydictvalue)) {
path_info = PyString_AsString(pydictvalue);
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
}
}
}
}
}
// set wsgi vars
wsgi_req->async_post = fdopen(wsgi_req->poll.fd, "r");
wsgi_socket = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_socket);
Py_DECREF(wsgi_socket);
#ifdef UWSGI_SENDFILE
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->wsgi_sendfile);
#endif
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.readable", wi->wsgi_eventfd_read);
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.writable", wi->wsgi_eventfd_write);
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
}
#endif
zero = PyTuple_New(2);
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", zero);
Py_DECREF(zero);
zero = PyFile_FromFile(stderr, "wsgi_input", "w", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.errors", zero);
Py_DECREF(zero);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.run_once", Py_False);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multithread", Py_False);
if (uwsgi->numproc == 1) {
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_False);
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_True);
}
if (wsgi_req->scheme_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
zero = PyString_FromString("https");
}
else {
zero = PyString_FromString("http");
}
}
else {
zero = PyString_FromString("http");
}
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
Py_DECREF(zero);
// call
#ifdef UWSGI_PROFILER
if (uwsgi->enable_profiler == 1) {
PyDict_SetItem(wi->pymain_dict, PyString_FromFormat("uwsgi_environ__%d", wsgi_req->app_id), wsgi_req->async_environ);
wsgi_req->async_result = python_call(wi->wsgi_cprofile_run, wsgi_req->async_args);
if (wsgi_req->async_result) {
wsgi_req->async_result = PyDict_GetItemString(wi->pymain_dict, "uwsgi_out");
Py_INCREF((PyObject*)wsgi_req->async_result);
Py_INCREF((PyObject*)wsgi_req->async_result);
}
}
else {
#endif
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
wsgi_req->async_result = python_call(wi->wsgi_callable, wsgi_req->async_args);
#ifdef UWSGI_PROFILER
}
#endif
if (wsgi_req->async_result) {
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
}
}
clear:
if (uwsgi->single_interpreter == 0) {
// restoring main interpreter
PyThreadState_Swap(uwsgi->main_thread);
}
clear2:
return UWSGI_OK;
}
void uwsgi_after_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
+166
View File
@@ -0,0 +1,166 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static char *nl = "\r\n";
static char *h_sep = ": ";
static const char *http_protocol = "HTTP/1.1";
PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
PyObject *headers, *head;
PyObject *h_key, *h_value;
int i, j;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
#ifndef UNBIT
int base = 0;
#else
int base = 4;
#endif
// use writev()
head = PyTuple_GetItem(args, 0);
if (!head) {
goto clear;
}
if (!PyString_Check(head)) {
uwsgi_log( "http status must be a string !\n");
goto clear;
}
#ifndef UNBIT
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
base = 4;
#endif
if (wsgi_req->protocol_len == 0) {
wsgi_req->hvec[0].iov_base = (char *) http_protocol;
wsgi_req->protocol_len = 8;
}
else {
wsgi_req->hvec[0].iov_base = wsgi_req->protocol;
}
wsgi_req->hvec[0].iov_len = wsgi_req->protocol_len;
wsgi_req->hvec[1].iov_base = " ";
wsgi_req->hvec[1].iov_len = 1;
#ifdef PYTHREE
wsgi_req->hvec[2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
wsgi_req->hvec[2].iov_len = strlen(wsgi_req->hvec[2].iov_base);
#else
wsgi_req->hvec[2].iov_base = PyString_AsString(head);
wsgi_req->hvec[2].iov_len = PyString_Size(head);
#endif
wsgi_req->status = atoi(wsgi_req->hvec[2].iov_base);
wsgi_req->hvec[3].iov_base = nl;
wsgi_req->hvec[3].iov_len = NL_SIZE;
#ifndef UNBIT
}
else {
// drop http status on cgi mode
base = 3;
wsgi_req->hvec[0].iov_base = "Status: ";
wsgi_req->hvec[0].iov_len = 8;
#ifdef PYTHREE
wsgi_req->hvec[1].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
wsgi_req->hvec[1].iov_len = strlen(wsgi_req->hvec[1].iov_base);
#else
wsgi_req->hvec[1].iov_base = PyString_AsString(head);
wsgi_req->hvec[1].iov_len = PyString_Size(head);
#endif
wsgi_req->status = atoi(wsgi_req->hvec[1].iov_base);
wsgi_req->hvec[2].iov_base = nl;
wsgi_req->hvec[2].iov_len = NL_SIZE;
}
#endif
#ifdef UNBIT
if (wsgi_req->unbit_flags & (unsigned long long) 1) {
if (tmp_dir_fd >= 0 && tmp_filename[0] != 0 && wsgi_req->status == 200 && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
save_to_disk = openat(tmp_dir_fd, tmp_filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
}
}
#endif
headers = PyTuple_GetItem(args, 1);
if (!headers) {
goto clear;
}
if (!PyList_Check(headers)) {
uwsgi_log( "http headers must be in a python list\n");
goto clear;
}
wsgi_req->header_cnt = PyList_Size(headers);
if (wsgi_req->header_cnt > uwsgi.max_vars) {
wsgi_req->header_cnt = uwsgi.max_vars;
}
for (i = 0; i < wsgi_req->header_cnt; i++) {
j = (i * 4) + base;
head = PyList_GetItem(headers, i);
if (!head) {
goto clear;
}
if (!PyTuple_Check(head)) {
uwsgi_log( "http header must be defined in a tuple !\n");
goto clear;
}
h_key = PyTuple_GetItem(head, 0);
if (!h_key) {
goto clear;
}
h_value = PyTuple_GetItem(head, 1);
if (!h_value) {
goto clear;
}
#ifdef PYTHREE
wsgi_req->hvec[j].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_key));
wsgi_req->hvec[j].iov_len = strlen(wsgi_req->hvec[j].iov_base);
#else
wsgi_req->hvec[j].iov_base = PyString_AsString(h_key);
wsgi_req->hvec[j].iov_len = PyString_Size(h_key);
#endif
wsgi_req->hvec[j + 1].iov_base = h_sep;
wsgi_req->hvec[j + 1].iov_len = H_SEP_SIZE;
#ifdef PYTHREE
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_value));
wsgi_req->hvec[j + 2].iov_len = strlen(wsgi_req->hvec[j + 2].iov_base);
#else
wsgi_req->hvec[j + 2].iov_base = PyString_AsString(h_value);
wsgi_req->hvec[j + 2].iov_len = PyString_Size(h_value);
#endif
wsgi_req->hvec[j + 3].iov_base = nl;
wsgi_req->hvec[j + 3].iov_len = NL_SIZE;
//uwsgi_log( "%.*s: %.*s\n", wsgi_req->hvec[j].iov_len, (char *)wsgi_req->hvec[j].iov_base, wsgi_req->hvec[j+2].iov_len, (char *) wsgi_req->hvec[j+2].iov_base);
}
// \r\n
j = (i * 4) + base;
wsgi_req->hvec[j].iov_base = nl;
wsgi_req->hvec[j].iov_len = NL_SIZE;
wsgi_req->headers_size = writev(wsgi_req->poll.fd, wsgi_req->hvec, j + 1);
if (wsgi_req->headers_size < 0) {
uwsgi_error("writev()");
}
Py_INCREF(uwsgi.wsgi_writeout);
return uwsgi.wsgi_writeout;
clear:
Py_INCREF(Py_None);
return Py_None;
}
+302
View File
@@ -0,0 +1,302 @@
#ifdef UWSGI_XML
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_XML_LIBXML2
#include <libxml/parser.h>
#include <libxml/tree.h>
void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options) {
xmlDoc *doc = NULL;
xmlNode *element = NULL;
xmlNode *node = NULL;
xmlNode *node2 = NULL;
xmlChar *xml_uwsgi_mountpoint = NULL;
xmlChar *xml_uwsgi_script = NULL;
struct option *lopt, *aopt;
doc = xmlReadFile(uwsgi.xml_config, NULL, 0);
if (doc == NULL) {
uwsgi_log( "[uWSGI] could not parse file %s.\n", uwsgi.xml_config);
exit(1);
}
if (long_options) {
uwsgi_log( "[uWSGI] parsing config file %s\n", uwsgi.xml_config);
}
element = xmlDocGetRootElement(doc);
if (element == NULL) {
uwsgi_log( "[uWSGI] invalid xml config file.\n");
exit(1);
}
if (strcmp((char *) element->name, "uwsgi")) {
uwsgi_log( "[uWSGI] invalid xml root element, <uwsgi> expected.\n");
exit(1);
}
if (long_options) {
// first check for pythonpath
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
lopt = long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp((char *) node->name, aopt->name)) {
if (!node->children && aopt->has_arg) {
uwsgi_log( "[uWSGI] %s option need a value. skip.\n", aopt->name);
exit(1);
}
if (node->children) {
if (!node->children->content && aopt->has_arg) {
uwsgi_log( "[uWSGI] %s option need a value. skip.\n", aopt->name);
exit(1);
}
}
if (aopt->flag) {
*aopt->flag = aopt->val;
}
else {
if (node->children) {
manage_opt(aopt->val, (char *) node->children->content);
}
else {
manage_opt(aopt->val, NULL);
}
}
}
lopt++;
}
}
}
}
else {
// ... then for wsgi apps
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, "app")) {
xml_uwsgi_mountpoint = xmlGetProp(node, (const xmlChar *) "mountpoint");
if (xml_uwsgi_mountpoint == NULL) {
uwsgi_log( "no mountpoint defined for app. skip.\n");
continue;
}
wsgi_req->script_name = (char *) xml_uwsgi_mountpoint;
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
for (node2 = node->children; node2; node2 = node2->next) {
if (node2->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node2->name, "script")) {
if (!node2->children) {
uwsgi_log( "no wsgi script defined. skip.\n");
continue;
}
xml_uwsgi_script = node2->children->content;
if (xml_uwsgi_script == NULL) {
uwsgi_log( "no wsgi script defined. skip.\n");
continue;
}
wsgi_req->wsgi_script = (char *) xml_uwsgi_script;
wsgi_req->wsgi_script_len = strlen(wsgi_req->wsgi_script);
init_uwsgi_app(NULL, NULL);
}
}
}
}
}
}
}
/* We cannot free xml resources on the first round as the string pointer must be valid for all the server lifecycle */
if (!long_options) {
xmlFreeDoc (doc);
xmlCleanupParser ();
}
}
#endif
#ifdef UWSGI_XML_EXPAT
#include <expat.h>
int current_xmlnode ;
int current_xmlnode_has_arg ;
char *current_xmlnode_text ;
int current_xmlnode_text_len ;
void uwsgi_endElement(void *userData, const char *name) {
if (current_xmlnode && !current_xmlnode_has_arg) {
manage_opt(current_xmlnode, NULL);
}
else if (current_xmlnode_has_arg) {
if (!current_xmlnode_text_len) {
uwsgi_log("option %s requires an argument\n", name);
exit(1);
}
// HACK: use the first char of closing tag for nulling string
current_xmlnode_text[current_xmlnode_text_len] = 0;
manage_opt(current_xmlnode, current_xmlnode_text);
}
current_xmlnode = 0 ;
current_xmlnode_has_arg = 0 ;
current_xmlnode_text = NULL ;
current_xmlnode_text_len = 0 ;
}
void uwsgi_endApp(void *userData, const char *name) {}
void uwsgi_textHandler(void *userData, const char *s, int len) {
if (current_xmlnode && current_xmlnode_has_arg) {
current_xmlnode_text = (char *) s;
current_xmlnode_text_len = len;
}
}
void uwsgi_textApp(void *userData, const char *s, int len) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) userData ;
if (current_xmlnode) {
wsgi_req->wsgi_script = (char *) s;
wsgi_req->wsgi_script_len = len;
init_uwsgi_app(NULL, NULL);
current_xmlnode = 0;
}
};
void uwsgi_startApp(void *userData, const char *name, const char **attrs) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) userData ;
if (!strcmp(name, "app")) {
current_xmlnode = 0 ;
uwsgi_log("%s = %s\n", attrs[0], attrs[1]);
if (strcmp(attrs[0], "mountpoint")) {
uwsgi_log("invalid attribute for app tag. must be 'mountpoint'\n");
exit(1);
}
if (attrs[1]) {
wsgi_req->script_name = (char *) attrs[1];
wsgi_req->script_name_len = strlen(attrs[1]);
}
else {
wsgi_req->script_name = "/";
wsgi_req->script_name_len = 1;
}
}
else if (!strcmp(name, "script")) {
if (!wsgi_req->script_name_len) {
uwsgi_log("you have not specified an app mountpoint.\n");
exit(1);
}
current_xmlnode = 1 ;
}
}
void uwsgi_startElement(void *userData, const char *name, const char **attrs) {
struct option *long_options = (struct option *) userData;
struct option *lopt, *aopt;
lopt = long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(name, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
break;
}
else {
current_xmlnode = aopt->val;
current_xmlnode_has_arg = aopt->has_arg ;
break;
}
}
lopt++;
}
}
void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options) {
int xmlfd ;
size_t rlen ;
struct stat stat_buf;
char *xmlbuf ;
XML_Parser parser = XML_ParserCreate(NULL);
xmlfd = open(uwsgi.xml_config, O_RDONLY);
if (xmlfd < 0) {
uwsgi_error("open()");
exit(1);
}
if (fstat(xmlfd, &stat_buf)) {
uwsgi_error("fstat()");
exit(1);
}
xmlbuf = malloc(stat_buf.st_size);
if (!xmlbuf) {
uwsgi_error("malloc()");
exit(1);
}
rlen = read(xmlfd, xmlbuf, stat_buf.st_size);
if (rlen != stat_buf.st_size) {
uwsgi_error("read()");
exit(1);
}
close(xmlfd);
if (long_options) {
XML_SetUserData(parser, long_options);
XML_SetElementHandler(parser, uwsgi_startElement, uwsgi_endElement);
XML_SetCharacterDataHandler(parser, uwsgi_textHandler);
}
else {
XML_SetUserData(parser, wsgi_req);
XML_SetElementHandler(parser, uwsgi_startApp, uwsgi_endApp);
XML_SetCharacterDataHandler(parser, uwsgi_textApp);
}
if (!XML_Parse(parser, xmlbuf, stat_buf.st_size, 1)) {
uwsgi_log( "%s at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)), (int) XML_GetCurrentLineNumber(parser));
exit(1);
}
if (!long_options) {
XML_ParserFree(parser);
free(xmlbuf);
}
}
#endif
#else
#warning "*** XML configuration support is disabled ***"
#endif