Compare commits

..
1370 Commits
Author SHA1 Message Date
roberto@precise64 6692276472 uWSGI 1.2 2012-04-30 11:05:08 +02:00
roberto@mrspurr 81c09a9c9c report signum in worker's death 2012-04-29 05:04:19 +02:00
roberto@precise64 6a0a367ec3 added a test for gevent + threads 2012-04-26 15:11:52 +02:00
roberto@precise64 bdf533d62b fixed auto-reloading 2012-04-26 14:51:39 +02:00
roberto@precise64 1aba0bc26c completed --if-reload//--if-not-reload 2012-04-26 09:40:20 +02:00
roberto@precise64 aac6e9a365 fixed ruby -bash 2012-04-26 09:26:33 +02:00
roberto@precise64 9da732d96c added --if-reload/--if-not-reload and --unenv 2012-04-26 09:17:45 +02:00
roberto@precise64 328ba43ed2 fix uninitialzied structure 2012-04-25 17:55:47 +02:00
roberto@freebsd9 62d3253b02 fix kqueue() usage 2012-04-25 15:02:19 +02:00
roberto@mrspurr e5ba01e707 fixed socket in non-blocking mode 2012-04-25 14:18:40 +02:00
roberto@openbsd51 82c25f7f8c better execinfo detection 2012-04-25 11:00:25 +02:00
roberto@precise64 8791866ea0 added ebug infos for touch checks 2012-04-25 08:37:23 +02:00
roberto@opensuse12 8f10b8fece fix python version printing on freeky systems 2012-04-25 08:11:12 +02:00
roberto@opensuse12 0d28d210d4 another opensuse-related fix, build mimedict only if needed 2012-04-25 08:02:24 +02:00
roberto@precise 2368a5a050 fixed bug 121 2012-04-25 07:21:28 +02:00
roberto@precise64 74a9b1b41d added uwsgi.ready() 2012-04-24 21:50:00 +02:00
roberto@precise64 672c49e8eb refactored signal handling 2012-04-24 21:27:43 +02:00
roberto@precise64 225db32636 threading support for gevent 2012-04-24 19:23:14 +02:00
roberto@opensuse12 01541e4a50 fixed bug #120 2012-04-24 18:53:38 +02:00
roberto@precise64 357e260b45 some minor cleanup spotted by marcin deranek 2012-04-20 16:27:00 +02:00
roberto@centos32 a2513b1851 put a \0 at the end of process name 2012-04-20 16:11:16 +02:00
roberto@precise64 bbe8604054 added hack for ruby -bash 2012-04-20 14:11:08 +02:00
roberto@precise64 58a33de7f7 Added tag 1.2-rc2 for changeset 29de0fb320bc 2012-04-20 10:11:59 +02:00
roberto@precise64 ab7abc6a48 added upstart socket activation support and applied git001 patch for additional include paths 2012-04-20 09:59:59 +02:00
roberto@mrspurr 4986bdf202 added --static-map2 2012-04-20 07:04:02 +02:00
roberto@precise64 11aaddac98 fixed --static-map to a file 2012-04-19 19:44:35 +02:00
roberto@precise64 da9b2b4378 added static-expires/static-expires-mtime 2012-04-19 19:22:00 +02:00
roberto@freebsd9 9771a98bc6 fixed a typecast in rack plugin 2012-04-18 15:47:55 +02:00
roberto@precise64 033ee5f4e9 fixed a typo 2012-04-18 14:38:30 +02:00
roberto@precise64 1383163627 import dummy_threading whenever threads are in place 2012-04-18 10:14:41 +02:00
roberto@precise64 1d31b35c4f export static_offload_threads in statistics 2012-04-18 08:01:48 +02:00
roberto@precise64 7b2cc757b2 fixed SERVER_PORT in zeromq 2012-04-18 00:54:43 +02:00
roberto@precise64 68cddd1c2e fixed REMOTE_ADDR in mongrel2 when protocol is tnetstring 2012-04-17 23:41:04 +02:00
roberto@goyle b2a9fbbc5c set offload threading stacksize to 512k 2012-04-17 22:26:32 +02:00
roberto@goyle 0fcb13b9f1 implemented offload static file serving 2012-04-17 22:01:54 +02:00
roberto@goyle 938a22ce2e multiple mime file support 2012-04-17 20:04:48 +02:00
roberto@goyle 2df5dbfe52 added support for expires header 2012-04-17 19:24:13 +02:00
roberto@goyle feed0d0faa fixed get_mime_type 2012-04-15 22:33:05 +02:00
roberto@goyle c8373d20a9 added a check for strlen in the cgi plugin 2012-04-15 17:42:28 +02:00
roberto@mrspurr 170267a04a fixed mod_Ruwsgi 2012-04-15 07:11:45 +02:00
roberto@precise64 bd5969db67 fix initial messages 2012-04-15 07:06:33 +02:00
roberto@precise64 02256c013c added --carbon-no-workers 2012-04-14 13:54:41 +02:00
roberto@precise64 89be9a0d4a Added tag 1.2-rc1 for changeset 24c8fe5a26e5 2012-04-14 12:55:03 +02:00
roberto@precise64 4e57a6e145 uWSGI 1.2-rc1 2012-04-14 12:54:48 +02:00
roberto@openindiana64 784434ef3e opeinindiana fixes 2012-04-14 12:24:04 +02:00
roberto@precise64 91273b2301 py-auto-reload-ignore 2012-04-14 11:48:27 +02:00
roberto@precise64 2bcc85a99f added support for REMOTE_ADDR in mongrel2/zeromq 2012-04-14 10:08:34 +02:00
roberto@precise64 b7e6da3392 added --write-errors-tolerance and --write-errors-exception-only 2012-04-14 09:11:52 +02:00
roberto@precise64 d934270a27 merge 2012-04-14 08:22:54 +02:00
roberto@fiorenzo ed5a268e1f fix reloading of gateways 2012-04-13 19:01:05 +02:00
roberto@fiorenzo 95beaa0a86 merge 2012-04-13 17:09:22 +02:00
roberto@fiorenzo 0d3bf93c76 fixed fd leak in daemonize 2012-04-13 17:08:52 +02:00
roberto@sirius 50fb43066a ported fastcgi and zeromq to the new api 2012-04-13 16:23:55 +02:00
roberto@centos4 c33ec8ff56 ported locking to obsolete kernels 2012-04-13 14:09:03 +02:00
roberto@mrspurr e6afeec8af fixed return value in cache sweeper thread 2012-04-13 15:57:07 +02:00
roberto@sirius 57b9bdb958 better write()/writev() management 2012-04-13 11:36:43 +02:00
roberto@precise64 315bcb72c9 applied nagios patch from github 2012-04-11 07:23:00 +02:00
roberto@precise64 6b2460c02f improved syslog 2012-04-11 07:20:58 +02:00
roberto@precise64 35bc999a59 correctly set bin_name in setup.py 2012-04-09 08:41:27 +02:00
roberto@precise64 f00ad75e45 added --emperor-magic-exec 2012-04-08 09:13:07 +02:00
roberto@openbsd51 6bfe8e5b41 openBSD fixes 2012-04-08 08:24:51 +02:00
roberto@precise64 d7e8fd7d06 a couple of typo 2012-04-07 21:17:09 +02:00
roberto@precise64 949a0c35d5 improve cache reliability and performance of the sweeper 2012-04-07 21:08:42 +02:00
roberto@precise64 d193d5572f add --cache-expire-freq 2012-04-06 16:09:58 +02:00
roberto@precise64 f79f7e44a7 fixed cache and queue locking 2012-04-06 15:54:29 +02:00
roberto@mrspurr 26db55aafd fixed --pyargv 2012-04-06 11:39:48 +02:00
roberto@mrspurr 9d405c6cb2 fixed locking in uwsgi.cache_exists 2012-04-06 10:28:02 +02:00
roberto@mrspurr cceee511f2 added support for reload-on-exception on PyPy and interval-based cron syntax 2012-04-06 07:40:21 +02:00
roberto@freebsd9 e2024ed2fd merge 2012-04-05 12:28:30 +02:00
roberto@freebsd9 add7e2ee0e added execinfo support for FreeBSD 2012-04-05 12:28:10 +02:00
roberto@precise64 0458aa8eb4 use ctime_r instead of ctime 2012-04-05 12:15:04 +02:00
roberto@freebsd9 9ff6be783a use posix semaphores on freebsd9 2012-04-05 06:22:02 +02:00
roberto@mrspurr 14c558559b pypy now has PyFile_FromFile 2012-04-05 05:52:58 +02:00
roberto@centos64 92c5dcb6f2 allows robust mutexes on older linux systems 2012-04-04 22:54:56 +02:00
roberto@precise64 ae31f349f7 added robust mutexes 2012-04-04 22:53:07 +02:00
roberto@centos64 ce2846d04f first pthread robust implementation 2012-04-04 21:48:34 +02:00
roberto@mrspurr 7a6c9a5fe4 merge 2012-04-04 17:29:39 +02:00
roberto@mrspurr 43c258ad48 support for virtualenv in pypy 2012-04-04 17:29:00 +02:00
roberto@precise64 8ba032adb2 added --spooler-max-tasks 2012-04-03 17:59:37 +02:00
roberto@precise64 1a61dfd4e0 ported mod_Ruwsgi to apache 2.4 2012-04-03 09:02:00 +02:00
roberto@precise64 8e150e77a8 ported mod_uwsgi to apache 2.4 2012-04-03 08:47:09 +02:00
roberto@goyle 729fa753fa remove unneded pypy ifdef 2012-04-02 19:33:33 +02:00
roberto@longshot bf6c552189 fixed python 2.4 2012-04-02 07:55:22 +02:00
roberto@precise64 e9dc987a95 revert wsgi.url_scheme 2012-04-02 07:48:20 +02:00
roberto@precise64 35d9a39100 fixed autoload 2012-04-01 06:14:09 +02:00
roberto@mrspurr a864c8d6ed fix pypy when no app is loaded 2012-03-31 18:06:03 +02:00
roberto@precise64 c2df8a099e added --python-auto-reload 2012-03-31 17:55:09 +02:00
roberto@precise64 878e9cb9ba reports microseconds in python profilers 2012-03-31 15:48:22 +02:00
roberto@precise64 3612ea2186 fixed a deadlock in get_mime_type 2012-03-30 21:15:14 +02:00
roberto@precise64 81f0f93d96 improved module aliasing 2012-03-30 10:17:30 +02:00
roberto@precise64 c2d7b65145 better error management in pymodule-alias 2012-03-29 12:59:50 +02:00
roberto@precise64 6274e82cea fix fastrouter subscription refcnt 2012-03-29 11:26:35 +02:00
roberto@precise64 66655c9429 php append options 2012-03-28 18:28:24 +02:00
roberto@precise64 f47c8553d5 added uwsgi_expand_path() 2012-03-28 16:48:17 +02:00
roberto@precise64 f2802d3332 gevent current_req fix 2012-03-28 16:22:18 +02:00
roberto@precise64 1a173c849f minor fixes for test suite 2012-03-28 12:40:20 +02:00
roberto@precise64 57d4cd9fc9 gevent fixes 2012-03-28 11:08:04 +02:00
roberto@precise64 f6b9345716 fixed a garbage in python_call 2012-03-28 10:21:20 +02:00
roberto@freebsd64 792cd01320 fixed daemonize 2012-03-28 09:34:37 +02:00
roberto@mrspurr 03bc7d0399 close bug 85 2012-03-28 09:00:53 +02:00
roberto@mrspurr ed8f0812d7 PyPy SUPPORT 2012-03-27 13:58:27 +02:00
roberto@precise64 196dc45d0b fixed zero socket (2) 2012-03-26 14:28:18 +02:00
roberto@precise64 f8ff906d1b fixed zero socket 2012-03-26 14:20:08 +02:00
roberto@precise64 bbf1b0eda5 merged pypy 2012-03-26 13:41:50 +02:00
roberto@precise64 6f811a4899 better realpath for static docroot 2012-03-26 13:41:18 +02:00
roberto@mrspurr c66957d685 first round of pypy patches 2012-03-26 10:46:12 +02:00
roberto@goyle 282b2d5ace lua fixes 2012-03-23 21:22:17 +01:00
roberto@precise64 6a73e3ae05 fixed rack.input read 2012-03-22 16:25:27 +01:00
roberto@precise64 5856d410fd second part of zerg fixes 2012-03-22 11:14:41 +01:00
roberto@precise64 08d9de54f0 uniq zerg sockets 2012-03-22 10:05:00 +01:00
roberto@precise64 af1f98131a --perl-no-die-catch 2012-03-22 08:32:11 +01:00
roberto@precise64 9cef49ec57 fixed perl caching, added uwsgi::signal 2012-03-22 08:26:33 +01:00
roberto@precise64 d60c6d50ec fixed plugin loading by symlink 2012-03-22 07:35:27 +01:00
roberto@precise64 f3fdec2739 completed --reload-on-exception* options 2012-03-21 20:37:03 +01:00
roberto@precise64 1a20f57b73 fixed --spooler-quiet 2012-03-21 20:28:08 +01:00
roberto@precise64 0fc74dac4d better GIL usage 2012-03-21 20:21:51 +01:00
roberto@precise64 4117dd91fc ported psycopg2 example to the new api 2012-03-21 19:53:40 +01:00
roberto@precise64 508ca0df39 add realpath() for php DOCUMENT_ROOT 2012-03-21 19:28:24 +01:00
roberto@precise64 a50e356beb more verbose php debug 2012-03-21 07:50:27 +01:00
roberto@precise64 a0b7237083 added --spooler-quiet 2012-03-20 15:42:10 +01:00
roberto@precise64 08afa73e69 spooler multiprocess fixes 2012-03-20 10:58:48 +01:00
roberto@precise64 b386317921 fixed python3 reload-on-exception 2012-03-19 13:39:07 +01:00
roberto@precise64 2043127f22 fixed snmp support 2012-03-19 07:29:39 +01:00
roberto@precise64 c297a9415b started 1.2 development cycle 2012-03-18 09:03:14 +01:00
roberto@precise64 f9f9f25a01 added exception detection 2012-03-18 08:21:45 +01:00
roberto@precise64 9001af1beb better uuid detection 2012-03-17 11:01:01 +01:00
roberto@debian32 4b03f17186 python 3.x fix 2012-03-17 10:36:06 +01:00
roberto@precise64 3dbab36b91 uWSGI 1.1 2012-03-17 07:56:09 +01:00
roberto@precise64 056c890845 Added tag 1.1 for changeset e1568fd16b7b 2012-03-17 07:39:33 +01:00
roberto@precise64 4f43cd74ad env must not be immediate 2012-03-16 20:53:03 +01:00
roberto@precise64 6585b7b13d fixed pifile 2012-03-16 13:38:26 +01:00
roberto@precise64 e55048b574 fixed logdate 2012-03-16 13:07:06 +01:00
roberto@mercury 570dcde654 report listen_queue_errors 2012-03-16 06:52:48 +01:00
roberto@precise64 3cb16ee29b ready for 1.1 release 2012-03-15 20:42:41 +01:00
roberto@mailcop3 bb453da5b5 added support for SIOBKLGQ 2012-03-15 20:40:26 +01:00
roberto@precise64 1a93b68664 fixed expire_timeouts in fastrouter 2012-03-15 17:44:56 +01:00
roberto@precise64 2ce2494a50 bumped to -rc4 2012-03-15 17:36:59 +01:00
roberto@precise64 0a1e451289 Added tag 1.1-rc4 for changeset ef99144291f0 2012-03-15 17:31:05 +01:00
roberto@precise64 8ef7819080 re-included WSGI iterator close() 2012-03-15 17:29:55 +01:00
roberto@precise64 319ad13af2 allows plugin 255 to be used 2012-03-15 08:58:41 +01:00
roberto@precise4 fe28e90ae3 fixed a bug in spooler and signal plugin 2012-03-15 08:48:26 +01:00
roberto f604a0a533 bumped to 1.1-rc3 2012-03-14 18:30:19 +01:00
roberto@precise64 4ab78d42a3 Added tag 1.1-rc3 for changeset ede5c664978b 2012-03-14 18:30:02 +01:00
roberto@precise64 c631e7dae6 fixed multiple touch-reload 2012-03-14 18:29:04 +01:00
roberto@precise da8e88d638 Added tag 1.1-rc2 for changeset 901f0cb5de36 2012-03-14 12:08:58 +01:00
roberto@precise64 4707d9250d queue/cache fix 2012-03-14 11:34:51 +01:00
roberto@precise64 d719960411 fixed emperor amqp 2012-03-14 10:03:54 +01:00
roberto@precise64 734818c995 fixed shared sockets 2012-03-14 08:28:25 +01:00
roberto@precise64 a35335a820 fixed lua plugin 2012-03-12 18:54:04 +01:00
roberto@precise64 aca4dbfbe7 fixed threading rpc 2012-03-12 14:54:59 +01:00
roberto@precise64 b036029b32 another locking fix 2012-03-12 09:58:02 +01:00
roberto@freebsd64 52f3e757ed added --ftok 2012-03-12 09:40:56 +01:00
roberto@precise64 c4ce1cf7d8 appliead Riccardo's patches 2012-03-11 20:10:04 +01:00
roberto@icarus 48175d0759 various fixed for php and cgi plugins, added notfound plugin 2012-03-11 17:21:53 +00:00
roberto@precise64 2932168db7 Added tag 1.1-rc1 for changeset 1d1702789710 2012-03-10 15:23:47 +01:00
roberto@precise64 e8d96b8f84 completed ldap support 2012-03-10 15:21:08 +01:00
roberto@precise64 bd15fd9da1 fixed ldap support 2012-03-10 14:30:48 +01:00
roberto@precise64 6e98eda963 set version to 1.1, only LDAP missing 2012-03-10 13:34:17 +01:00
roberto@precise64 ec9bb3601e added --flock/--flock2/--flock-wait/--flock-wait2 2012-03-10 13:26:45 +01:00
roberto@precise64 02e4840b29 re-added --ignore-sigpipe 2012-03-10 12:34:45 +01:00
roberto@precise64 d7e8523fcf do not call atexit hooks in async mode 2012-03-10 12:06:19 +01:00
roberto@precise64 41464c3bfa fr sctp fix 2012-03-10 11:35:05 +01:00
roberto@goyle a3617d0b5a fastrouter heavy optimization 2012-03-10 11:25:19 +01:00
roberto@centos6 10ff849ebd fixed permissions of files 2012-03-07 15:06:38 +01:00
roberto@centos6 c2f7d487d0 initgroups() usage 2012-03-07 04:40:16 +01:00
roberto@centos6 395cf57e21 added stats for sctp fastrouter 2012-03-07 02:55:48 +01:00
roberto@centos6 4c854a83c9 SCTP improvements, rack optimizations 2012-03-07 01:40:57 +01:00
roberto@centos6 881b3b7e0c another series of SCTP fixes 2012-03-06 16:43:41 +01:00
roberto@openbsd50 bb28e4279b fixed cgi cast of FILE 2012-03-06 15:22:38 +01:00
roberto@openbsd50 c65b8ce162 various fixes 2012-03-06 15:20:25 +01:00
roberto@openindiana 8a303b1965 solaris fixes 2012-03-06 12:19:29 +01:00
roberto@centos6 adca811941 fixed 105 2012-03-06 11:34:56 +01:00
roberto@goyle f79e9d8773 fixed a typo 2012-03-05 16:22:20 +01:00
roberto@precise64 629fbf4f07 another series of sctp patch 2012-03-05 04:29:11 +01:00
roberto@precise64 da9ce52294 little refactoring for the fastrouter 2012-03-04 16:10:35 +01:00
roberto@precise64 205605a3c4 fixed PATH_INFO in php 2012-03-03 17:34:44 +01:00
roberto@precise64 e39127be92 ready for rc 2012-03-03 16:31:26 +01:00
roberto@precise64 0b2458d74a SCTP is experimenta, stop development til 1.1 release 2012-03-03 16:17:16 +01:00
roberto@precise64 9d661122bd added experimental SCTP/persistent connections support 2012-03-03 13:46:21 +01:00
roberto@precise64 8518747a51 try to reduce spooler wait 2012-03-03 09:35:46 +01:00
roberto@precise64 2f6450a560 <app> tag usage will be removed in uWSGI 1.2 2012-03-02 08:27:52 +01:00
roberto@precise64 c72889c10f added --daemonize2 2012-03-02 07:31:20 +01:00
roberto@precise64 bb7456e3f8 gateways structure is again shared 2012-03-01 21:27:17 +01:00
roberto@precise64 5aff13543e another fastrouter fix 2012-03-01 20:11:06 +01:00
roberto@precise64 c7d967d43c fixed python 3 2012-03-01 18:30:32 +01:00
roberto@precise64 1a42194304 added ruby rvm/gemset support 2012-03-01 18:22:25 +01:00
roberto@precise64 312563437c multiprocess spooler 2012-03-01 14:54:10 +01:00
roberto@precise64 5972ac1ed7 fixed permission in ipcsem 2012-03-01 11:11:51 +01:00
roberto@precise64 75d4123b34 added locking test 2012-03-01 11:06:53 +01:00
roberto@precise64 89ef4f68a9 added ipcsem 2012-03-01 11:06:00 +01:00
roberto@precise64 ed72677e52 even fcntl is broken 2012-03-01 09:51:31 +01:00
roberto@precise64 08ab27c36c cache_get optimization 2012-03-01 09:15:43 +01:00
roberto@precise64 af8bb8fd05 fixed locking in multithread 2012-03-01 09:06:02 +01:00
roberto@precise64 57bade7eae close stdin in vassals 2012-02-29 14:57:44 +01:00
roberto@mishmash 3c6de0e84d various fastrouter fixes 2012-02-29 10:14:44 +01:00
roberto@precise64 24e3fea334 added fd:// to corerouter bind subsystem 2012-02-29 08:47:52 +01:00
roberto@precise64 6af77aab8b added --fastrouter-gracetime 2012-02-29 07:46:24 +01:00
roberto@precise64 12325633ed fastrouter improvements 2012-02-29 07:04:14 +01:00
roberto@sirius 3a108b61ee fixed pause reporting 2012-02-28 18:56:32 +01:00
roberto@goyle b2eaf384ac --fastrouter-fallback 2012-02-28 18:08:40 +01:00
roberto@precise64 3d17ef9603 lockf for sun 2012-02-28 10:31:24 +01:00
roberto@precise64 3b031872f7 lockf for sun 2012-02-28 10:30:07 +01:00
roberto@precise64 e97d39f37c prepared umtx for future implementations 2012-02-28 09:21:44 +01:00
roberto@sirius 763f715279 ported locking api to OSX 2012-02-28 09:18:41 +01:00
roberto@precise64 af9f79f3eb ported new locking api to linux 2012-02-28 09:14:08 +01:00
roberto@freebsd64 01ab3e2895 broken commit for new locking api 2012-02-28 09:05:37 +01:00
roberto@precise64 7a34344632 fixed a bug in setrlimit 2012-02-27 20:21:55 +01:00
roberto@precise64 9714cb6790 fixed log flush 2012-02-27 19:48:35 +01:00
roberto@precise64 aa981d03e8 reintroduce the remote spooler plugin [2] 2012-02-27 15:59:47 +01:00
roberto@precise64 9a09164fc3 reintroduce the remote spooler plugin 2012-02-27 15:59:07 +01:00
roberto@precise64 9674a81323 added --forkbomb-delay 2012-02-27 14:38:49 +01:00
roberto@precise64 aba7280691 added --need-app 2012-02-27 14:27:34 +01:00
roberto@precise64 ef9908b058 fixed --cluster-reload and --cluster-log 2012-02-26 12:35:05 +01:00
roberto@precise64 4da4fb4cbd completed clustering porting 2012-02-26 12:30:35 +01:00
roberto@precise64 b4f8a3b179 fixed bug #62 2012-02-26 09:07:14 +01:00
roberto@precise64 b48a955848 fixed paste logging 2012-02-26 08:57:43 +01:00
roberto@precise64 5ea4e3bcc3 removed url from setup.py 2012-02-26 08:26:21 +01:00
roberto@precise64 6732cb01a8 free libxml2 resources on exit 2012-02-26 08:05:39 +01:00
roberto@precise64 0b5ca736d4 re-added expat support 2012-02-25 20:26:17 +01:00
roberto@precise64 a2358c6bec completed porting of the http plugin to the new api 2012-02-25 18:36:04 +01:00
roberto@precise64 10775dd2ac another series of http ports 2012-02-25 18:24:56 +01:00
roberto@precise64 d33d12c642 ported --http-var 2012-02-25 18:20:59 +01:00
roberto@precise64 af3ccfeed4 added negative configlogic 2012-02-25 09:24:07 +01:00
roberto@precise64 1d64267aba added --check-static-docroot 2012-02-25 08:44:00 +01:00
roberto@cable 9bbef9b0c5 various condition build fixes 2012-02-25 08:34:11 +01:00
roberto@precise64 c95ec82b03 a series of php/cgi fixes 2012-02-24 12:12:19 +01:00
roberto@precise64 46108a00f0 fixed startup time in rack plugin 2012-02-24 09:37:33 +01:00
roberto@precise64 d6c3fd7771 --php-app added 2012-02-24 09:26:57 +01:00
roberto@precise64 ad783ccaf0 added script for external app loading 2012-02-24 06:49:54 +01:00
roberto@precise64 f58be4241f added cheaper_backlog2 example 2012-02-23 21:46:27 +01:00
roberto@precise64 cb1d22d88b added pluggable cheaper algorithms 2012-02-23 21:38:53 +01:00
roberto@precise64 6c8453d98e another logging refactoring 2012-02-23 20:42:00 +01:00
roberto@colossus 061de3b037 merge 2012-02-23 18:16:38 +01:00
roberto@colossus ded065ef38 php-server-software 2012-02-23 18:16:18 +01:00
roberto@precise64 822959238c fixed a bug with --set 2012-02-23 16:58:36 +01:00
roberto@precise64 4ebb9d7b46 faster restart thanks to single getrlimit call 2012-02-23 14:13:38 +01:00
roberto@precise64 cc49964c43 fixed a lost null pointer 2012-02-23 07:51:36 +01:00
roberto@precise64 3787d5e84a flush logs on exit 2012-02-23 07:48:54 +01:00
roberto@precise64 7329606a6a added a cast (just to be sure) 2012-02-22 17:11:12 +01:00
roberto@precise64 5facafadea added uwsgi api support for php 2012-02-22 16:44:56 +01:00
roberto@precise64 d3102df2bf added a signal handler for FPE 2012-02-22 12:00:32 +01:00
roberto@precise64 87860da238 better loaded app reporting 2012-02-22 11:55:06 +01:00
roberto@precise64 4a8aa01f40 added startup time for apps 2012-02-22 11:39:19 +01:00
roberto@longshot 9d35067b4b allows custom php-config path 2012-02-22 10:33:45 +01:00
roberto@precise64 1c29be3745 fix php uwsgi.h include 2012-02-20 04:07:16 +01:00
roberto@centos6 bf3c3a3768 another php update 2012-02-19 17:52:17 +01:00
roberto@fedora32 b25de79ae4 completed new php plugin 2012-02-19 15:44:23 +01:00
roberto@precise64 ba663ef2cc ready for new php plugin 2012-02-19 11:08:52 +01:00
roberto@precise64 19185640a5 fixed a typo 2012-02-18 16:29:21 +01:00
roberto@precise64 eafe8c4fff new cheaper implementation 2012-02-18 16:28:01 +01:00
roberto@precise64 bdd3e69024 removed some funny debug log 2012-02-18 11:40:25 +01:00
roberto@precise64 b5a7ab3688 fixed paste logging 2012-02-18 09:32:39 +01:00
roberto@centos64 cc0fa8dee6 fixed rack build 2012-02-18 08:55:35 +01:00
roberto@precise64 14941cc1c0 deprecate <app> 2012-02-18 08:40:36 +01:00
roberto@precise64 910cb3a790 fixed single-intepreter mode 2012-02-18 08:32:53 +01:00
roberto@precise64 355e989eea refactored xmlconf 2012-02-18 08:07:48 +01:00
roberto@precise64 bfcd9dad25 removed useless makefiles 2012-02-18 07:37:48 +01:00
roberto@precise64 73ed5fd7cf added --auto-weight 2012-02-18 07:25:11 +01:00
roberto@netbsd64 d21cc0970c NetBSD fixes 2012-02-18 08:16:37 +01:00
roberto@precise64 eb8b03139d master_loop function is becoming extremely huge, time to refactor it... 2012-02-17 20:36:04 +01:00
roberto@precise64 1558145985 refactored uwsgi_reload() 2012-02-17 20:23:29 +01:00
roberto@precise64 4ea9a29e62 fixed some typo in comments 2012-02-17 20:09:54 +01:00
roberto@precise64 72c8d9cd5e refactored/reimplemented cheaper mode 2012-02-17 19:04:32 +01:00
roberto@precise64 fb4fc38f14 better umask handling 2012-02-17 17:58:46 +01:00
roberto@precise64 de25db9e75 fixed shared sockets for http and fastrouter plugins 2012-02-17 17:48:57 +01:00
roberto@precise64 4ba558430d added wrr to fastrouter/subscription 2012-02-17 13:57:46 +01:00
roberto@precise64 e4711484ac fixed a stupid deadlock 2012-02-17 11:21:08 +01:00
roberto@precise64 5081a3f635 placed a mutex in threaded logger trying to fix #84 2012-02-17 09:50:56 +01:00
roberto@precise64 b31fa366a2 make older gcc happy for gevent 2012-02-17 07:05:26 +01:00
roberto@precise64 c1b24b390a fixed unsubscribe 2012-02-16 20:13:36 +01:00
roberto@precise64 b7461442b0 added a report on unsubscribe 2012-02-16 16:56:08 +01:00
roberto@precise64 c072e9b609 added stacktrace to perl errors 2012-02-16 11:31:52 +01:00
roberto@precise64 5236c58255 added new routing rules 2012-02-16 09:04:59 +01:00
roberto@precise64 4f5280ea2b zeromq/mongrel2 improvements 2012-02-16 07:33:31 +01:00
roberto@precise64 4d1c3fcaea added UWSGI_APPID management in router_uwsgi 2012-02-16 07:22:13 +01:00
roberto@precise64 310acaf4cc do not inizialize request plugins if not needed 2012-02-15 21:28:12 +01:00
roberto@precise64 8111acaad1 completed new perl infrastructure 2012-02-15 20:34:52 +01:00
roberto@mrspurr c80b10d2b2 fixes for non ithreads perl 2012-02-15 19:55:43 +01:00
roberto@precise64 9807192bd1 thread-safe perl multi-app support 2012-02-15 18:10:22 +01:00
roberto@precise64 9386c97851 added perl multiple interpreter support (non-thread-safe) 2012-02-15 14:10:33 +01:00
roberto@precise64 7f3e9b10c4 merge 2012-02-15 05:03:56 +01:00
roberto@precise64 360719582b fix #91 2012-02-15 05:03:15 +01:00
roberto@sirius a1a6d4a248 fxed the carbon plugin 2012-02-14 16:20:34 +01:00
roberto@precise64 015ea78927 set correct status in routers 2012-02-13 19:27:42 +01:00
roberto@precise64 ad32841aaa fixed wrong definition of --route option 2012-02-13 19:22:32 +01:00
roberto@precise64 2a3771dccf added blacklist/whitelist support for options 2012-02-13 16:55:48 +01:00
roberto@precise64 26af8af48f fixed port handling in fastrouter stats 2012-02-13 11:54:03 +01:00
roberto@precise64 5829c3a843 new plugin infrastructure 2012-02-13 11:40:06 +01:00
roberto@goyle c723d6d9d5 non-linux fix 2012-02-13 07:56:59 +01:00
roberto@oneiric64 2c0c9a918a fixed a stupid bug in uniq_warning 2012-02-13 06:41:27 +01:00
roberto@precise64 8f9bc7170e added zergpool pluin 2012-02-12 17:20:51 +01:00
roberto@precise64 ee002167d4 improved zergpool 2012-02-12 17:17:19 +01:00
roberto@precise64 4ddeb26cca extended zerg mode to support an unlimited number of sockets 2012-02-12 13:16:58 +01:00
roberto@precise64 a1514e2eaf added another config style for basicauth 2012-02-12 10:11:39 +01:00
roberto@precise64 5d1c7ab8b0 fixed a race condition in cheaper + threads 2012-02-12 09:42:17 +01:00
roberto@precise64 27698e34f5 added protected.ini 2012-02-12 09:28:19 +01:00
roberto@precise64 c06b4773c7 thread-safe basicauth 2012-02-12 09:26:38 +01:00
roberto@mrspurr e431936a8e python set() is not good 2012-02-12 08:43:21 +01:00
roberto@precise64 de3d22a401 preliminary support for http basic auth (real) 2012-02-12 08:35:21 +01:00
roberto@precise64 22778d9de7 preliminary support for http basic auth 2012-02-12 08:34:14 +01:00
roberto@precise64 069f517b04 added --zerg-fallback 2012-02-11 21:02:15 +01:00
roberto@precise64 1017dda1ec merge 2012-02-11 17:50:20 +01:00
roberto@centos64 581b4a4216 off by one fix 2012-02-11 17:40:41 +01:00
roberto@precise64 e1f00cbf96 better erlang detection 2012-02-11 17:20:47 +01:00
roberto@centos64 32ad0a7b87 build improvements 2012-02-11 14:17:00 +01:00
roberto@oneiric64 aa4b9b16fb fixed magic_table handling 2012-02-10 16:14:44 +01:00
roberto@oneiric64 73721ab73a disable write-strings 2012-02-10 15:27:02 +01:00
roberto@oneiric64 90cc3dc389 fixed rack build 2012-02-10 12:37:07 +01:00
roberto@oneiric64 f4f4d5a6c0 python atexit improvements from mod_wsgi 2012-02-10 11:18:53 +01:00
roberto@oneiric64 4bd2410ee7 added support for logic in config directives with a first 'for' implementation 2012-02-10 09:06:09 +01:00
roberto@gambit 6bc264d33b various fixes for better cgi routing support 2012-02-09 13:00:27 +01:00
roberto@gambit c7d1c6818b fixed touch-reload 2012-02-09 12:32:31 +01:00
roberto@oneiric64 937e68bf67 another lock fix 2012-02-08 12:56:46 +01:00
roberto@oneiric64 434fb96be7 another fix in locking subsystem 2012-02-08 12:49:06 +01:00
roberto@oneiric64 e2fe86027c improved pyargv management 2012-02-08 12:19:14 +01:00
roberto@oneiric64 06ca891d94 fixed threading in command mode 2012-02-08 11:54:15 +01:00
roberto@oneiric64 57c00c9b12 set to_hell in command mode 2012-02-08 11:41:01 +01:00
roberto@sirius b320e1e222 disable master process in command mode 2012-02-08 11:15:29 +01:00
roberto@sirius c72ddc9dd8 added command mode 2012-02-08 11:01:04 +01:00
roberto@oneiric64 c37a386674 added uwsgi.is_locked 2012-02-07 16:40:25 +01:00
roberto@oneiric64 ad6a79b5b7 remove -Wwrite-strings 2012-02-07 16:09:45 +01:00
roberto@oneiric64 ff733cd50b fixed logto 2012-02-07 15:37:19 +01:00
roberto@oneiric64 53128a2391 fixed daemonize and cron 2012-02-07 15:32:34 +01:00
roberto@oneiric64 d01fc8804c fixed a stupid bug in cron management 2012-02-07 14:36:26 +01:00
roberto@oneiric64 e520d7a58f fixed mules signal handling 2012-02-07 12:38:37 +01:00
roberto@freebsd64 7846ea636c ported new locking api to freebsd 2012-02-07 12:09:20 +01:00
roberto@mrspurr 0025ad8329 ported new lock api to OSX 2012-02-07 12:03:50 +01:00
roberto@oneiric64 1a1f270f4e completed locking refactoring on linux 2012-02-07 11:56:19 +01:00
roberto@oneiric64 517f4498f5 another locking refactoring 2012-02-07 11:10:20 +01:00
roberto@oneiric64 87a165477f fixed disable logging 2012-02-07 05:34:28 +01:00
roberto@oneiric64 1e657f0b77 plugins loading fix 2012-02-07 05:26:51 +01:00
roberto@oneiric64 a8e399db1e psgi fixes 2012-02-07 05:08:53 +01:00
roberto@oneiric64 66f9607404 various fixes reported by Lukasz Mierzwa 2012-02-07 03:20:10 +01:00
roberto@oneiric64 27319c2da3 ported --http-manage-expect to new options api 2012-02-06 17:23:22 +01:00
roberto@oneiric64 de21abb21c ported jvm plugin to the new options api 2012-02-06 17:17:26 +01:00
roberto@oneiric64 94cae4ac17 completed php porting to the new api 2012-02-06 17:01:16 +01:00
roberto@oneiric64 3b5e1f98f5 completed fastrouter porting to the new options api 2012-02-06 16:56:06 +01:00
roberto@oneiric64 594f67c6d7 added support for paste loggers 2012-02-06 16:29:04 +01:00
roberto@oneiric64 f1b415df2f completed python plugin porting to the new options api 2012-02-06 16:14:15 +01:00
roberto@oneiric64 c07e0ef581 --touch-logreopen and --touch-logrotate 2012-02-06 16:00:51 +01:00
roberto@goyle 0d4f6501b0 ported backtrace to osx 2012-02-06 11:38:56 +01:00
roberto@goyle d2cbb7eea2 allow non-pcre build 2012-02-06 11:02:57 +01:00
roberto@oneiric64 f4cb3c67c1 a series of stupid fixes 2012-02-05 11:56:50 +01:00
roberto@oneiric64 a51877cd1d another series of options fixes/porting 2012-02-05 11:50:33 +01:00
roberto@oneiric64 c0c3287f74 fully ported cgi plugin to the new options api 2012-02-05 11:44:18 +01:00
roberto@oneiric64 83378802af completed porting perl/psgi to new options api 2012-02-05 11:25:39 +01:00
roberto f05d712923 completed ruby/rack porting to the new options api 2012-02-05 11:20:19 +01:00
roberto@freebsd64 5b2df55b8e ported freebsd to the new locking api 2012-02-05 11:07:40 +01:00
roberto@oneiric64 865ec4dd8f added internal routing subsystem 2012-02-05 10:43:03 +01:00
roberto@oneiric64 6ddf1afc81 ported --http-use-cache to the new api 2012-02-04 16:20:37 +01:00
roberto@mrspurr 7bd44f4f14 added internal routing infrastructure 2012-02-04 16:10:32 +01:00
roberto@goyle a92c2003ee prepare for new routing system 2012-02-02 18:20:10 +01:00
roberto@debian64 97a8c5e4b6 another fix for pyargv 2012-02-02 11:40:52 +01:00
roberto@debian64 a5aa31f13e applied ticket #82 2012-02-02 11:25:44 +01:00
roberto@debian64 1a0161cb6b fixed pyargv 2012-02-02 11:14:34 +01:00
roberto@debian64 b8c17baf7c fixed pythonpath 2012-02-02 11:08:02 +01:00
roberto@debian64 e161ea3f0a another fix for locking 2012-02-02 11:04:51 +01:00
roberto@debian64 fb827a274b started porting rack plugin to the new options api 2012-02-02 10:29:31 +01:00
roberto@debian64 7281318ef6 fixed bug #79 2012-02-02 10:20:57 +01:00
roberto@debian64 80be7385ed fixed locking 2012-02-02 09:59:48 +01:00
roberto@debian64 8913dda413 added uwsgi_tmpname() 2012-02-02 09:07:39 +01:00
roberto@debian64 b8ad90104b another series of fastrouter patches 2012-02-02 09:01:53 +01:00
roberto@debian64 2646109986 ported --fastrouter option 2012-02-02 08:56:47 +01:00
roberto@oneiric64 cf247c828a fixed emperor reload in lazy mode 2012-02-01 17:53:50 +01:00
roberto@debian64 28106e624e fixed http protocol bug 2012-02-01 16:41:50 +01:00
roberto@debian64 30e8420342 added --cheaper-overload 2012-02-01 16:07:29 +01:00
roberto@debian64 99e4d55e9b ported pthread mutex to the new api 2012-02-01 15:32:33 +01:00
roberto@goyle f9daec9e43 implementation of lock detector 2012-02-01 14:30:26 +01:00
roberto@goyle 68a2902ce3 fixed readlink in binary path 2012-01-31 11:46:30 +01:00
roberto@goyle 4b2db3de57 started revamp of the JVM plugin 2012-01-31 11:15:05 +01:00
roberto@goyle c4c526df17 fixed gateways in non-master mode 2012-01-31 11:03:19 +01:00
roberto@goyle 15ad5531b0 another series of updates 2012-01-31 10:54:29 +01:00
roberto@goyle c0af1c1094 ported rrdtool plugin 2012-01-31 10:44:28 +01:00
roberto@goyle 9b89333244 ported lua 2012-01-31 10:40:38 +01:00
roberto@goyle 1863030078 ported ping and nagios 2012-01-31 10:38:44 +01:00
roberto@goyle 15055ffa0d ported psgi to the new api 2012-01-31 10:31:46 +01:00
roberto@oneiric64 8391ce28f7 ported max vars to new options api 2012-01-30 11:09:59 +01:00
roberto@oneiric64 b38791a357 ported chmod-socket to new options api 2012-01-30 10:46:20 +01:00
roberto@oneiric64 53ba043168 ported logdate to new options api 2012-01-30 10:37:44 +01:00
roberto@oneiric64 d46a8dba7b ported snmp to new options api 2012-01-30 10:26:28 +01:00
roberto@oneiric64 1e62afc161 ported zerg to new options api 2012-01-30 09:33:59 +01:00
roberto@oneiric64 03cf6e868f ported mule subsystem to the new options api 2012-01-30 08:26:30 +01:00
roberto@oneiri64 e1da28ccc3 ported static file serving to the new options api 2012-01-30 08:21:04 +01:00
roberto@oneiric64 4173ca36cb ported map-socket to the new api 2012-01-30 08:05:52 +01:00
roberto@oneiric64 c393de492d ported ksm 2012-01-29 08:53:08 +01:00
roberto@oneiric64 f9a716d70f fixed dynamic options 2012-01-29 08:51:45 +01:00
roberto@oneiric64 2e8655c203 ported pidfile signal to the new api 2012-01-29 08:49:07 +01:00
roberto@oneiric64 42b7164f33 ported sqlite3 to the new api 2012-01-29 08:21:33 +01:00
roberto@oneiric64 602d49b045 ported cap/unshare to the new api 2012-01-29 08:04:05 +01:00
roberto@oneiric64 58a67df534 ported uid/gid to new api 2012-01-29 07:59:56 +01:00
roberto@oneiric64 de6cc04685 added exec:// facility 2012-01-29 07:52:39 +01:00
roberto@oneiric64 33763e074d ported spooler to the new options api 2012-01-28 17:40:24 +01:00
roberto@oneiric64 32b0f8efb6 ported queue and cache to new options api 2012-01-28 17:32:34 +01:00
roberto@oneiric64 644618963a another series of options porting 2012-01-28 17:14:49 +01:00
roberto@oneiric64 97ac31376e added --never-swap 2012-01-28 17:04:37 +01:00
roberto@oneiric64 e5ec0f0221 even simpler options hook 2012-01-28 16:37:20 +01:00
roberto@oneiric64 5875ddc355 refactored first part of clustering 2012-01-28 15:42:50 +01:00
roberto@oneiric64 f7d5f4692d another series of options ported to the new api 2012-01-28 15:14:41 +01:00
roberto@oneiric64 d85bc64aa9 ported uwsgi_help to the new api 2012-01-28 09:29:57 +01:00
roberto@oneiric64 a18ed0503c implemented flag subsystem for options 2012-01-28 08:57:17 +01:00
roberto@oneiric64 77a4e3771b ported plugin loading to the new api 2012-01-28 07:40:20 +01:00
roberto@oneiric64 7523eb1cb0 ported short options to new api 2012-01-27 19:37:37 +01:00
roberto@oneiric64 46f8ee9410 ported xml config to new option/help api 2012-01-27 18:24:55 +01:00
roberto@oneiric64 f0aa9f9fd2 another part of options refactoring 2012-01-27 17:54:31 +01:00
roberto@oneiric64 73d5cadd8c massive refactoring of options management (broken, do not use this rev) 2012-01-27 16:30:00 +01:00
roberto@oneiric64 1a0e2076d5 restore termios on exit (if required) 2012-01-25 07:19:25 +01:00
roberto@oneiric64 6db3dab5ea added --pyshell-oneshot 2012-01-25 06:32:02 +01:00
roberto@oneiric64 20856549c1 fixed a double free in spooler 2012-01-24 21:33:24 +01:00
roberto@oneiric64 d570845592 fixed sigquit/sigint in hijacked mode 2012-01-24 21:13:24 +01:00
roberto@oneiric64 eed27c0aac implemented rack.input.gets and expect-continue in http router 2012-01-24 21:11:17 +01:00
roberto@oneiric64 daef139496 added --http-manage-expect 2012-01-24 18:57:29 +01:00
roberto@oneiric64 3690d836b0 another refactoring of corerouter 2012-01-23 17:36:59 +01:00
roberto@oneiric64 93faeb4177 first round of common code base for routers 2012-01-23 16:04:10 +01:00
roberto@oneiric64 095b9154e0 fixed signal handling in gateways 2012-01-23 12:33:57 +01:00
roberto@oneiric64 f86aa55220 destructive commit for http and fastrouter plugins 2012-01-23 12:13:05 +01:00
roberto@oneiric64 40f7aecbba fixed a race condition in SIGINT/SIGQUIT 2012-01-22 17:55:09 +01:00
roberto@oneiric64 5d9d67caa4 preliminary refactoring for multithreaded fastrouter/removed fastfuncs support 2012-01-22 11:48:13 +01:00
roberto@oneiric64 0f00d6fb23 added --fastrouter-post-buffering-dir 2012-01-21 17:36:15 +01:00
roberto@oneiric64 61b0e68641 added UWSGI_POSTFILE 2012-01-21 04:26:02 +01:00
roberto@oneiric64 6ed38ced3c preliminary infrastructure for fastrouter buffering 2012-01-21 03:02:09 +01:00
roberto@app2 7a681a97b5 added --exec-in-jail 2012-01-20 16:55:54 +00:00
roberto@app2 41008fa594 fix a bunch of spooler issue 2012-01-20 15:16:47 +00:00
roberto@oneiric64 fb13084b87 applied patch #76 by prymitive 2012-01-20 10:59:39 +01:00
roberto@oneiric64 3f9023281e added --exec-pre-jail and --exec-post-jail 2012-01-20 09:18:18 +01:00
roberto@oneiric64 4e21fe6607 fix uwsgi.atexit when threading mode is enabled 2012-01-18 05:01:22 +01:00
roberto@oneiric64 7a95c726cd segmentation fault manager (linux only) 2012-01-15 04:33:19 +01:00
roberto@oneiric64 940401e0f8 second round of multispooler patches 2012-01-14 06:56:11 +01:00
roberto@oneiric64 86bfb20903 applied first part of multispooler patch 2012-01-14 06:00:33 +01:00
roberto@oneiric64 e21cf87285 fixed atexit 2012-01-13 04:26:20 +01:00
roberto@oneiric64 65f1445b64 bumped to 1.1 and added uwsgi.atexit 2012-01-12 19:25:54 +01:00
roberto@oneiric64 f87761d092 fix for invalid --http address 2012-01-11 11:14:31 +01:00
roberto@oneiric64 0c712ac28d added --no-harakiri-arh 2012-01-11 05:05:15 +01:00
roberto@oneiric64 db301531d0 added uwsgi.after_req_hook 2012-01-10 20:30:46 +01:00
roberto@oneiric64 4c82a72fd5 FreeBSD9 fix 2012-01-10 19:08:00 +01:00
roberto@oneiric64 7417e582c3 a fix for subscription system 2012-01-10 18:06:46 +01:00
roberto@oneiric64 e32564c7b2 added --fastrouter-harakiri 2012-01-10 15:58:49 +01:00
roberto@oneiric64 798bc482dc fixed a leak in cgi plugin 2012-01-10 14:00:36 +01:00
roberto@oneiric64 c7e7f756bc do not build netlink support by default 2012-01-10 13:43:13 +01:00
roberto@oneiric64 24358701f7 added Roy to contributors 2012-01-06 22:03:29 +01:00
roberto@netbsd64 f1e392c0a0 added support for post_buffering in cgi plugin 2012-01-06 22:57:58 +01:00
roberto@netbsd64 5e8d38d8bc support body_as_file in cgi plugin 2012-01-06 22:21:08 +01:00
roberto@oneiric64 4650d2edbb added support for indexed cgi vars 2012-01-06 19:36:42 +01:00
roberto@oneiric64 b153033514 fixed PATH_INFO and SCRIPT_NAME in cgi plugin 2012-01-06 18:23:07 +01:00
roberto@netbsd64 6dcbce5eb7 added binary detection for NetBSD 2012-01-05 22:47:50 +01:00
roberto@oneiric64 4ceeab439a fixed a typo 2012-01-05 21:14:45 +01:00
roberto@oneiric64 8b1a6be9da various realpath fixes 2012-01-05 21:10:02 +01:00
roberto@netbsd64 baeb864075 fixed #70 2012-01-05 21:28:47 +01:00
roberto@netbsd64 c88e1c3619 realpath on BSD is different from Linux/Solaris/OSX 2012-01-05 21:25:21 +01:00
roberto@oneiric64 1b04df7c5e Added tag 1.0.1 for changeset 8fe7bb792399 2012-01-03 17:12:16 +01:00
roberto@oneiric64 237f11dba3 fixed http protocol post optimization 2012-01-03 13:44:53 +01:00
roberto@oneiric64 313f1c2f29 make some gcc OSX version happy 2012-01-02 16:53:06 +01:00
roberto@oneiric64 f0862f3bc7 Added tag 1.0 for changeset 3c7092733585 2011-12-30 08:25:31 +01:00
roberto@oneiric64 1a8850ffe5 fixed cache monitor 2011-12-28 19:36:34 +01:00
roberto@genesi e640f812ba added cache monitor from Riccardo Magliocchetti in contrib/ 2011-12-28 04:32:21 +01:00
roberto@genesi 75ea170472 report hostname in welcome.py 2011-12-27 12:18:32 +01:00
roberto@debian32 1b14b1926e dded changelog for 1.0 2011-12-27 08:18:32 +01:00
roberto@oneiric64 edaed7ab01 fixed x-accel-redirect (temp workaround) 2011-12-26 08:26:14 +01:00
roberto@oneiric64 6cceece3d7 (really) fixed fibers plugin 2011-12-26 08:18:01 +01:00
roberto@oneiric64 2add03edb8 closed bug #67 2011-12-25 23:09:54 +01:00
roberto@oneiric64 7aab9bae51 report tiem delta in idle mode 2011-12-24 11:15:18 +01:00
roberto@oneiric64 46c2c1d885 moved version string to 1.0 2011-12-23 17:47:54 +01:00
roberto@oneiric64 544e97fac0 do not export original-proc-name in uwsgi.opt 2011-12-23 12:52:27 +01:00
roberto@oneiric64 265a700498 added --cheaper-step 2011-12-22 13:23:34 +01:00
roberto@oneiric64 a657b4b0aa Added tag 1.0-rc10 for changeset af490b8c30f8 2011-12-22 07:37:45 +01:00
roberto@oneiric64 ac97c8cf34 php plugin is now in beta 2011-12-21 15:46:23 +01:00
roberto@oneiric64 545f3ee608 gratily improved the php plugin 2011-12-21 15:00:14 +01:00
roberto@oneiric64 fcd1a36420 added --static-index 2011-12-21 11:02:36 +01:00
roberto@fiorenzo 47a8ab3da9 fixed fastrouter when nodes are on non-existent unix-socket 2011-12-21 11:00:45 +01:00
roberto@oneiric64 c4375a8e7a better ordering of options 2011-12-21 09:36:06 +01:00
roberto@oneiric64 a6c5bd3bb3 fixed optional-argument support 2011-12-21 07:56:19 +01:00
roberto@oneiric64 d53127e8cf fixed Makefile after php inclusion 2011-12-20 11:57:51 +01:00
roberto@oneiric64 851dd987ab added alpha-quality php plugin 2011-12-20 11:33:03 +01:00
roberto@goyle cf582af970 added --fastrouter-zerg 2011-12-19 09:37:46 +01:00
roberto@oneiric64 d0ec331b6b do not daemonize in emperor mode 2011-12-19 07:52:42 +01:00
roberto@oneiric64 cc75f5f7b3 fixed a stupid bug in emperor 2011-12-17 22:01:45 +01:00
roberto@oneiric64 3d08b7fdd0 added --cflags as build option 2011-12-17 14:02:52 +01:00
roberto@oneiric64 7a92449fc3 another binname improvement 2011-12-16 12:17:53 +01:00
roberto@oneiric64 4b3c34469d fixed bin-name implicit plugin loading 2011-12-16 11:51:07 +01:00
roberto@oneiric64 55bf34561e detect misusage of --rails 2011-12-16 06:49:04 +01:00
roberto@oneiric64 7e79dc0405 removed a debug line in uwsgidecorators 2011-12-15 09:21:17 +01:00
roberto@oneiric64 d3053523ab completed logging pluginization 2011-12-14 10:50:25 +01:00
roberto@oneiric64 e32185cc14 added --threaded-logger 2011-12-14 09:10:26 +01:00
roberto@oneiric64 8e3e3cf27b set level to 5 in graylog2 plugin 2011-12-13 20:42:39 +01:00
roberto@oneiric64 e2cea376e8 added rsyslog plugin 2011-12-13 20:33:17 +01:00
roberto@oneiric64 2a27b66d96 ported zeromq logging to the new api 2011-12-13 19:02:58 +01:00
roberto@oneiric64 522717ca99 initial structure for logging plugins (post-1.0) 2011-12-13 18:21:23 +01:00
roberto@oneiric64 5ee106170b added contrib/cgi_python.c 2011-12-13 06:40:10 +01:00
roberto@oneiric64 d62f04a5a6 cgi loadlib 2011-12-13 06:25:18 +01:00
roberto@oneiric64 eefe5048b2 fixed threading in multiple apps 2011-12-12 17:41:49 +01:00
roberto@oneiric64 8f792fde2d export daemons infos in stats server 2011-12-12 15:15:15 +01:00
roberto@oneiric64 d8ef2d8300 added CLONE_NEWPID for future unshare() improvements 2011-12-12 13:11:50 +01:00
roberto@oneiric64 e69dd5cb6a remove unshare call() on older kernels 2011-12-12 12:54:25 +01:00
roberto@oneiric64 8acd57d87e Added tag 1.0-rc9 for changeset 5da6fe43a8c2 2011-12-12 12:03:39 +01:00
roberto@oneiric64 a42aa1a273 raise exception on rack.input gets/each 2011-12-12 11:49:28 +01:00
roberto@sirius 4b2b7ccf82 fixed rack.input in older rails releases 2011-12-12 11:46:10 +01:00
roberto@Oneiric64 e0fa180a23 --cgi-allowed-ext --cgi-unset 2011-12-11 12:01:40 +01:00
roberto@oneiric64 06ea1fcd1b better SCRIPT_NAME handling in cgi plugin 2011-12-11 11:47:23 +01:00
roberto@oneiric64 567bcc582d improved PATH_INFO in cgi plugin 2011-12-11 11:09:20 +01:00
roberto@oneiric64 844f8c71fa more apache-compliant cgi plugin 2011-12-11 10:40:23 +01:00
roberto@oneiric64 bddbbb93cd first round of improvements for the cgi plugin 2011-12-10 13:37:11 +01:00
roberto@oneiric64 310cc83d36 --exec-as-user 2011-12-09 17:56:57 +01:00
roberto@oneiric64 23dcdc5863 added linux unshare() support 2011-12-09 17:26:33 +01:00
roberto@oneiric64 1286e1835c more tolerant cache checks 2011-12-09 07:42:49 +01:00
roberto@oneiric64 613f2ed939 fixed --rails wirh ruby 1.9.2 2011-12-08 18:36:40 +01:00
roberto@oneiric64 46108f8d0c include st.h in ruby1.8 2011-12-08 08:34:40 +01:00
roberto@oneiric64 28dcfa4131 added SpoolProc class in uwsgidsl.rb 2011-12-08 08:30:25 +01:00
roberto@oneiric64 b48597d3c3 completed spooler support in ruby 2011-12-08 08:09:38 +01:00
roberto@oneiric64 fe4c6ba13e you can now write spooler tasks in ruby 2011-12-08 06:40:29 +01:00
roberto@oneiric64 4049493ffd Added tag 1.0-rc8 for changeset 365e2514cc19 2011-12-07 10:23:54 +01:00
roberto@oneiric64 0c9b6e98f7 added support for yaml lists under libyaml 2011-12-07 10:21:11 +01:00
roberto@colossus ce33d0be5a support for older rails apps 2011-12-07 09:21:28 +01:00
roberto@oneiric64 4f0fb90bff added failcnt in subscription system 2011-12-06 11:17:26 +01:00
roberto@mrspurr 66eff0107a fixed SEQPACKET usage 2011-12-06 10:50:30 +01:00
roberto@oneoric64 82f83e610f fixed a fd leak on static file serving 2011-12-06 09:29:41 +01:00
roberto@oneiric64 cf7df391ad correctly report load in fastrouter stats 2011-12-04 15:58:38 +01:00
roberto@oneiric64 244c9f8204 allows modifier2 to be subscribed 2011-12-04 15:35:29 +01:00
roberto@oneoric64 26dc19df7d reverted subscription string usage 2011-12-04 15:30:08 +01:00
roberto@oneiric64 7b8bff1a08 fixed a bug in load value 2011-12-04 13:50:18 +01:00
roberto@oneiric64 0b010124ef subscription optimizations 2011-12-04 13:45:18 +01:00
roberto@oneiric64 c7bde15f39 ready for next (last?) -rc 2011-12-04 10:38:53 +01:00
roberto@oneiric64 b941e4f2f0 pep8 setup.py 2011-12-04 07:41:49 +01:00
roberto@oneiric64 536c6e7e29 pep8 uwsgidecorators 2011-12-04 07:39:01 +01:00
roberto@oneiric64 dfe4abec35 added health_check in log_pipe 2011-12-04 07:14:19 +01:00
roberto@oneiric64 693b80d7d3 fixed healthcheck skip 2011-12-03 11:06:30 +01:00
roberto@oneiric64 c9e6475ef4 fixed another leak in master 2011-12-03 08:26:41 +01:00
roberto@oneiric64 b745132ebd improved ksm support 2011-12-02 13:31:17 +01:00
roberto@oneiric64 19686cb19f update the copyright to 2011 in apache module 2011-12-01 14:18:54 +01:00
roberto@oneiric64 e0c0593b5b fixed a memory leak in glob() 2011-12-01 13:45:52 +01:00
roberto@oneiric64 415a8af363 fix compilation with async=false 2011-12-01 05:44:23 +01:00
roberto@oneiric64 d44777b1b4 fixed mod_uwsgi when SCRIPT_NAME = / 2011-11-30 18:47:14 +01:00
roberto@oneiric64 e3ff3037b4 use vector-io in fileserve mode 2011-11-30 18:38:42 +01:00
roberto@oneiric64 7add30fd31 added uWSGIemptyRemoteUser in mod_uwsgi 2011-11-30 15:37:48 +01:00
roberto@fiorenzo 501cd0349b another fastrouter fix/optimization 2011-11-29 20:52:08 +01:00
roberto@oneiric64 7b4e3f6601 better error reporting in fastrouter 2011-11-29 19:34:29 +01:00
roberto@oneiric64 8622c2780c fixed cheap reporting 2011-11-29 16:17:17 +01:00
roberto@oneiric64 13de7b6d5b fixed a loop in subscription system 2011-11-29 13:29:23 +01:00
roberto@fiorenzo 53cb864f9c added death mark in fastrouter stats 2011-11-29 11:50:09 +01:00
roberto@fiorenzo 72f693f02a fixed subscription rr and added --fastrouter-stats 2011-11-29 11:46:50 +01:00
roberto@genesi fb80e32682 fix obsolete kernel check 2011-11-29 10:41:57 +01:00
roberto@oneiric64 1db3426ee1 applied riccardo's fix for sendfile 2011-11-29 07:52:26 +01:00
roberto@oneiric64 a44879e384 improved lazy mode to allows signals 2011-11-29 07:47:19 +01:00
roberto@oneiric64 c0075c817d remove unneeded debug entry 2011-11-28 22:06:08 +01:00
roberto@oneiric64 177dc3322b remove unneded rb_gc_unregister_address 2011-11-28 21:57:35 +01:00
roberto@storm 21ef4fc89b multiline headers rack fixes 2011-11-28 21:36:03 +01:00
roberto@oneiric64 f467643f6f better post_buffering 2011-11-28 14:14:24 +01:00
roberto@oneiric64 3db41e7e05 better usage of fwrite() 2011-11-28 14:04:49 +01:00
roberto@oneiric64 73151729c6 mark route() requests 2011-11-28 13:58:15 +01:00
roberto@longshot 5d9c415028 merge 2011-11-28 13:07:05 +01:00
roberto@longshot b92ed4da4e fixed after_request remapper 2011-11-28 13:06:43 +01:00
roberto@oneiric64 2d1a9a03d2 reduce a potetial race conditions in evil reloads 2011-11-28 11:35:35 +01:00
roberto@longshot 5d6edd2321 force removal of -Winline during plugins building 2011-11-28 10:29:46 +01:00
roberto@oneiric64 365f4ba83f fixed a bug in FIFO reading 2011-11-28 07:17:58 +01:00
roberto@oneiric64 66e30ae293 report config in USR1 management 2011-11-27 21:05:06 +01:00
roberto@oneiric64 728425de19 Added tag 1.0-rc7 for changeset a3ca2e8e27c5 2011-11-26 18:50:41 +01:00
roberto@oneiric64 b0af1f800b fixed a bug in #ifdef for pump/web3 spotted by riccardo 2011-11-26 18:39:44 +01:00
roberto@oneiric64 543271e856 fixed a ksm leak 2011-11-26 13:02:47 +01:00
roberto@oneiric64 a1564a44fa added postgresql probe 2011-11-26 12:44:38 +01:00
roberto@oneiric64 571029cfd3 added probe infrastructure 2011-11-26 11:05:49 +01:00
roberto@oneiric64 579eaa630a refactored daemons and removed uwsgi.attach_daemon function 2011-11-26 09:04:19 +01:00
roberto@oneiric64 9530c8ffe0 applied riccardo's patch [2] 2011-11-26 08:10:29 +01:00
roberto@oneiric64 0d8690091b applied riccardo's patch [1] 2011-11-26 08:04:39 +01:00
roberto@goyle 5b5e3a1ec1 added delta_requests 2011-11-25 15:34:41 +01:00
roberto@centos64 869ae5e3ed allows the building of uWSGI on ancient linux kernel (like CentOS4) 2011-11-24 12:57:08 +01:00
roberto@oneiric64 d6dc8d86f8 added subscription report on startup 2011-11-24 07:42:14 +01:00
roberto@oneiric64 758745be68 closed bug #56 2011-11-24 07:35:32 +01:00
roberto@oneiric64 2adfa56d6a added threading name in python threads object 2011-11-23 17:44:41 +01:00
roberto@oneiric64 a4c728f5df added auto-patching for Rack::BodyProxy.each 2011-11-23 11:45:13 +01:00
roberto@oneiric64 5c06341b7f ready for -rc7 2011-11-23 10:08:49 +01:00
roberto@oneiric64 6f57902a9b another cron fix 2011-11-23 05:37:00 +01:00
roberto@longshot a3e118893d do not build sqlite on unbit 2011-11-22 18:52:12 +01:00
roberto@oneiric64 ff2d3c29d6 fixed a bug in cron management 2011-11-22 17:56:03 +01:00
roberto@oneiric64 59a8df85f2 added --st as a --subscribe/--subscribe-to alias 2011-11-22 11:23:10 +01:00
roberto@oneiric64 e303bd182a report subscribed nodes timeout 2011-11-22 11:15:13 +01:00
roberto@oneiric64 dcef9a497c less verbose build system 2011-11-22 09:46:16 +01:00
roberto@oneiric64 8d4fd66aaf fixed a bug in execvp() during reload on 64 bit 2011-11-22 09:16:34 +01:00
roberto@debian32 471bd23acf added --subscribe-freq and --subscription-tolerance 2011-11-21 20:22:00 +01:00
roberto@debian32 ffcef81dd0 greatly improved subscription system 2011-11-21 16:23:24 +01:00
roberto@debian32 317df5d06b added @(filename) magic var 2011-11-21 13:22:05 +01:00
roberto@debian32 ad7b5efd6f added --logfile-chmod 2011-11-21 10:32:48 +01:00
roberto@deban32 891f770724 added Lukas to CONTRIBUTORS 2011-11-21 09:55:43 +01:00
roberto@debian32.local 0b6d715982 refactored ping and nagios 2011-11-21 09:42:48 +01:00
roberto@debian32 76c2415516 moved cluster-related functions to a dedicated file 2011-11-20 11:36:42 +01:00
roberto@gambit 3260faca17 Added tag 1.0-rc6 for changeset a2b8f25fd17e 2011-11-19 08:40:45 +01:00
roberto@arch32 feb493158c a fix fir capability support on arch linux 2011-11-19 07:55:22 +01:00
roberto@debian32 a5c1556cb7 do not exit on realod if chdir() fail 2011-11-18 20:46:07 +01:00
roberto@longshot 89e640bdd9 better to not remove -g/-ggdb 2011-11-18 09:29:30 +01:00
roberto@longshot 3ade8daff8 fixed rack compilation 2011-11-18 09:23:06 +01:00
roberto@debian32 049ea3fbed added Linux KSM support 2011-11-17 11:16:48 +01:00
roberto@goyle 715d26beed added support for remote signalling in rack plugin 2011-11-16 18:30:00 +01:00
roberto@goyle 1f5064094c better signal registration reporting 2011-11-15 18:33:44 +01:00
roberto@goyle 7ed522dc29 added --signal 2011-11-15 18:18:42 +01:00
roberto@goyle 2086500405 added signal plugin 2011-11-15 18:06:37 +01:00
roberto@debian32 8f79409ed1 added uwsgi.route() 2011-11-14 15:05:23 +01:00
roberto@debian32 c2a3cd1476 added mule support to ruby DSL 2011-11-13 17:25:47 +01:00
roberto@debian32 e195a5d72c improved signal handling and rack mule_msg 2011-11-13 15:08:29 +01:00
roberto@debian32 c86b757904 use app_id in rack plugin 2011-11-12 16:24:47 +01:00
roberto@debian32 6800d2ac95 added lock/unlock to rack plugin 2011-11-12 11:31:22 +01:00
roberto@debian32 90fda2b4bb added UWSGI.mem 2011-11-12 11:18:25 +01:00
roberto@debian32 bf7ded9058 added a bunch of constant to rack plugin 2011-11-12 11:13:06 +01:00
roberto@debian32 6615dc3a62 added UWSGI.setprocname 2011-11-12 11:07:38 +01:00
roberto@debian32 c35054085c completed ruby cache support 2011-11-12 11:02:30 +01:00
roberto@debian32 fdf2bd7f96 fixed ruby 1.9 support 2011-11-12 10:53:19 +01:00
roberto@debian32 1c10b9dfe1 ported cache api to rack plugin 2011-11-12 10:44:23 +01:00
roberto@debian32 6854394e5c added rpc support to ruby 2011-11-11 12:29:04 +01:00
roberto@debian32 78a0d5f432 added postfork in uwsgidsl 2011-11-11 09:57:35 +01:00
roberto@debian32 5fe5aa70a4 added post_fork_hook to ruby 2011-11-11 09:49:17 +01:00
roberto@debian32 e9c0c6bd0b report GC frequency 2011-11-11 06:54:08 +01:00
roberto@debian32 5d12b3dc9c added --rbrequire 2011-11-11 06:51:29 +01:00
roberto@debian32 169a4b66db added UWSGI.signal_received to ruby 2011-11-10 16:32:26 +01:00
roberto@debian32 fbd6329db9 improved ruby signal handling 2011-11-10 16:11:48 +01:00
roberto@debian32 69c2e56857 ported python plugin to new signal_wait api 2011-11-10 15:36:36 +01:00
roberto@debian32 18f7d1edd3 refactored signal_wait 2011-11-10 15:34:19 +01:00
roberto@debian32 3f7cd5ff92 added rubydsl 2011-11-10 15:33:41 +01:00
roberto@debian32 785e1dbf83 re-thinked remap-modifier 2011-11-10 15:33:19 +01:00
roberto@debian32 bc6acf8d14 use SIGTSTP instead of SIGWINCH for pause/suspend/resume 2011-11-10 11:25:22 +01:00
roberto@sirius 3a099d0b2e added --pause/--suspend/--resume 2011-11-10 09:38:32 +01:00
roberto@longshot f9ad5e4144 fixed multi-option parser 2011-11-09 20:58:33 +01:00
roberto@debian32 ce9f6650a0 allows carbon-id to include dots 2011-11-09 07:08:44 +01:00
roberto@mrspurr fdeef04343 fixed a stupid bug in carbon plugin 2011-11-09 06:57:21 +01:00
roberto@debian32 fe72ec82e1 completed carbon plugin 2011-11-09 06:50:51 +01:00
roberto@debian32 fd0f308273 added carbon plugin 2011-11-09 06:25:38 +01:00
roberto@longshot f4e9ab43cb fixed rack compilation 2011-11-08 18:46:29 +01:00
roberto@debian32 3a141b523c Added tag 1.0-rc5 for changeset 043ba93dd69c 2011-11-03 09:40:07 +01:00
roberto@debian32 2d731532be various erlang fixes 2011-11-03 09:09:17 +01:00
roberto@debian32 d545cd5be0 added @erlang decorator 2011-11-02 20:48:11 +01:00
roberto@debian32 261d05d67e added @mulemsg decorator 2011-11-02 19:55:11 +01:00
roberto@debian32 639995785a fixed pyerl 2011-11-02 14:41:32 +01:00
roberto@debian32 817e076cae uwsgidecorators is installed when run under pip/easy_install 2011-11-02 14:20:51 +01:00
roberto@debian32 713370f343 completed regexp support in subscription system 2011-11-01 08:33:52 +01:00
roberto@debian32 5594503a56 pcre support in subscription system 2011-10-31 09:11:02 +01:00
roberto@debian32 d57e5d46fb fixed subscriptions removal in http plugin 2011-10-31 07:56:01 +01:00
roberto@debian32 ee2db5fabd a bunch of subscription optimizations 2011-10-30 13:10:26 +01:00
roberto@debian32 0c4cd6f378 ported http plugin to new subscription system 2011-10-30 11:36:53 +01:00
roberto@debian32 8c32b9665c re-implementation of subscription system 2011-10-30 11:30:53 +01:00
roberto@colossus 7405a01654 ready for next -rc ? 2011-10-28 17:53:16 +02:00
roberto@colossus 5d27691b4b fixed log rotation 2011-10-28 16:49:26 +02:00
roberto@debian32 19bbcfbf4c added @mule decorator 2011-10-28 16:22:39 +02:00
roberto@debian32 fa1064db87 added --umask 2011-10-28 16:10:26 +02:00
roberto@colossus 850ac69ca1 fixed master reloading 2011-10-28 11:35:18 +02:00
roberto@debian32 943edeb30c fixed a typo in subscribe-to and incresed slots to 64 2011-10-28 08:11:51 +02:00
roberto@debian32 01815a354b added a centos init script in contrib 2011-10-27 13:54:29 +02:00
roberto@debian32 2f4412aca1 allows .json as a valid vassal extension 2011-10-27 13:52:11 +02:00
roberto@oneiric64 2782bb7594 fixed 64bit support in rrdtool 2011-10-27 12:44:01 +02:00
roberto@debian32 074c1298d5 procname-prefix-spaced 2011-10-27 10:08:38 +02:00
roberto@debian32 55a7911611 added rrdtool plugin 2011-10-27 09:26:59 +02:00
roberto@debian32 013ad3044d added @mulefuc decorators 2011-10-26 10:51:03 +02:00
roberto@debian32 dcf4217b9d greatly improved uwsgi.mule_msg() 2011-10-26 10:13:20 +02:00
roberto@debian32 876dfc31a9 dynamic buffer_size and timeout for mule_get_msg 2011-10-26 06:43:07 +02:00
roberto@debian32 fd03bdbe00 improved mule and farm signal handling 2011-10-26 06:30:42 +02:00
roberto@debian32 83612649d5 mule_get_msg can manage signals 2011-10-26 06:11:07 +02:00
roberto@debian32 3c4db7e97e timerfd_create workaround 2011-10-26 05:45:06 +02:00
roberto@colossus 088c70efdc fixed locking 2011-10-25 18:05:52 +02:00
roberto@debian32 2b19029dd0 multiple mule_msg() 2011-10-25 17:46:41 +02:00
roberto@debian32 4fb5a84378 improved multi-mule support 2011-10-25 17:35:52 +02:00
roberto@debian32 b3107d9a25 another mule fix 2011-10-25 17:03:13 +02:00
roberto@debian32 bf32988f3e applied riccardo magliocchetti patch for .json support 2011-10-25 16:44:33 +02:00
roberto@debian32 1bf3dd7bf4 fixed mule patch message 2011-10-24 18:52:41 +02:00
roberto@debian32 07fd84f89f ported symimporter/symzipimporter to python3 2011-10-24 16:35:59 +02:00
roberto@debian32 3a8db4a97a fixed unlocking 2011-10-24 15:56:17 +02:00
roberto@debian32 aea30a26f5 added --mules <n> 2011-10-24 10:40:29 +02:00
roberto@gambit 8f5d1cdae7 Added tag 1.0-rc4 for changeset 24f7e260ea34 2011-10-24 10:05:02 +02:00
roberto@gambit 53913357e0 fixed strtok usage 2011-10-24 10:04:25 +02:00
roberto@debian32 098416f444 uWSGI 1.0-rc3 2011-10-24 09:42:41 +02:00
roberto@debian32 c98cb09c7c Added tag 1.0-rc3 for changeset 4e4e781ef89a 2011-10-24 09:42:27 +02:00
roberto@debian32 bb1ef28d69 updated decorators with @farm([name]) 2011-10-23 19:59:53 +02:00
roberto@debian32 1d5b05265d initial farm implementation 2011-10-23 19:18:31 +02:00
roberto@debian32 d9fef3c30e a little hack for psgi loader waiting for a truly agnostic init_uwsgi_app 2011-10-23 12:14:53 +02:00
roberto@debian32 e5dfb9efc3 improved get_memusage 2011-10-23 12:04:02 +02:00
roberto@debian32 02bab15e86 perl threading improvements 2011-10-23 11:49:25 +02:00
roberto@debian32 6f4ddead09 Added tag 1.0-rc2 for changeset 7a4e021ea7ba 2011-10-23 08:37:03 +02:00
roberto@gambit b361248ff6 fixed add_exported_opts 2011-10-23 08:35:15 +02:00
roberto@debian32 e9c42ceaa5 support for multiple values in options 2011-10-22 18:32:32 +02:00
roberto@debian32 5d7029744a PATH_INFO is correctly escaped in http modes 2011-10-22 09:35:01 +02:00
roberto@gambit 1084a3afa8 fixed mule patch loading 2011-10-20 10:38:59 +02:00
roberto@gambit ed254bffee fixed mule process name 2011-10-20 10:20:44 +02:00
roberto@djangocloud 733784d7dd another procname fix... 2011-10-19 16:13:10 +10:00
roberto@djangocloud cb5b26bcb4 another bunch of procname fixes 2011-10-19 14:26:07 +10:00
roberto@djangocloud 0065152bb1 daemons throttling subsystem 2011-10-18 18:53:22 +10:00
roberto@djangocloud 03266203fd another fix for environ 2011-10-18 18:30:13 +10:00
roberto@djangocloud 4a5f68f9d8 fixed environ 2011-10-18 18:12:39 +10:00
roberto@djangocloud 83e31a1c27 another setprocname fix 2011-10-18 16:20:33 +10:00
roberto@djangocloud 0efed5ef9c various emperor procname fixes 2011-10-18 16:15:06 +10:00
roberto@djangocloud cdfef1281d fixed another spooler compilation bug 2011-10-18 15:12:59 +10:00
roberto@debian32 e00907e142 --spooler-harakiri 2011-10-17 19:07:12 +02:00
roberto@app1 6dcbcf39e3 fixed compilation when spooler is disabled 2011-10-17 03:16:55 -05:00
roberto@debian32 044579a8e0 more verbose annihilation report 2011-10-16 11:16:13 +02:00
roberto@debian32 d2b52b4663 added uwsgi.setprocname() 2011-10-16 10:37:26 +02:00
roberto@debian32 7f75b2c02c added --procname and --procname-master 2011-10-16 10:18:45 +02:00
roberto@freebsd64 24a3f671e5 freebsd setproctitle 2011-10-16 10:06:08 +02:00
roberto@debian32 875100e3c8 check for mules before nuke 2011-10-16 09:58:37 +02:00
roberto@mrspurr 34bc7c0cfd check for procname 2011-10-16 09:54:35 +02:00
roberto@debian32 b39a10ff7c procname initial management 2011-10-16 09:45:41 +02:00
roberto@debian32 02331904de uWSGI 1.0-rc1 2011-10-15 08:47:00 +02:00
roberto@debian32 d1a4ae694e --locks 2011-10-15 08:32:32 +02:00
roberto@debian32 7a5ffc1124 --spooler-chdir 2011-10-14 19:20:05 +02:00
roberto@debian32 19c5bfb42c fixed a spooler signal bug spotted by Gabriele Giaccari 2011-10-14 18:32:17 +02:00
roberto@debian32 893bf3686b fixed a wrong typecast 2011-10-14 10:58:02 +02:00
roberto@debian32 e54fa9bcd4 added --emperor-stats 2011-10-13 07:53:32 +02:00
roberto@debian32 c1eb5ab0fe prepare for emperor-stats 2011-10-12 06:51:49 +02:00
roberto@mrspurr 461914dde4 completed --evil-reload options 2011-10-12 06:48:52 +02:00
roberto@debian32 85662578e4 implemented --mule-harakiri 2011-10-12 01:48:30 +02:00
roberto@debian32 a59c0ae795 setlinebuf in syslog mode 2011-10-12 00:54:18 +02:00
roberto@debian32 3a860155ee added --evil-reload-on-as and --evil-reload-on-rss 2011-10-11 20:39:00 +02:00
roberto@debian32 27553c2967 prepare for --evil-reload-... options 2011-10-11 20:18:31 +02:00
roberto@colossus 9a8ac9af3c added uwsgi.mule_id() 2011-10-11 07:31:41 +02:00
roberto@debian32 2f5daffe99 use hggit for better github sync 2011-10-09 09:11:54 +02:00
roberto@debian32 75cd31dce4 better spooler error reporting 2011-10-07 03:30:16 +02:00
roberto@colossus f7150d1b41 fixed mule socketpair 2011-10-06 18:37:24 +02:00
roberto@debian32 d6a6b65338 added --log-x-forwarded-for 2011-10-06 06:42:31 +02:00
roberto@freebsd64 979f6027b4 ignore SIGPIPE by default 2011-10-05 20:45:55 +02:00
roberto@freebsd64 7dc059c75b completed new freebsd64 sendfiel async support 2011-10-05 20:34:25 +02:00
roberto@freebsd64 b639b5974f better freebsd sendfile support 2011-10-05 20:19:12 +02:00
roberto@netbsd64 0de08c553c fixed a potential overflow 2011-10-05 21:16:28 +02:00
roberto@freebsd64 80788ac695 freebsd event fix 2011-10-05 19:01:29 +02:00
roberto@freebsd64 1494c621c1 non-linux fix 2011-10-05 18:43:53 +02:00
roberto@debian32 605e5b5173 export listen_queue size in stats 2011-10-05 17:24:46 +02:00
roberto@debian32 4cf2213051 added --log-truncate --log-reopen --log-maxsize --log-backupname 2011-10-05 11:58:15 +02:00
roberto@debian32 3aa36668e5 better error reporting 2011-10-04 20:28:08 +02:00
roberto@debian32 1c0b5b42e9 support for multiple --touch-reload options 2011-10-04 19:40:09 +02:00
roberto@openindiana64 702dc44fad fixed openindiana build on 64bit 2011-10-03 15:46:04 +02:00
roberto@solrisexpress 2cae07aa52 fixed 64bit compilation 2011-10-03 09:37:32 +00:00
roberto@ebian32 b5616ff25c completed mule signal handling 2011-10-03 08:36:21 +02:00
roberto@debian32 b7b7521975 refactored fds closing and socketpair 2011-10-03 08:29:19 +02:00
roberto@debian32 dce3263ee3 added mule messaging subsystem 2011-10-03 07:45:18 +02:00
roberto@debian32 9796e05ca1 added support for X_FORWARDED_SSL in http parser 2011-10-03 06:38:14 +02:00
roberto@debian32 5cc0d459ec struct uwsgi_server is becoming huge, better to add some comment 2011-10-02 20:45:03 +02:00
roberto@debian32 531a850a71 first almost-working commit for uWSGI mules 2011-10-02 20:05:31 +02:00
roberto@debian32 4c36280287 support --manage-script-name in http socket mode 2011-09-30 12:32:31 +02:00
roberto@debian32 70be8eb55e restored setup.py 2011-09-30 10:55:12 +02:00
roberto@debian32 f8b757b21e print argv in setup.py 2011-09-30 10:39:22 +02:00
roberto@debian32 3a63d352bb print envs in setup.py 2011-09-30 10:36:30 +02:00
roberto@sirius 60467705c5 fixed a stupid bug 2011-09-30 10:31:00 +02:00
roberto@debian32 eada0c09e0 refactored placeholder management 2011-09-30 10:21:26 +02:00
roberto@debian32 8e851aa6a1 fixed egg 2011-09-30 09:56:51 +02:00
roberto@debian32 eaf7bb967d added a check for http (3) 2011-09-30 09:43:42 +02:00
roberto@debian32 7be45c77b1 added a check for http (2) 2011-09-30 09:42:19 +02:00
roberto@debian32 5e2b460dc8 added a check for http (2) 2011-09-30 09:24:33 +02:00
roberto@debian32 16143e698f added a check for http 2011-09-30 09:21:12 +02:00
roberto@debian32 4259946e3b second little typecast fix 2011-09-30 08:51:18 +02:00
roberto@debian32 0a750d76ee little typecast fix 2011-09-30 08:50:00 +02:00
roberto@debian32 e4a9f5f0dd merge 2011-09-28 20:21:11 +02:00
roberto@debian32 d5b7698f89 added --stats 2011-09-28 20:20:40 +02:00
roberto@sirius a481e8508e added .gitignore 2011-09-28 17:23:22 +02:00
roberto@debian32 a53b57497b close bug #47 2011-09-28 07:27:43 +02:00
roberto@debian32 d871357b2d added uwsgi_req_error 2011-09-25 16:16:08 +02:00
roberto@debian32 2d57db55f4 removed a useless error checking 2011-09-25 14:06:06 +02:00
roberto@debian32 bae45ce03a error checking in uwsgi proto writer 2011-09-25 14:01:06 +02:00
roberto@debian32 44cc4336f1 added posix capability support 2011-09-25 13:41:10 +02:00
roberto@debian32 44f6e214fd improved uwsgi.queue_last 2011-09-25 10:44:19 +02:00
roberto@debian32 3e46f81d2b use PyLong_FromUnsignedLongLong 2011-09-25 06:42:23 +02:00
roberto@debian32 e4532b9a50 added memory usage in uwsgicc 2011-09-24 09:07:34 +02:00
roberto@debian32 2694be562c fixed respawn_count 2011-09-24 08:28:19 +02:00
roberto@debian32 fadb9edd7f added running time and avg_rt to uwsgicc 2011-09-24 08:24:51 +02:00
roberto@debian32 d85e0790de added response_time and running_time statistics 2011-09-24 06:40:30 +02:00
roberto@debian32 bc46c4d704 python3 fix 2011-09-23 08:36:28 +02:00
roberto@centos64 a73a010188 fixed build system for older gcc releases 2011-09-23 08:33:15 +02:00
roberto@debian3 4e8c8ef317 improved screen support 2011-09-21 06:09:05 +02:00
roberto@debian32 e402e7805d no need to set pty, screen is much metter 2011-09-21 05:27:58 +02:00
roberto@debian32 302b8f026b --cheaper improvement 2011-09-19 10:15:24 +02:00
roberto@debian32 630054b72a better wakeup of workers 2011-09-19 07:53:51 +02:00
roberto@debian32 a05f459b2b preliminary cheaper implementation 2011-09-19 07:13:45 +02:00
roberto@debian32 207979580a added uwsgi.extract 2011-09-18 07:04:36 +02:00
roberto@debian32 f69526f8bf parse plugin-specific options 2011-09-18 06:57:19 +02:00
roberto@debian32 e249d567a1 --fastrouter-cheap 2011-09-16 15:14:08 +02:00
roberto@debian32 a23ba653da better shared sockets support 2011-09-16 07:46:45 +02:00
roberto@debian32 0644d53572 set pty to raw mode 2011-09-13 08:35:50 +02:00
roberto@debian32 f58f51294d fixed sendfile typecasting 2011-09-11 07:41:42 +02:00
roberto@debian32 86194eb93e GC in symzipimporter is useless 2011-09-11 07:33:23 +02:00
roberto@debian32 0a89f375e6 added charles as contributor 2011-09-11 06:55:27 +02:00
roberto@debian32 6282178b3c fixed python optimize flag 2011-09-11 06:42:45 +02:00
roberto@debian32 8e14d68022 merge 2011-09-10 17:28:40 +02:00
roberto@debian32 e86bd0c070 preliminary support for detachable pyshell 2011-09-10 17:28:01 +02:00
roberto@mrspurr bf991f8892 report gb objects in welcome.py 2011-09-10 11:03:39 +02:00
roberto@mrspurr b341678d20 another symzip fix 2011-09-10 10:58:37 +02:00
roberto@mrspurr 5f59365d88 symzip GC fix 2011-09-10 10:54:27 +02:00
roberto@debian32 5130a7bb33 moved the old 'j' to 'J' option 2011-09-09 20:36:00 +02:00
roberto@dexter cc84a596d6 better iso99 check 2011-09-09 18:44:18 +02:00
roberto@longshot e67bed431a a fix for older gcc 2011-09-09 18:43:08 +02:00
roberto@dexter 72613a9f48 mime type optimization 2011-09-09 18:35:29 +02:00
roberto@sirius c048ea0615 better mimetype file check 2011-09-09 18:14:53 +02:00
roberto@dexter 957ca1b7ed added mime types support in static file serving 2011-09-09 17:06:35 +02:00
roberto@ebian32 d80a6df039 fixed a threading bug 2011-09-09 10:00:09 +02:00
roberto@mrspurr 94f9bd9d91 added Corey as contributor 2011-09-09 08:53:37 +02:00
roberto@mrspurr b480efe672 fixed script_name handling 2011-09-09 08:42:31 +02:00
roberto@mrspurr 4fc306d979 added a new debug entry 2011-09-09 08:32:20 +02:00
roberto@mrspurr 56abccbdeb another fix for urack.rb 2011-09-08 19:59:37 +02:00
roberto@mrspuur f218af0735 clang fixes 2011-09-08 19:45:46 +02:00
roberto@mrspurr 9b69c62780 automagic bundler in urack.rb 2011-09-08 13:44:50 +02:00
roberto@dexter eb5d67e07f 1.0 is better than 1.0.0 2011-09-07 16:09:45 +02:00
roberto@sirius e7391987b1 fixed sandboxviolation on osx 2011-09-07 12:33:12 +02:00
roberto@sirius 02cbe15575 test3 2011-09-07 12:32:02 +02:00
roberto@sirius a5a657f0d4 a second test 2011-09-07 12:29:24 +02:00
roberto@sirius 67567c86e0 a test 2011-09-07 12:27:47 +02:00
roberto@dexter 445d02da45 make easy_install happy 2011-09-06 17:58:02 +02:00
roberto@debian32 4a05df41ce subscription logging 2011-09-05 16:26:25 +02:00
roberto@debian32 5c0c2f6b45 yaml fix 2011-09-05 08:12:12 +02:00
roberto@debian32 0ab55fef46 added support for regexp in UWSGI_APPID 2011-09-04 21:33:30 +02:00
roberto@debian32 dd344bfe38 fixed a bug in multiapp mode 2011-09-04 18:01:04 +02:00
roberto@debian32 e92a889bcc refactored UWSGI_PY_READLINE_BUFSIZE 2011-09-03 07:15:51 +02:00
roberto@debian32 419d656a83 1.0.0-dev cycle started 2011-08-31 14:27:21 +02:00
roberto@debian32 3c3d58bfe9 pypyuwsgi.py 2011-08-31 14:01:46 +02:00
roberto@debian32 1989099cc5 preliminary pypy support 2011-08-31 13:18:32 +02:00
roberto@sirius 1446e3f0a9 allows pyuwsgi in osx 2011-08-31 12:09:56 +02:00
roberto@debian32 00fc31289d a pyuwsgi fix 2011-08-31 12:06:26 +02:00
roberto@sirius 2c463ad6af a test for libless pyuwsgi 2011-08-31 12:02:19 +02:00
roberto@sirius e641ae05c4 pyuwsgi 2011-08-31 11:42:22 +02:00
roberto@debian32 a13e0075ee fixed virtualhosting in fully-dynamic mode 2011-08-31 07:55:34 +02:00
roberto@debian32 e617a7b88e added an example for the new fd-based config 2011-08-30 12:08:22 +02:00
roberto@debian32 cbdeb4caad --stop and --reload, open by fifo and fd 2011-08-30 10:51:50 +02:00
roberto@sirius 59314d692f uWSGI 0.9.9 2011-08-29 17:32:08 +02:00
roberto@sirius 3dfa56b279 Added tag 0.9.9 for changeset 376ffd8f1906 2011-08-29 17:26:31 +02:00
roberto@dexter 920d5d7416 Changelog for 0.9.9 2011-08-29 11:32:27 +02:00
roberto@dexter dcb654d7fb spooler reload fix 2011-08-29 10:50:09 +02:00
roberto@solarisexpress a563da1223 solaris fix for lockf() 2011-08-29 10:34:46 +00:00
roberto@sirius 1e26cda615 fixed a race condition 2011-08-29 10:30:01 +02:00
roberto@dexter 97133b27ce the decoratortest is fully working, ready for release 2011-08-29 09:54:07 +02:00
roberto@sirius b428bd3b87 another bunch of build fixes 2011-08-29 08:02:37 +02:00
roberto@dexter 05136e74b4 fixed build system 2011-08-29 07:55:46 +02:00
roberto@mrspurr 9f28a8bdf1 improved upload progress 2011-08-28 20:53:46 +02:00
roberta@mrspurr d9361f1fee added test for upload progress 2011-08-28 19:13:56 +02:00
roberto@debian32 835230b1a4 emperor-tyrant 2011-08-28 09:15:13 +02:00
roberto@debian32 f88f51c553 added welcome.ini 2011-08-28 08:33:49 +02:00
roberto@debian32 1996305eb1 allows multiple --ini options 2011-08-28 07:55:54 +02:00
roberto@solrisexpress c7ad50e950 do not free getexecname() ret value 2011-08-28 07:37:21 +00:00
roberto@debian32 0ec0c29d67 fixed an indentation 2011-08-28 07:21:49 +02:00
roberto@solarisexpress 75af117e8a better magic plugin loading on binary_path 2011-08-28 07:14:42 +00:00
roberto@debian32 2b04cefe4e added help for a bunch of options 2011-08-27 19:37:34 +02:00
roberto@debian32 0e41c4111a fixed upstart 2011-08-27 18:46:53 +02:00
roberto@debian32 5f5d382c64 signal framework ported to gevent 2011-08-27 07:15:44 +02:00
roberto@dexter 3e867fe401 resolve domain names in socket logging 2011-08-26 16:20:14 +02:00
roberto@dexter 153142b8b0 fixed django uwsgi_admin without spooler 2011-08-26 15:02:02 +02:00
roberto@dexter 5562c0c047 use hub.join() instead of hub.switch() 2011-08-26 14:05:03 +02:00
roberto@debian32 f4a1f800ba timeout handling in gevent plugin 2011-08-26 12:34:12 +02:00
roberto@debian32 bdbc5e5605 another gevent improvement suggested by denis 2011-08-26 11:35:32 +02:00
roberto@debian32 4104f825ff another improvement for sys.executable in python3 2011-08-26 10:28:34 +02:00
roberto@longshot efa01ea404 better sys.executable and sys.argv values 2011-08-26 10:08:01 +02:00
roberto@debian32 982559ae66 snmp fixes 2011-08-26 09:54:11 +02:00
roberto@gambit 60002e8de8 Added tag 0.9.9-rc2 for changeset 6aa667612019 2011-08-26 08:17:20 +02:00
roberto@debian32 25d671e0f6 fixed python snmp api 2011-08-26 08:13:14 +02:00
roberto@debian32 5a58281a3f various gevent fixes 2011-08-26 07:37:26 +02:00
roberto@debian32 c422231806 ops another grunt fix 2011-08-25 18:16:58 +02:00
roberto@debian32 4979883fe5 fixed a grunt bug 2011-08-25 17:51:04 +02:00
roberto@debian32 8158a624d3 check for loop engine 2011-08-25 14:34:18 +02:00
roberto@debian32 06403b5fce fixed stupid bug in setup.py 2011-08-25 14:15:55 +02:00
roberto@debian32 bc482652fc updated setup.py 2011-08-25 14:13:13 +02:00
roberto@debian32 58aa5755e0 fixed a typo 2011-08-25 14:04:57 +02:00
roberto@debian32 bca835c58a added UWSGI_PROFILE unix env 2011-08-25 14:03:43 +02:00
roberto@debian32 4b0f68a57a check gevent version 2011-08-25 13:53:38 +02:00
roberto@debian32 b693d73ebe gevent dedicated plugin 2011-08-25 13:46:42 +02:00
roberto@dexter dfab80447b added a check for Riccardo 2011-08-24 18:24:45 +02:00
roberto@dexter bbde0c866a a couple of fixes, and reintroduction of string-based multiapp 2011-08-24 17:48:27 +02:00
roberto@mrspurr 7b3514f757 --emperor-throttle 2011-08-24 13:03:25 +02:00
roberto@mrspurr 6d5fb3b252 export cache and queue functions only if available 2011-08-20 11:12:32 +02:00
roberto@debian32 87e8f118d3 fix refcnt in async-disabled compilation 2011-08-19 16:35:16 +02:00
roberto@debian32 3ae78cc0a8 another bufsize fix 2011-08-19 16:28:44 +02:00
roberto@debian32 7ef921356f updated sharedarea 2011-08-19 15:22:20 +02:00
roberto@debian32 378185d997 added a build profile for uwsgi_pypy integration 2011-08-19 12:24:38 +02:00
roberto@debian32 c4b15a8509 changed final banner in library mode 2011-08-19 12:15:18 +02:00
roberto@debian32 96ef9d155b uwsgi.magic_table 2011-08-19 11:44:40 +02:00
roberto@debian32 d5e6412b20 uWSGI 0.9.9-rc1 2011-08-19 09:57:58 +02:00
roberto@debian32 eebe757c16 Added tag 0.9.9-rc1 for changeset fb168b0b8616 2011-08-19 08:51:26 +02:00
roberto@debian32 43a21d32cb fixed a stupid bug 2011-08-19 08:49:39 +02:00
roberto@debian32 9f9eb5ef17 improved apache2 SCRIPT_NAME/PATH_INFo handling 2011-08-19 08:48:15 +02:00
roberto@debian32 0116c62980 another refcnt fix 2011-08-19 07:06:29 +02:00
roberto@debian32 fae446e495 fix for 3.0-arch 2011-08-19 06:46:07 +02:00
roberto@debian32 6f7054df18 more tolerant cache and queue size 2011-08-18 14:27:21 +02:00
roberto@debian32 0f31c21f4a completed queue subsystem with test 2011-08-18 09:46:32 +02:00
roberto@debian32 bd3e234703 another xml app tag fix 2011-08-18 07:06:27 +02:00
roberto@gambit 71bfd63623 fixed xml app tag 2011-08-18 07:01:13 +02:00
unbit@localhost 98b89dc83c Added tag 0.9.9-beta1 for changeset 6945ee03c7ea 2011-08-18 06:33:20 +02:00
roberto@gambit 97ec789bbe fixed casting 2011-08-18 06:13:51 +02:00
roberto@debian32 14b403c046 fixed a post-buffering bug 2011-08-17 12:42:12 +02:00
roberto@debian32 bc01d25068 uWSGI can now be built as a shardd library 2011-08-17 11:21:22 +02:00
roberto@fedora64 69808c34a8 fixed callable and start_response refcnt 2011-08-16 17:00:15 +02:00
roberto@debian32 273181daf5 another threading fix 2011-08-16 08:00:09 +02:00
roberto@debian32 8d2394eba1 better name handling in --wsgi-file 2011-08-16 07:33:46 +02:00
roberto@debian32 6f5b468b11 fix threading bug in pyshell 2011-08-16 07:31:20 +02:00
roberta@mrspurr c9e759bc14 allow threads in gateways 2011-08-14 07:46:29 +02:00
roberto@debian32 e6d064f5c1 allows fastrouter cache to set modifier1 2011-08-13 11:25:06 +02:00
roberto@debian32 8f7ed02475 a bunch of lua fixes 2011-08-13 11:12:10 +02:00
roberto@debian32 f7edcebbdc added --fastrouter-use-code-string 2011-08-13 08:39:17 +02:00
roberto@debian32 a19b392ba6 applications list is now shared 2011-08-12 08:08:39 +02:00
roberto@mrspurr 287df9ef86 fixed a stupid bug with thread stacksize 2011-08-11 07:32:02 +02:00
roberto@juggernaut de7be379c4 shut up gcc on ubuntu lucid 2011-08-10 14:43:57 +02:00
roberto@debian32 1e4d41795c allows setting threads stacksize 2011-08-10 12:13:46 +02:00
roberto@debian32 e2e973a20e we are now at 0.9.9-dev 2011-08-09 08:25:09 +02:00
roberto@debian32 5d993fbfc0 implemented UWSGI_APPID var 2011-08-09 08:20:12 +02:00
roberto@debian32 a94a8ea287 added a check on spooler unlink 2011-08-05 06:53:43 +02:00
roberto@debian32 55d8677a46 fixed a spooler thread problem 2011-08-04 18:20:44 +02:00
roberto@debian32 4004aeb54e fileno() for wsgi.input 2011-08-04 16:53:39 +02:00
roberto@debian32 2de2898d86 fix a stupid bug 2011-08-04 16:28:47 +02:00
roberto@debian32 8c1b48a88d a new kick-ass feature for the spooler 2011-08-04 16:25:17 +02:00
roberto@debian32 9bd3022a5e a bunch of threading fixes in the spooler 2011-08-04 14:11:40 +02:00
roberto@debian32 eb0ce609f0 wakeup spooler (if possibile) after each submission 2011-08-04 11:15:24 +02:00
roberto@debian32 5353eba35b improved the pyshell 2011-08-04 07:05:39 +02:00
roberto@debian32 4f94ceed5e fix for solaris 2011-08-03 16:00:35 +02:00
roberto@debian32 cd29998b40 --pyshell and fix for wsgi.url_scheme in pep3333 2011-08-03 15:07:15 +02:00
roberto@debian32 9aad6be26a better realoding in lazy mode 2011-08-03 06:54:48 +02:00
roberto@debian32 19edee88bc fixed --log-master 2011-08-02 21:15:10 +02:00
roberto@debian32 42e6a7d024 wait max 60 seconds for gracefull reload 2011-08-02 20:36:16 +02:00
roberto@debian32 1890290d05 fixed reload-mercy in lazy mode 2011-08-02 20:28:31 +02:00
roberto@debian32 c85231be96 improved picasso test 2011-08-02 16:10:17 +02:00
roberto@debian32 0ca89771d6 fixed pump method 2011-08-02 16:01:06 +02:00
roberto@debian32 d203b12464 fixed --http-var 2011-08-02 15:48:54 +02:00
roberto@debian32 b64690bdd6 allow compilation of pump in python3 2011-08-02 15:38:41 +02:00
roberto@debian32 e76c696678 completed pump support 2011-08-02 15:31:39 +02:00
roberto@debian32 f1ad2090fc remove incompatible LDFLAGS 2011-08-02 15:13:21 +02:00
roberto@debian32 f0be3c3966 fixed rack.scheme 2011-08-02 15:02:26 +02:00
roberto@debian32 8b7abc956f first round for pump support 2011-08-02 13:56:52 +02:00
roberto@debian32 25a8af392b fixed a leak in web3 subhandler 2011-08-02 12:48:15 +02:00
roberto@debian32 ebe1b3497e updated web3 handler 2011-08-02 09:33:49 +02:00
roberto@debian32 6a7246fe5a a little fix 2011-07-31 19:47:54 +02:00
roberto@debian32 1d64e46fcd support for data:// in import/module 2011-07-31 19:42:24 +02:00
roberto@debian32 6d5e089e4e uwsgi.ZipImporter 2011-07-31 19:32:14 +02:00
roberto@debian32 845bc1d41b added data:// facility 2011-07-31 18:51:10 +02:00
roberto@solarixexpress 007cd73ac5 solaris fix 2011-07-31 19:13:01 +00:00
roberto@freebsd64 651a7e4078 added freebsd binary detection 2011-07-31 17:47:15 +02:00
roberto@debian32 c3423370ec added binary detection for sun 2011-07-31 16:07:36 +02:00
roberto@mrspurr 500f1e37f6 better binary detection in osx 2011-07-31 17:25:10 +02:00
roberto@debian32 699a9bfa8e better binary detection on linux 2011-07-31 15:39:36 +02:00
roberto@debian32 90aa7f0d0e fixed --set 2011-07-31 14:44:36 +02:00
roberto@debian32 527819703e added -S/--set option 2011-07-31 14:35:54 +02:00
roberto@debian32 47adc8fe48 added --http-socket and --fastcgi-socket 2011-07-29 14:26:07 +02:00
roberto@debian32 865ad5d631 virtualhosting for http protocol 2011-07-29 13:59:29 +02:00
roberto@debian32 877b99c1d5 extreme optimization for http protocol 2011-07-29 13:49:22 +02:00
roberto@debian32 45bb124200 fixed a typo 2011-07-29 10:04:10 +02:00
roberto@debian32 147af04342 fixed apache2 module, adding uWSGImaxVars directive (bug #31) 2011-07-29 08:06:13 +02:00
roberto@debian32 b30e54bdc1 close bug #35 2011-07-29 07:30:24 +02:00
roberto@debian32 1b7484cf22 closed bug #34 2011-07-29 07:27:03 +02:00
roberto@debian32 c04513f8bd fixed SERVER_PORT in http protocol handler 2011-07-29 06:13:50 +02:00
roberto@debian32 c29db6ee6f cache fixed WSGI values 2011-07-29 05:53:54 +02:00
roberto@debian32 0d60b001fb uwsgi.cache_update 2011-07-28 10:27:37 +02:00
roberto@dexter ea7d428c1b added UWSGI.signal_registered 2011-07-27 11:11:30 +02:00
roberto@dexter 55ac61dbb0 signal framework ported to ruby.rack plugin 2011-07-27 10:58:03 +02:00
roberto@mrspurr 048878b197 added uwsgi.signal to ruby interface 2011-07-27 08:27:24 +02:00
roberto@dexter 1e479de839 auto-set post-buffering in rack plugin 2011-07-26 09:46:11 +02:00
roberto@debian32 5b34f6c515 fixed multiprotocol uwsgi.sendfile 2011-07-26 07:06:46 +02:00
roberto@centos6 8fcf83769c a zombie cannot be avoided... 2011-07-25 08:58:17 +02:00
roberto@centos6 d1ca55da55 get rid of a zombie in http-only mode 2011-07-25 08:23:05 +02:00
roberto@gambit 375328623b Added tag 0.9.8.3 for changeset f4d3c4dcd7a6 2011-07-23 08:27:35 +02:00
roberto@gambit be15137a49 uWSGI 0.9.8.3 2011-07-23 08:26:42 +02:00
roberto@dexter 43d89b2eaf added --freebind option (Linux only) 2011-07-22 13:11:14 +02:00
roberto@fedora15 d590a189ed added support for systemd socket activation 2011-07-22 13:03:18 +02:00
roberto@dexter c26861bff6 fixed fd 0 inheritance for xinetd support 2011-07-22 11:11:03 +02:00
roberto@mrspurr b4923deae2 fixed OSX build 2011-07-21 18:50:00 +02:00
roberto@natty32 20e7a65d92 finalized zip import 2011-07-19 21:19:15 +02:00
roberto@natty32 fc895d105e added bootstrap2.py for uwsgi.SymZipImporter class 2011-07-19 20:28:45 +02:00
roberto@natty32 e0e8dbe6b6 added uwsgi.SymZipImporter class 2011-07-19 20:28:04 +02:00
roberto@sirius 8e5834dcbb Added tag 0.9.8.2 for changeset 7169ef1d68d3 2011-07-19 07:53:44 +02:00
roberto@natty32 668c173969 uWSGI 0.9.8.2 2011-07-19 07:36:11 +02:00
roberto@debian32 4c19a941eb disabled embedded loading in python 3.x 2011-07-18 19:18:00 +02:00
roberto@debian32 9761153ab0 symbol based python importer in C 2011-07-18 18:24:01 +02:00
roberto@debian32 140a1b1587 added a django template loader for embedded files 2011-07-16 09:15:14 +02:00
roberto@debian32 e5f5f40f3c added bootstrap.py 2011-07-16 08:20:52 +02:00
roberto@debian32 2e13622ecc build directory 2011-07-16 08:05:26 +02:00
roberto@debian32 a4fb281859 allow directories to be embedded 2011-07-16 08:01:07 +02:00
roberto@dexter 75ba4e2220 better translation in import by filename 2011-07-15 12:02:42 +02:00
roberto@dexter 24b17da2ea added AUTHORS file 2011-07-15 11:15:07 +02:00
roberto@dexter c4664fe6e3 thunder_lock enabled only in threading mode 2011-07-15 10:51:35 +02:00
roberto@debian32 a1ab298609 Changelog for 0.9.8.2 2011-07-15 05:53:05 +02:00
roberto@natty32 533f9f8323 fixed an ini and yaml parsing bug spotted by Raffaele Colace 2011-07-14 20:03:20 +02:00
roberto@sirius 6d5912f307 a couple of spooler improvements 2011-07-13 19:41:56 +02:00
roberto@centos6 3d2b7c136a drop privileges after chown-socket (second-try) 2011-07-12 20:58:40 +02:00
roberto@centos6 f25d147908 drop privileges after chown-socket 2011-07-12 20:54:35 +02:00
roberto@centos6 e119c8cc53 solaris fix 2011-07-12 20:31:48 +02:00
roberto@centos6 73e94350df return the name of the spoolfile on uwsgi.spool() 2011-07-12 20:20:55 +02:00
roberto@centos6 9d8ee5aec8 --chown-socket 2011-07-12 20:11:19 +02:00
roberto@sirius c3bbd5f54f fixed spooler decorators 2011-07-11 19:15:26 +02:00
roberto@natty32 e17be93cb6 fixed rack.input 2011-07-11 11:56:19 +02:00
roberto@natty32 1013ca340a uwsgi.embedded_data 2011-07-10 19:47:53 +02:00
roberto@natty32 b87e7c0af8 added embed_files 2011-07-10 19:31:12 +02:00
roberto@natty32 615348c5a1 new embed_config build_option 2011-07-10 18:13:02 +02:00
roberto@natty32 cae0f9bc2e fixed fd leaks generated by new signal improvements 2011-07-10 16:26:36 +02:00
roberto@sirius 93b23e3de0 fixed cache-server on 64bit 2011-07-07 12:22:36 +02:00
roberto@natty32 eebb00d2b3 cache-server implementation 2011-07-07 12:02:11 +02:00
roberto@natty32 11f9b04fd1 thunder lock (sigh) 2011-07-07 09:58:03 +02:00
roberto@natty32 bde996de75 added -f in rm for make clean 2011-07-07 09:44:57 +02:00
roberto@natty32 552163a3bd second try for fixing inheritance of build profiles 2011-07-07 09:35:14 +02:00
roberto@natty32 2e6af966a9 revert last useless fix 2011-07-07 09:27:38 +02:00
roberto@natty32 c1775967c8 fixed build system 2011-07-07 09:25:10 +02:00
roberto@natty32 034a0a594d remove json from unbitstaff 2011-07-07 09:11:26 +02:00
roberto@natty32 63a66ea82a added an hello_world 2011-07-07 08:35:23 +02:00
roberto@maverick64 6f155ebf17 spooler object debug 2011-07-06 19:43:28 +02:00
roberto@maverick64 f39d8cc5fb fixed spooler for python 3 2011-07-06 18:17:53 +02:00
roberto@maverick64 aecba7e710 export UWSGI_VASSALS_DIR even on stop-hook 2011-07-05 20:17:34 +02:00
roberto@maverick64 c365eeec76 fixed a typo 2011-07-05 15:06:51 +02:00
roberto@maverick64 5bd06402de added shebang in decoratortest.py 2011-07-05 14:56:23 +02:00
roberto@maverick64 ec899a45d5 added body to spooler 2011-07-05 14:55:10 +02:00
roberto@maverick64 513c9cee3d allow plugin to be written in C++ 2011-07-05 11:28:35 +02:00
roberto@mrspurr 850f2abd5c fixed psgi on osx 2011-07-05 07:50:27 +02:00
roberto@maverick64 8d7940ebee fixed plugin value in uwsgi.opt 2011-07-04 16:14:33 +02:00
roberto@maverick64 195e9c398e use TCP port '0' for auto-socket in http mode 2011-07-04 10:38:07 +02:00
roberto@longshot c998d6bd1b fixed a master bug in socketpair 2011-07-04 09:55:13 +02:00
roberto@maverick64 34be14ece1 updated unbit.ini 2011-07-04 09:17:34 +02:00
roberto@maverick64 c0d6f33d54 support SIGQUIT in emperor 2011-07-03 19:17:24 +02:00
roberto@maverick64 d5210283ca launch stop hook on emperor quit 2011-07-03 19:16:09 +02:00
roberto@maverick64 545784d7af fixed ticket #12 reported bugs 2011-07-03 19:08:22 +02:00
roberto@maverick64 e9726b1e75 fixed ticket #28 2011-07-03 12:59:58 +02:00
roberto@maverick64 e08b2cccf9 implemented workerN signal target 2011-07-03 12:55:18 +02:00
roberto@maverick64 0ba1b982d1 implemented target='workers' for signal infrastructure 2011-07-03 12:43:30 +02:00
roberto@maverick64 374c02c46e prefork/multithread uwsgi.signal_wait() implementation 2011-07-03 12:00:06 +02:00
roberto@maverick64 5ed59690a0 report time taken for each spooler job 2011-07-02 19:53:31 +02:00
roberto@maverick64 2de489f301 fixed uwsgi_log_verbose 2011-07-02 19:49:12 +02:00
roberto@maverick64 40a722294f added 'at' variable to the spooler 2011-07-02 11:04:25 +02:00
roberto@maverick64 9598c525cf export uwsgi.node in WSGI vars 2011-07-02 10:03:34 +02:00
roberto@maverick64 3ed6c5e943 added @lock decorator 2011-07-02 09:22:52 +02:00
roberto@maverick64 0f178c17ee report threading status in uwsgicc 2011-07-02 08:43:52 +02:00
roberto@maverick64 1c963b72a3 added @thread decorator 2011-07-02 08:35:08 +02:00
roberto@maverick64 bd1b3b8b12 allows spooler to manage signals 2011-07-01 15:17:43 +02:00
roberto@maverick64 f9a843dfd5 added @postfork decorator 2011-07-01 10:03:16 +02:00
roberto@maverick64 9df8f4ae2b better spooler check 2011-07-01 09:56:38 +02:00
roberto@maverick64 87f649b71b a new bunch of decorators 2011-07-01 09:48:54 +02:00
roberto@sirius 3585bb0a6e added spoolforever 2011-07-01 09:12:30 +02:00
roberto@sirius 750bbd64b2 new option --import, new api function uwsgi.signal_registered 2011-07-01 09:05:55 +02:00
roberto@maverick64 19c567cef3 fixed fastrouter nodes stats 2011-06-30 13:00:14 +02:00
roberto@maverick64 5024368854 gather statistics about subscribed fastrouter nodes 2011-06-30 12:56:13 +02:00
roberto@debian32 3200f88363 applied Riccardo Magliocchetti patch for spooler pid and uwsgicc 2011-06-28 15:14:49 +02:00
roberto@debian32 650c77d0d1 refactored cgroups 2011-06-28 06:46:43 +02:00
roberto@debian32 3fa29515f2 --emperor-broodlord added 2011-06-27 20:27:34 +02:00
roberto@debian32 012435747e first attempt of bloodlord mode 2011-06-27 18:18:24 +02:00
roberto@debian32 733077a437 added another example 2011-06-26 18:18:57 +02:00
roberto@debian32 6b3fa74800 fixed uwsgi.h indentation 2011-06-26 11:36:18 +02:00
roberto@freebsd64 d673627c79 FreeBSD fix and applied riccardo's patch 2011-06-26 11:35:18 +02:00
roberto@debian32 8b423d00e9 added priority keyword to spooler 2011-06-26 11:26:52 +02:00
roberto@gambit 201086c854 uWSGI 0.9.8.1 2011-06-25 10:34:50 +02:00
roberto@gambit 2441cf36b3 Added tag 0.9.8.1 for changeset fd8477b6348f 2011-06-25 10:33:43 +02:00
roberto@debian32 df0f2a549e TODO: survive to dynamic loading errors 2011-06-25 10:24:52 +02:00
roberto@debian32 9b7cbab37c preparing for official release... 2011-06-25 10:09:44 +02:00
roberto@debian32 ac46cb2371 a bit of debug junk 2011-06-25 10:08:42 +02:00
roberto@debian32 c858c88bb3 fixed a race condition 2011-06-25 09:52:42 +02:00
roberto@debian32 a05f5d9860 another series (the last i hope) of threading fixes 2011-06-25 09:36:59 +02:00
roberto@debian32 e6914b91e1 spooler task are now managed asap on startup 2011-06-25 08:13:15 +02:00
roberto@debian32 b624bd2d35 update psgix.harakiri to last spec 2011-06-25 08:03:28 +02:00
roberto@debian32 e3c9b2c0bf cheap+idle+lazy improved for threading 2011-06-25 07:58:40 +02:00
roberto@debian32 576a1e7cb2 fixed threadstate swap 2011-06-25 07:44:21 +02:00
roberto@debian32 55c3ba73d3 added Changelog for 0.9.8.1 2011-06-25 07:27:31 +02:00
roberto@debian32 2246d30bbe fixed threaded loading 2011-06-24 19:42:01 +02:00
roberto@goyle 789e333736 master_fixup on reloads 2011-06-24 07:41:01 +02:00
roberto@goyle 283904107f better master threading 2011-06-24 06:56:30 +02:00
roberto@goyle 8d92261852 re-enabled threads in master process 2011-06-23 20:50:14 +02:00
roberto@goyle e8f5d82b78 -propagate-touch 2011-06-22 12:40:00 +02:00
roberto@goyle 0a8643155e an attempt for a better touch reload in threading mode 2011-06-22 12:12:15 +02:00
roberto@goyle 61793201c7 fixed uwsgi.sendfile in threading mode 2011-06-22 11:14:02 +02:00
roberto@goyle 41f2982074 fixed stupid bug in wsgi.input readline 2011-06-22 07:19:49 +02:00
roberto@goyle 27b86f1b79 fixed a bug in dynamic touch reload 2011-06-21 17:19:28 +02:00
roberto@goyle d69892c91e @europython add --logto2 option 2011-06-21 14:53:50 +02:00
roberto@debian32 296549d1bf export %c in config files 2011-06-18 11:59:37 +02:00
roberto@debian32 7d2f147172 fixed libyaml support and support for modifiers in subscription requests 2011-06-18 11:31:38 +02:00
roberto@debian32 aa56f99ee2 reset random seed on first python spooler job 2011-06-18 09:32:23 +02:00
roberto@debian32 ca82b99f42 subscribe from file 2011-06-18 08:59:02 +02:00
roberto@debian32 d204a5b844 allow binding to port 0 (auto-assignment) 2011-06-18 07:50:37 +02:00
roberto@debian32 0a98550770 reset random seed on grunt 2011-06-18 06:58:01 +02:00
roberto@debian32 0c0c2736a7 maintain a constant mapping in vhost mode 2011-06-17 17:54:49 +02:00
roberto@debian32 27e2d984ce debug in virtualhosting 2011-06-17 17:41:48 +02:00
roberto@debian32 14eeae09b1 fix python3 + virtualenv 2011-06-17 16:31:55 +02:00
roberto@debian32 16eb47070d survive to task doing chdir() in the spooler 2011-06-17 16:20:02 +02:00
roberto@debian32 1f69f58593 fixed a stupid bug in non-async initialization 2011-06-17 08:44:32 +02:00
roberto@debian32 1b4421e013 better zeromq+clustering support 2011-06-17 08:11:56 +02:00
roberto@debian32 f13400d592 improved zeromq support 2011-06-17 07:52:38 +02:00
roberto@mrspurr e29f0323ea fixed make clean 2011-06-17 07:33:53 +02:00
roberto@debian32 15a582d046 allow clustering without a socket 2011-06-17 07:26:36 +02:00
roberto@mrspurr 1e01f8be17 fixed a typecast in fastcgi 2011-06-17 06:39:44 +02:00
roberto@debian32 8cc73991a3 added checks for decorators 2011-06-16 13:52:22 +02:00
roberto@debian32 ecce74ade5 less verbose logging in inotify 2011-06-16 10:16:06 +02:00
roberto@debian32 836efaaf70 less verbose logging in python api for clustering 2011-06-16 07:20:15 +02:00
roberto@debian32 46f8e7dc00 less verbose log in cluster joining 2011-06-16 07:17:35 +02:00
roberto@mrspurr 88cd033ca6 refactored clustering 2011-06-16 07:08:56 +02:00
roberto@debian32 984df3bcdf added signal sending in uwsgicc 2011-06-15 19:05:14 +02:00
roberto@debian32 7673cdb1aa refactored uwsgi_parse_response to uwsgi_parse_packet 2011-06-15 14:01:00 +02:00
roberto@debian32 8af700ce37 fixed rpc 2011-06-15 12:30:01 +02:00
roberto@mrspurr ffb8752190 report corrent worker id in cheap mode 2011-06-15 07:04:07 +02:00
roberto 71fa3ab3af report max buffer_size on pktsize error 2011-06-14 14:07:48 +00:00
roberto@dj1 09501cfa74 remove pipe in uwsgi_daemon 2011-06-14 13:37:33 +00:00
roberto@dj1 d84ae12733 fixed a fd leak in attach-daemon 2011-06-14 13:37:00 +00:00
roberto@dj1 05f292abe6 use setsid in attach-daemon 2011-06-14 13:22:14 +00:00
roberto@sirius a75833d322 OSX fixes 2011-06-14 11:26:03 +02:00
roberto@debian32 ca3f56de5c Zerg mode added 2011-06-14 11:24:25 +02:00
roberto@debian32 9d75f2c9c7 added psgix.harakiri.supported 2011-06-13 19:13:12 +02:00
roberto@debian32 a58cbf92b0 added psgix.harakiri 2011-06-13 16:45:19 +02:00
roberto@debian32 7bac76fae5 added PLACK_SERVER 2011-06-13 11:55:42 +02:00
roberto@debian32 9c71b39edd fixed rpc 2011-06-13 09:07:49 +02:00
roberto@debian32 52f731c6b7 fixed argv clobbering in command line module functions 2011-06-13 08:17:36 +02:00
roberto@dj1.djangocloud.com 735d1cb689 fixed fastrouter 2011-06-12 13:19:39 -05:00
roberto@debian32 5a0977f412 allows magic vars in sqlite3 db 2011-06-12 19:58:38 +02:00
roberto@dj1 1da1fccbc7 fixed plugin loading 2011-06-12 12:19:23 -05:00
roberto@debian32 ca5a528818 added UWSGI_FASTROUTER_KEY var 2011-06-12 11:45:30 +02:00
roberto@debian32 a9ef806a37 added flaskpost to address a bug reported on post-buffering 2011-06-12 09:04:59 +02:00
roberto@debian32 de112b7788 no more than 1 'async queue is full' message per-second 2011-06-12 07:16:24 +02:00
roberto@debian32 ef7baba274 process options in reverse order for better templating 2011-06-12 06:51:45 +02:00
roberto@debian32 3a9d13b011 --cron option, thanks Simon Litchfield for the idea 2011-06-11 15:05:20 +02:00
roberto@debian32 5b5493aab0 --vassals-start-hook and --vassals-stop-hook 2011-06-11 11:56:21 +02:00
roberto@debian32 5f208d8f12 remove the old proxy plugin, bug #8 2011-06-11 10:54:59 +02:00
roberto@debian32 47c077d066 closed bug #14 2011-06-11 10:45:58 +02:00
roberto@debian32 d2ac69b6c1 applied leonid borisenko patch for better automagic plugin loading 2011-06-11 09:47:42 +02:00
roberto@dj1 8860cac7dd close unneded fd in subemperor and vassals 2011-06-08 13:54:50 -05:00
roberto@debian32 28bcc73c70 reintroduced clang support 2011-06-07 21:26:07 +02:00
roberto@netbsd64 af20c2d8f0 fix CMSG_SPACE mess 2011-06-07 22:37:55 +02:00
roberto@mrspurr 44213ca510 move msg_control union to end of struct wsgi_request (as suggested by Riccardo Magliocchetti) 2011-06-07 20:02:24 +02:00
roberto@mrspurr ab21a1ac00 applied Piotr Sikora fix for OpenBSD/NetBSD 2011-06-07 20:00:36 +02:00
roberto@dj1 a67f366501 fix for abstract socket without prefix 2011-06-07 06:21:09 -05:00
roberto@mrspurr b32251e5aa osx launchd examples 2011-06-07 06:37:54 +02:00
roberto@gambit 16e0accb74 uWSGI 0.9.8 2011-06-05 08:28:03 +02:00
roberto@gambit c6ce291cbf Added tag 0.9.8 for changeset 42efe1f32900 2011-06-05 08:27:51 +02:00
roberto@debian32 b7525475d8 ready for 0.9.8 release 2011-06-05 08:20:23 +02:00
roberto@debian32 f35a36ac02 set a mercy mode for INT/QUIT 2011-06-05 07:38:58 +02:00
roberto@netbsd64 3b53f89a24 netbsd fix 2011-06-05 09:17:38 +02:00
roberto@debian32 764d94e41b support for abstract unix socket prefixed with \0 2011-06-04 08:55:49 +02:00
roberto@indianajones 0292e15497 add /lib to linker on SunOS-derived systems 2011-06-02 19:35:05 +01:00
roberto@debian32 bde4ac7b2f uWSGI 0.9.8-rc4 2011-06-02 18:53:49 +02:00
roberto@debian32 c71fa3abd1 Added tag 0.9.8-rc4 for changeset 0f1f3924ee53 2011-06-02 18:53:38 +02:00
roberto@indianajones d2abdb5d3a fix accept() to receive the correct ip 2011-06-02 18:44:48 +01:00
roberto@indianajones 1392791837 OpenIndiana is now officially supported 2011-06-02 15:15:35 +01:00
roberto@goyle 6f7d9634d5 allows log-date 2011-06-02 12:08:56 +02:00
roberto@goyle 82b95114a8 added welcome.py 2011-06-02 11:38:18 +02:00
roberto@debian32 d90e701acd use int in uwsgi.version_info 2011-06-01 13:02:33 +02:00
roberto@debian32 42993022bb python3 fix 2011-06-01 12:55:20 +02:00
roberto@dj1 29b1e46252 uwsgi.version_info 2011-06-01 05:52:46 -05:00
roberto@sirius 260cea639f better myadmin.py 2011-06-01 10:04:57 +02:00
roberto@sirius 208aea8aca two new management flag for backlog queue 2011-06-01 10:00:17 +02:00
roberto@sirius f164d401d3 another uwsgi_log fix 2011-06-01 09:47:58 +02:00
roberto@dj1 5e1c34a08b really fix uwsgi_log 2011-06-01 02:15:53 -05:00
roberto@debian32 9c7b596a0d fixed uwsgi_log 2011-06-01 08:38:51 +02:00
roberto@debian32 5ff34ac6d0 a couple of admin plugin fixes 2011-06-01 08:12:50 +02:00
roberto@debian32 e304e34929 throw exception on too much big spool requests 2011-06-01 07:11:54 +02:00
roberto@dj1 6d7848248d added --early-emperor option 2011-05-31 08:44:26 -05:00
roberto@sirius dbc0da0586 support for idle mode in single process mode 2011-05-31 14:26:57 +02:00
roberto@debian32 fecdcf9d10 allows sub-emperors (emperors generated by emperors) 2011-05-31 08:56:03 +02:00
roberto@sirius bfd0ab2301 fixed a typo 2011-05-30 19:10:01 +02:00
roberto@sirius 8002777e75 uWSGI 0.9.8-rc3 2011-05-30 19:04:05 +02:00
roberto@debian32 d57d5acb30 --idle mode 2011-05-29 06:52:47 +02:00
roberto@debian32 43e6664dd9 --cheap option 2011-05-28 19:43:29 +02:00
roberto@dj1 d0c6dff83e --add-header option 2011-05-28 05:20:48 -05:00
roberto@dj1 54b40f5978 better cgroup support 2011-05-27 14:23:22 -05:00
roberto@dj1 1c59c03261 unlimited sockets for fastrouter 2011-05-27 08:55:15 -05:00
roberto@dj1 ce23fd38ab better emperor+master mode 2011-05-27 05:11:41 -05:00
roberto@dj1 4818efa7de emperor+amqp fixes 2011-05-27 04:07:07 -05:00
roberto@dj1 ea19e74229 better netlink ns detection 2011-05-27 03:21:21 -05:00
roberto@dj1 fe353de5a8 fixed netlink compilation 2011-05-27 01:58:43 -05:00
roberto@dj1 1d89266f2e unlimited shared sockets 2011-05-27 01:39:01 -05:00
roberto@debian32 61d79394ca --fastrouter-subscription-slot 2011-05-26 05:35:43 +02:00
roberto@debian32 491f2828b5 --no-fd-passing 2011-05-26 05:29:01 +02:00
roberto@nexenta32 431e05d4f4 fixed ifaddrs support 2011-05-26 06:17:46 +02:00
roberto@solarisexpress ae6780a487 remember: do not use the word 'sun' as variable on solaris... 2011-05-26 04:54:55 +00:00
roberto@debian32 5707a70141 added --log-socket 2011-05-25 08:57:13 +02:00
roberto@debian32 e9a7bd7da1 add abstract unix socket 2011-05-23 21:50:04 +02:00
roberto@debian32 91e45daf6c better unix socket support in abstract namespace (Linux only) 2011-05-23 16:10:27 +02:00
roberto@debian32 9f69998075 grunt improvement 2011-05-23 11:43:22 +02:00
roberto@debian32 4f6270976b fixed python3.x spooler 2011-05-22 14:07:01 +02:00
roberto@debian32 328caa43f2 allow --auto-snapshot to take a value 2011-05-22 11:56:58 +02:00
roberto@debian32 368408374a preliminary snapshotting support 2011-05-22 11:43:28 +02:00
roberto@debian32 c3a90db493 uWSGI 0.9.8-rc2 2011-05-21 08:10:03 +02:00
roberto@debian32 5bc0320877 Added tag 0.9.8-rc2 for changeset e91bc724325e 2011-05-21 08:09:49 +02:00
roberto@debian32 622ed620b9 fixed python 3.1 2011-05-21 08:03:22 +02:00
roberto@debian2 1b859413de add mercurial revision to uWSGI version string 2011-05-21 07:43:49 +02:00
roberto@maverick64 95432fd8e3 added --die-on-term 2011-05-19 20:35:47 +02:00
roberto@freebsd64 b3f3c5d7b3 fixed touch reload 2011-05-19 09:33:25 +02:00
roberto@debian32 02cef20462 another fix for wsgi.input 2011-05-19 08:33:11 +02:00
roberto@debian32 3edebe34ae improved upload test 2011-05-18 21:15:41 +02:00
roberto@longshot 28c9b75fb5 wsgi.input fix 2011-05-18 21:10:18 +02:00
roberto@fedora15 a2735e10b7 report number of vassals to systemd 2011-05-17 08:57:50 +02:00
roberto@fedora15 e03d26fd63 report emperor dead status to systemd 2011-05-17 08:36:54 +02:00
roberto@sirius 7c4c346e64 fix systemd on unsupported platform 2011-05-17 08:29:33 +02:00
roberto@fedora15 67b3c0c4a8 systemd integration 2011-05-17 08:26:39 +02:00
roberto@fedora15 dadca785e4 initial systemd support 2011-05-16 17:25:38 +02:00
roberto@debian32 accebe5597 add --log-prefix option 2011-05-16 10:06:47 +02:00
unbit@gambit 792965bedd uWSGI 0.9.8-rc1 2011-05-14 09:57:15 +02:00
unbit@localhost 1bb1bafe0c Added tag 0.9.8-rc1 for changeset d1e57707f631 2011-05-14 09:56:41 +02:00
roberto@debian32 28c11324ca merge 2011-05-14 09:34:29 +02:00
roberto@debian32 42d940c38e a bit of refactoring 2011-05-14 09:34:03 +02:00
roberto@freebsd64 c1ea05b925 fixed profiler compilation in older python 2011-05-14 07:08:33 +02:00
roberto@debian32 9435693865 removed old/useless writers.c 2011-05-13 18:49:31 +02:00
roberto@debian32 14da582637 various static file fixes 2011-05-13 18:46:21 +02:00
roberto@debian32 b2d4a795a1 various ruby.rack fixes 2011-05-13 18:19:26 +02:00
roberto@sirius 493696705b another off_t to size_t fix 2011-05-13 16:52:21 +02:00
roberto@debian32 d827c6f09a moved rack.input to the new POST api 2011-05-13 16:46:06 +02:00
roberto@debian32 df000b0cb2 support for jemalloc 2011-05-12 12:55:07 +02:00
roberto@debian32 d9630a32c7 added support for tcmalloc 2011-05-12 12:49:07 +02:00
roberto@debian32 71cc6f61bd fixed a stupid (really stupid) bug in uwsgi.core allocation 2011-05-11 19:04:52 +02:00
roberto@debian32 46eb832cc7 set in_request per core 2011-05-11 18:47:42 +02:00
roberto@debian32 11b2e4b430 lock goodbye_cruel_world in threading mode 2011-05-11 17:08:02 +02:00
roberto@debian32 11775532ee applied leonid patch for symlinks 2011-05-11 15:49:59 +02:00
roberto@debian32 f3388db8ba do not link core libraries in plugins 2011-05-11 12:28:15 +02:00
roberto@sirius 25ac86393f use size_t instead of off_t 2011-05-11 12:05:48 +02:00
roberto@debian32 b3432a95e1 finally fixed wsgi.input 2011-05-11 11:55:28 +02:00
roberto@debian32 e34d169fa6 merge 2011-05-11 06:24:11 +02:00
roberto@debian32 de84accb7a removed unused variable in pyerl 2011-05-11 06:23:40 +02:00
roberto@sirius 187577cbb5 fixed a stupid typo 2011-05-10 09:53:54 +02:00
roberto@debian32 72109b72d2 various rack fixes 2011-05-10 09:36:07 +02:00
roberto@debian32 f6c01d11e9 completed ruby 1.9 fiber support 2011-05-10 08:50:06 +02:00
roberto@debian32 d695ef4f57 removed garbage 2011-05-09 21:41:55 +02:00
roberto@debian32 16c6dcc573 better threading reload 2011-05-09 21:27:08 +02:00
roberto@debian32 3df19b286a support for plugin as symlinks 2011-05-09 20:18:49 +02:00
roberto@debian32 6f1b08762d adde fixup hook handler 2011-05-09 09:43:55 +02:00
roberto@debian32 a4a379f9d6 rack ported to new socket api 2011-05-07 09:32:49 +02:00
roberto@mrspurr 3d3d0304bc plugin autoloading (finally) 2011-05-07 09:21:07 +02:00
roberto@natty32 26135018a3 added check for patl method in psgi response 2011-05-06 08:09:30 +02:00
roberto@debian32 4bd381bb99 big PSGI update 2011-05-06 14:17:01 +02:00
roberto@debian32 cf08972e82 first round of memleak hunting in psgi/perl 2011-05-06 10:12:59 +02:00
roberto@natty32 d57a58d1e7 psgi input fix 2011-05-06 00:16:57 +02:00
roberto@natty32 f10789965e added seek to psgi custom object 2011-05-05 17:08:52 +02:00
roberto@natty32 94145bd300 temp --psgi-custom-input option 2011-05-05 17:04:51 +02:00
roberto@natty32 cdcb61d10d signal on python thread fix 2011-05-05 02:47:04 +02:00
roberto@natty32 56146a34af python get line number/profier fix 2011-05-05 02:40:53 +02:00
roberto@natty32 991e818449 fixes for python2.6 and forcing -bash in perl 2011-05-05 02:25:17 +02:00
roberto@natty32 80083cba76 funny hack to have a consistent __FILE__ in perl 2011-05-04 17:43:09 +02:00
roberto@natty32 2c44fd5aa2 fix stdout/stderr in python3 2011-05-04 15:39:24 +02:00
roberto@natty32 1561dd38fc another PSGI loading fix 2011-05-04 05:27:32 +02:00
roberto@natty32 8152648f66 psgi loading improvement 2011-05-04 04:59:01 +02:00
roberto@natty32 c1507d0381 put master logging in non-blocking mode 2011-05-04 03:33:44 +02:00
roberto@natty32 f0fb603af2 debug send/recv log buffer 2011-05-04 03:24:44 +02:00
roberto@natty32 93e891153f fixed sqlite3 support 2011-05-03 18:45:04 +02:00
roberto@natty32 26ece717b6 added support for sqlite3 configuration 2011-05-03 18:35:49 +02:00
roberto@natty32 93767335ca added --profiler 2011-05-03 15:01:51 +02:00
roberto@natty32 7cbe751a39 added --perl-local-lib 2011-05-02 17:12:32 +02:00
roberto@natty32 c45df83f19 set buffer size in $/ 2011-05-02 13:25:36 +02:00
roberto@natty32 fabce61a58 add PLACK_ENV and -bash 2011-05-02 12:11:38 +02:00
roberto@natty32 5c9ccae598 added PSGI streamer test 2011-05-02 08:44:50 +02:00
roberto@natty32 6c9d7239f2 uGreen support added to perl 2011-05-02 08:36:57 +02:00
roberto@natty32 4b75e2577e preliminary async/nonblocking support for PSGI 2011-05-02 07:58:16 +02:00
roberto@natty32 08c9d942a4 lazy mode support 2011-05-01 17:31:54 +02:00
roberto@natty32 3b59b4ad21 psgi: allows multiline headers 2011-05-01 17:01:05 +02:00
roberto@natty32 7682eec52a do not die on perl die() :P 2011-05-01 16:42:01 +02:00
roberto@sirius 694517bbe7 export all the required psgi.* vars and all of the supported psgix.* 2011-05-01 15:37:25 +02:00
roberto@natty32 7f443fdd05 allow globbed-pythonpath 2011-04-27 16:28:44 +02:00
roberto@natty32 01ab891c11 unlimited pythonpath entries 2011-04-27 15:56:33 +02:00
roberto@natty32 052aacfd36 fixed --map-socket 2011-04-27 15:46:00 +02:00
roberto@natty32 80a6d2ccfb various fixes in multiple sockets and support for file piped via stdin 2011-04-27 14:15:01 +02:00
roberto@debian32 b4ce175bdf add --master to carbon/graphite example 2011-04-27 08:08:59 +02:00
roberto@debian32 f6f52d32dc fixed a typo 2011-04-27 08:07:19 +02:00
roberto@debian32 865b2de9bb added an example script for graphite/carbon update 2011-04-27 08:04:45 +02:00
roberto@debian32 4a8233a041 support for libzmq 2.0 2011-04-26 19:39:40 +02:00
roberto@natty32 f856ad78a3 added --log-zeromq 2011-04-26 17:26:40 +02:00
roberto@debian32 653267cbe6 added libyaml support, for future advanced implementations 2011-04-26 08:45:44 +02:00
roberto@debian32 8b53df27ab gcc-4.6 fixes and applied Riccardo Magliocchetti patch for libm 2011-04-26 07:38:10 +02:00
roberto@debian32 c4b7c2b58c fix build without zeromq 2011-04-25 16:56:06 +02:00
roberto@maverick64 66f82f364c fixed clustering 2011-04-25 09:50:11 +02:00
roberto@maverick64 6d269607d2 allow clustering + zeromq 2011-04-25 09:38:26 +02:00
roberto@maverick64 8370977e5b fixed indentation 2011-04-25 07:15:41 +02:00
roberto@maverick64 e2c335ff73 threaded zeromq/mongrel2 support 2011-04-25 07:13:23 +02:00
roberto@maverick64 816b9d0343 refactored zeromq 2011-04-24 18:50:44 +02:00
roberto@maverick64 2922e1ba35 slowdown vassals spawn 2011-04-24 07:38:38 +02:00
roberto@maverick64 c86f341d29 first part of --socket-protocol option 2011-04-22 09:34:50 +02:00
roberto@maverick64 73cdd68283 fixed modifier1 30 2011-04-22 09:18:07 +02:00
roberto@maverick64 81641686bc various fixes 2011-04-22 08:51:29 +02:00
roberto@maverick64 14c58c8e62 fixed preforking+threading 2011-04-22 07:53:32 +02:00
roberto@maverick64 74b8f2587c prototype for uwsgidump protocol 2011-04-21 19:28:02 +02:00
roberto@mrspurr bebe041061 added psgi full streaming support 2011-04-21 06:24:41 +02:00
roberto@msrpurr 2e5d3d2952 fixed response size in PSGI 2011-04-21 04:26:58 +02:00
roberto@mrspurr c2d155b8ff --inherit and --vassals-inherit 2011-04-20 21:33:56 +02:00
roberto@natty32 fda368ff08 added support for mongrel2 tnetstrings 2011-04-20 11:49:41 +02:00
roberto@natty32 19cf592e77 fastcgi optimization 2011-04-20 09:32:37 +02:00
roberto@natty32 260cac6b59 fixed zeromq post-file close 2011-04-19 18:19:08 +02:00
roberto@natty32 673275e708 multiprotocol refactoring 2011-04-19 18:14:40 +02:00
roberto@freebsd64 a6bc778c25 conditionally compile libuuid 2011-04-19 20:46:31 +02:00
roberto@centos32 ef2f5879b6 conditionally compile netlink support 2011-04-19 13:46:26 +02:00
roberto@sirius ee725bf625 fixed compilation in no-zmq environments 2011-04-19 11:35:03 +02:00
roberto@natty32 5388fa442c completed zeromq support 2011-04-19 08:34:03 +02:00
roberto@natty32 913493fd2e mongrel2/zeromq support added 2011-04-19 06:59:34 +02:00
roberto@natty32 6d4a8c6619 added a pure-zeromq loop engine 2011-04-18 20:00:26 +02:00
roberto@natty32 4a57115336 edge triggered events support 2011-04-18 17:07:13 +02:00
roberto@natty32 1dd754a0d5 fallback to read/write instead of sendfile in fastcgi mode 2011-04-18 06:32:52 +02:00
roberto@natty32 509b78d906 fastcgi fixes 2011-04-18 05:04:11 +02:00
roberto@natty32 363366d012 preliminary fastcgi support 2011-04-17 07:35:15 +02:00
roberto@natty32 26d4fd4e00 fixed uwsgi protocol support 2011-04-16 20:02:27 +02:00
roberto@natty32 09ee97e775 first destructive commit for uWSGI 0.9.8 2011-04-16 19:41:58 +02:00
roberto@natty32 1400a95cec added JSON support to the Emperor 2011-04-14 09:38:06 +02:00
roberto@natty32 5e96c4ca79 fixed json support with pkg-config 2011-04-14 09:10:03 +02:00
roberto@sirius 3c068b2a00 fixed http support 2011-04-14 09:47:04 +02:00
roberto@sirius 81fd7757c1 JSON support, thanks jansson 2011-04-14 09:32:17 +02:00
roberto@natty32 1db64b72ae fixed build of PSGI plugin on non-Apple platform 2011-04-13 13:27:32 +02:00
roberto@natty32 ab1bed236c use close-on-exec instead of close() on osx reload 2011-04-13 07:38:46 +02:00
roberto@debian64 e503999392 fixed virtualhosting with dynamic virtualenv 2011-04-12 10:34:36 +02:00
roberto@dj1 2392eb7e0b fixed wait in emperor 2011-04-08 03:25:16 -05:00
roberto@dj1 c62b54f18d added vassal loyalty concept 2011-04-08 02:43:05 -05:00
roberto@natty32 603d46c1ae merge 2011-04-07 08:46:34 +02:00
roberto@natty32 c0e0ae551d use binary stream for wsgi.input in Python 3.x 2011-04-07 08:45:59 +02:00
unbit@localhost a0a2507c05 Added tag 0.9.7.2 for changeset a5f13497b392 2011-04-06 09:50:01 +02:00
roberto@natty32 6eed48b28d updated Changelog and copyright year 2011-04-06 09:29:46 +02:00
roberto@netbsd64 9c5d289098 better locking for NetBSD and OpenBSD 2011-04-06 08:16:03 +02:00
roberto@solarisexpress 42ab7f23d8 added timegm to solaris 2011-04-06 06:03:17 +00:00
roberto@natty32 c9c2f4232e preparing for 0.9.7.2 release 2011-04-06 05:06:38 +02:00
roberto@longshot d4f23cc6bd use realpath() for document_root 2011-04-05 20:55:48 +02:00
roberto@natty32 b0db67d4d4 refactored post limit management 2011-04-05 16:51:40 +02:00
roberto@natty32 703cad6715 disallow empty socket names 2011-04-05 11:32:15 +02:00
roberto@natty32 667d67460f do not build netlink support (still useless for non-third-party plugins) 2011-04-05 09:00:58 +02:00
roberto@natty32 35cf9ae328 implemented exc_info in WSGI start_response and added --reload-on-as and --reload-on-rss 2011-04-05 08:58:22 +02:00
roberto@natty32 c04131af4b fixed syslog support 2011-04-04 17:17:47 +02:00
roberto@natty32 9cc4db1a12 various fixes 2011-04-04 09:46:17 +02:00
roberto@natty32 b326500913 --static-map mountpoint=documentroot option 2011-04-04 08:31:17 +02:00
roberto@natty32 a26579fcf5 better plugin loading 2011-04-03 08:18:51 +02:00
roberto@natty32 a2b9c44433 -ldl should be used only for Linux 2011-04-02 15:57:57 +02:00
roberto@natty32 c3b97da1d4 various Riccardo Magliocchetti build fixes 2011-04-02 15:26:00 +02:00
roberto@natty32 048cf0232a nailed connection between emperor and rabbitmq 2011-04-01 16:11:18 +02:00
roberto@natty32 89c113bee6 added EXILE mode for vassals 2011-04-01 08:35:20 +02:00
roberto@natty32 6b9969a302 allow emperor config files to be taken via http 2011-04-01 08:09:34 +02:00
roberto@natty32 a6e7513d2a declare exchange automatically 2011-04-01 07:13:09 +02:00
roberto@natty32 8a04f4810f allow vassals configuration to be stored on amqp/rabbitmq servers 2011-04-01 06:31:54 +02:00
roberto@natty32 1d9d443de0 amqp/rabbitmq emperor fixes 2011-04-01 05:17:50 +02:00
roberto@natty32 00e5809a71 preliminary amqp/rabbitmq support for emperor 2011-04-01 03:14:51 +02:00
roberto@freebsd64 07ba4a040b fixed freebsd kvm_open 2011-03-30 20:48:01 +02:00
roberto@mrspurr 7b319d230a allow building of psgi plugin without ithreads 2011-03-30 08:03:48 +02:00
roberto@natty32 641bc2daec fixed unbitstaff build profile 2011-03-29 12:06:13 +02:00
roberto@dj2 fbaa30cc08 various fixes 2011-03-28 11:31:40 -05:00
roberto@dj2 a0c2c9056b fixed a couple fo emperor race conditions 2011-03-28 09:37:17 -05:00
roberto@dj2 30ab5fd76b added --exit-on-reload 2011-03-28 07:31:51 -05:00
roberto@dj2 30beab4017 fixed a regression in setgroups() 2011-03-28 05:38:29 -05:00
roberto@dj2 4ec1493b09 fixed subscription system 2011-03-28 04:29:04 -05:00
roberto@dj2 e7cbe9709e build netlink support in Linux 2011-03-28 04:17:07 -05:00
roberto@dj2 aacaeba525 shared sockets support 2011-03-28 04:15:31 -05:00
roberto@dj2 6e4da5efb7 add netlink library 2011-03-28 04:11:31 -05:00
roberto@natty32 87443a4ff2 Added tag 0.9.7.1 for changeset 486e7760bcbc 2011-03-26 09:39:57 +01:00
roberto@natty32 9746759c68 fixed changelog before official release 2011-03-26 09:39:53 +01:00
roberto@natty32 170ee2b98a date was wrong in 0.9.7.1 2011-03-26 09:38:21 +01:00
roberto@natty32 938fb777dd uWSGI 0.9.7.1 2011-03-26 09:36:11 +01:00
roberto@natty32 33e1aafcd1 Added tag 0.9.7.1 for changeset d9b9b540f7dc 2011-03-26 09:35:31 +01:00
roberto@natty32 597ee90041 add sys.abiflags if necessary 2011-03-26 09:27:30 +01:00
roberto@natty32 e87e54ea28 allow --namespace-net and fix python library name 2011-03-26 09:18:52 +01:00
roberto@natty32 5c64c1ac3f fixed post-buffering without pep3333-input 2011-03-25 19:11:53 +01:00
roberto@natty32 c611cbc2ca fixed current_wsgi_req in multithreading without cores 2011-03-23 11:59:05 +01:00
roberto@sirius 9d051f4171 fixed a buf on older OSX versions (i hope) 2011-03-22 19:34:12 +01:00
roberto@sirius 6aee788678 fixed cmsg parsing 2011-03-22 17:21:19 +01:00
roberto@natty32 425a45caa7 updated banner message in debug mode 2011-03-22 17:02:20 +01:00
roberto@natty32 0571601e02 added --map-socket 2011-03-22 14:55:54 +01:00
roberto@natty32 c1992c8c7a added --check-cache 2011-03-22 12:12:03 +01:00
roberto@natty32 bd913870c7 fixed setup.py 2011-03-21 10:36:52 +01:00
roberto@natty32 7a479dd47f add 304/If-Modified-Since support for --check-static <dir> 2011-03-21 10:31:50 +01:00
roberto@natty32 7ae77aa58d added UWSGI_CACHE_GET dynamic variable 2011-03-20 21:24:32 +01:00
roberto@natty32 97a4260d44 added --pidfile2 and --logfile-chown 2011-03-20 08:05:27 +01:00
roberto@mrspurr b90d711764 allow python modules to be on http server 2011-03-20 07:51:56 +01:00
roberto@mrspurr 22de5b523e reintroduce modifier1 30 2011-03-19 17:03:00 +01:00
roberto@mrspurr 5798b824c0 forbid daemonizing in vassal mode 2011-03-19 11:03:16 +01:00
roberto@goyle 4cbf6cfc33 various fixes in touch_reload 2011-03-19 09:33:28 +01:00
roberto@mrspurr 8b55460156 added persistence for queue 2011-03-18 20:20:36 +01:00
roberto@mrspurr a61d48a451 fixed stackless support 2011-03-18 08:14:12 +01:00
roberto@mrspurr b9f4d57d67 applied activestate fix for --root support in setup.py 2011-03-18 07:15:10 +01:00
roberto@natty32 92cd36d14d ready for first stable release 2011-03-17 09:15:52 +01:00
roberto@natty32 f74e61b126 fixed psgi compilation 2011-03-16 21:29:52 +01:00
roberto@natty32 c8b4ba2b5b updated iobound_async example and improved pep3333-input 2011-03-16 20:54:54 +01:00
roberto@natty32 0a15ba1c5b remove stackless support, move it to async plugin 2011-03-16 13:12:50 +01:00
roberto@natty32 7ee5948233 better error reporting on failed open/fopen 2011-03-16 12:14:41 +01:00
roberto@natty32 85c8bcf9d2 removed memory leak in greenlet plugin 2011-03-16 11:12:55 +01:00
roberto@natty32 67394c6664 added greenlet plugin 2011-03-16 11:02:05 +01:00
roberto@silente 66ef7d8229 remove uGreen compilation on unsupported platforms 2010-12-29 23:06:47 +01:00
roberto@solarisexpress 3773bc69f2 fixed ldap solaris support 2011-03-16 09:48:52 +00:00
roberto@natty32 912416b119 fixed openldap support 2011-03-16 09:45:15 +01:00
roberto@solarisexpress 7dfe125013 solaris fixes 2011-03-16 09:39:02 +00:00
roberto@mrspurr 87db34ef0b removed setjmp code 2011-03-16 07:46:11 +01:00
roberto@natty32 d4f75ab53c re-added ugreen support (better and faster) 2011-03-16 07:28:23 +01:00
roberto@natty32 dc97e8fce5 new help system 2011-03-15 12:14:22 +01:00
roberto@natty32 b3965d9d67 updated async support 2011-03-15 10:45:23 +01:00
roberto@natty32 7ee90d1e12 fixed python uwsgi.cache_get 2011-03-12 14:52:11 +01:00
roberto@sirius 9d8b373e4f uWSGI 0.9.7-rc3 2011-03-12 14:21:16 +01:00
roberto@natty32 a068a7eb5b added support for cache backing store 2011-03-12 14:14:43 +01:00
roberto@natty32 aa004c1893 less verbose file monitoring 2011-03-12 09:31:14 +01:00
roberto@natty32 9a9c149370 fixed emperor waitpid and erlang list encoding 2011-03-12 07:35:41 +01:00
roberto@natty32 9e6e226e4b improved snmp agent and fixed cache modifier 4 2011-03-11 11:55:44 +01:00
roberto@mrspurr 06c2aed0e0 add modifier 3 in cache plugin 2011-03-11 10:57:39 +01:00
roberto@natty32 df4f610cfc preliminary cpu-affinity support 2011-03-11 07:37:43 +01:00
roberto@natty32 64249abae1 improved ldap support 2011-03-10 19:14:13 +01:00
roberto@sirius 94f4be58bd auto configure ldap support 2011-03-10 10:40:56 +01:00
roberto@sirius 35987d3741 added --allowed-modifiers 2011-03-10 10:21:08 +01:00
roberto@natty32 be73e00dde merge 2011-03-10 09:56:33 +01:00
roberto@natty32 a5f272f337 fixed a bug in getopt_long 2011-03-10 09:56:04 +01:00
roberto@sirius 406691aa69 uWSGI 0.9.7-rc2 2011-03-09 11:26:27 +01:00
roberto@natty32 6827b3bf15 cron-like interface added to signal framework 2011-03-09 10:33:44 +01:00
roberto@natty32 2055a1472f great fix suggested by Damjan Georgievski for linux namespaces 2011-03-08 14:17:30 +01:00
roberto@natty32 f4f9018068 fixed multithreading + max-requests 2011-03-08 11:45:37 +01:00
roberto@sirius 3e82b5cd33 improved configuration system 2011-03-07 16:06:59 +01:00
roberto@sirius 07036bce20 fix %v usage in emperor 2011-03-07 11:52:44 +01:00
roberto@sirius a4a7a75f29 uWSGI 0.9.7-rc1 2011-03-07 09:42:53 +01:00
316 changed files with 42136 additions and 11492 deletions
+4
View File
@@ -0,0 +1,4 @@
syntax: glob
*.o
*.pyc
+41
View File
@@ -10,3 +10,44 @@ b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
3c70927335856883283fe4db448e092cecc0ccdb 1.0
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
+20
View File
@@ -0,0 +1,20 @@
- this is a incomplete list of all the contributors of the project -
Roberto De Ioris, Unbit, <roberto@unbit.it>
Riccardo Magliocchetti, Unbit, <riccardo@unbit.it>
Yann Malet, Lincoln Loop
Simon Litchfield
Masahiro Honma, <hiratara@cpan.org>
Łukasz Wróblewski <admin@nri.pl>
Giacomo Bagnoli, Asidev
Guido Notari, Link I.T. S.p.a.
Marco Beri, Link I.T. S.p.a.
Leonid Borisenko
Cal Leeming, Simplicity Media Ltd
Luigi Scarso
Corey Farwell
Charles Duffy
Lukas Lalinsky
Steven Fernandez
Łukasz Mierzwa
Roy Marples
+348
View File
@@ -1,5 +1,353 @@
*** april 2012 ***
* 1.2 [20120430]
- PyPy support
- Improved gevent support with threads
- Python auto-reload subsystem
- added --spooler-max-tasks
- pthread robust mutexes support in Linux and Solaris
- posix semaphores support in FreeBSD9
- thread-safe ctime() reporting
- interval support in cron subsystem
- improved syslog support
- better management of disconnected clients
- static files serving improvements
- another set of multithreading optimizations
- minor fixes in the Rack plugin
- Upstart socket-activation support
*** march 2012 ***
* 1.1 [20120317]
- new options parser subsystem
- improved php support
- multiple spooler with multiprocessing
- segmentation fault and floating point exceptions manager
- never-swap option
- zergpool plugin
- perl/psgi multiple interpreters support
- deadlock detector
- pluggable cheaper algos
- new internal routing susbsystem
- preliminary support for config logic
- log rotation infrastructure
- support for paste loggers
- threading improvements
- plugins can now mapped to specific modifiers
- <app> tag is deprecated (use mount option)
- report startup time for apps
- reintroduced expat support
- reintroduced remote spooler plugin
- various fastrouter optimizations
- added ruby rvm support
*** december 2011 ***
* 1.0 [20111230]
- adaptive process spawning (--cheaper option)
- new control options --stop, --reload, --suspend, --resume, --pause
- stats framework
- new subscription system
- support for mime types in static file serving
- posix capablities support
- uWSGI mules and farms
- support for multiple --touch-reload options
- new logging subsystem
- new custom locking subsystem
- process name handling
- better (and faster) HTTP parser
- perl and python threading improvements
- new plugins: rrdtool, carbon, cgi, php
- various improvements in the Rack/ruby plugin
- Linux KSM support
- refactored ping and nagios plugins
- support for signals in lazy mode
- optimized static-file serving
- support for linux unshare()
*** august 2011 ***
* 0.9.9 [20110829]
- various spooler improvements
- upload progress optimizations and fixes
- new emperor mode: Tyrant
- allows multiple --ini options
- better binary path detection
- gevent loop engine support
- resolve domain names in socket logging
- snmp fixes and reintroduction of the snmp-api
- fixed grunt mode
- you can specify build profile via env var UWSGI_PROFILE
- reintroduction of string-based multiapp
- new option --emperor-throttle
- improved queue and sharedarea subsystems
- uWSGI can now be built as a shared library
- new api attribute: uwsgi.magic_table
- improved apache2 module
- new option --pyshell
- allow threads in gateways
- fastrouter improvements
- the application list is now shared and exported to the api
- allows setting the thread stack size
- UWSGI_APPID for better multiapp hosting
- better reloading in lazy mode
- native pump support
- various rack fixes
- support for attaching binary data in the executable
- new option --set
- extreme-optimized http protocol parser
- WSGI handler optimizations
*** july 2011 ***
* 0.9.8.3 [20110723]
- implemented uwsgi.SymZipImporter to load embedded zip files
- OSX Lion is officially supported
- fixed xinetd support (example file added in contrib)
- suppot for systemd socket activation
- added --freebind option (Linux only)
* 0.9.8.2 [20110719]
- fixed an ini and yaml parsing bug spotted by Raffaele Colace
- spooler has been extremely improved
- new option --chown-socket
- added uwsgidecorators for elegant uwsgi api access from python
- the rack plugin is now stable
- support for embedding config and generic files in the server binary
- high-performance cache-server
- accept() is now locked on all threads in the same workers
- preliminary implementation of hooks in emperor
- support for C++ in server core
- tcp port auto-bind
- implemented workers, workerN and spooler signal target
- prefork/multithread uwsgi.signal_wait() implementation
- export uwsgi.node in WSGI vars
- new option --import (python plugin)
- support for unlimited number of Linux cgroups
- broodlord mode
*** june 2011 ***
* 0.9.8.1 [20110625]
- the build system has been improved
- various threading fixes
- fix python GIL status after reload
- new option --propagate-touch
- fixed uwsgi.sendfile
- fixed readline() support in wsgi.input
- fixed dynamic touch reload
- new option --logto2
- export %c in config files
- fixed libyaml support
- support passing modifiers in subscription system
- reset random seed in spooler
- subscribe from a list in a text file
- allow binding on port 0 (auto-assignment)
- reset random seed on grunt
- fix vhost mode for empty hostname
- fixed python3+virtualenv support
- tasks are now allowed to chdir() in spooler
- better zeromq+clustering support
- clustering has been refactored
- fixed rpc
- report correct worker id in cheap mode
- fixed a fd-leak in attach-daemon
- use setsid() in attach-daemon
- zerg mode
- added psgix.harakiri
- allows magic vars in sqlite3 config db
- added UWSGI_FASTROUTER_KEY var
- slowdown async-queue-is-full messages
- new option --cron
- --vassals-start-hook and --vassals-stop-hook
- the proxy plugin has been removed
* 0.9.8 [20110605]
- support for --callable in virtualhosting mode
- a NetBSD fix
- abstract unix socket can be prefixed with \0 (nginx-style)
- add /lib to the linker in sun-like systems
- a mercy mode of 5 seconds is enabled by default on SIGINT/SIGQUIT
* 0.9.8-rc4 [20110602]
- fixed REMOTE_ADDR when --protocol=http
- official support for OpenIndiana
- added a welcome.py test script
- new api attribute uwsgi.version_info
- improved the admin plugin
- two new management flag for backlog queue monitoring
- fixed uwsgi_log for bigger loglines
- new option --early-emperor to allows out-of-jail emperors
- emperor can now spawn other emperors (sub-emperors)
- fixed idle mode in single-process
- fixed solaris iovec
*** may 2011 ***
* 0.9.8-rc3 [20110530]
- snapshotting support
- fixed python 3.x spooler
- improvements for grunt processes
- better abstract unix socket
- --log-socket allows logging to generic DGRAM sockets
- a bunch of solaris fixes
- new option --no-fd-passing for fastrouter
- --fastrouter-subscription-slot to set the number of slot in subscription server
- unlimited shared sockets
- fixed netlink compilation
- auto-reconnect on emperor+amqp server disconnection
- various emperor fixes
- unlimited fastrouter sockets
- better cgroup support
- --add-header option allow adding of custom HTTP response headers
- cheap and idle operational modes
* 0.9.8-rc2 [20110521]
- new option --die-on-term
- fixed touch reload
- a couple of optimizations for wsgi.input
- systemd integration
* 0.9.8-rc1 [20110514]
- massive code cleanup and refactoring
- added vassals loyalty concept
- fixed virtualhosting with dynamic virtualenv
- fixed reloading on grand-central-dispatch-enabled OSX
- improved PSGI support with uGreen and async support
- improved Rack support with complete fiber+async in ruby 1.9
- support for JSON config files
- native multi-protocol support (added fastcgi and http)
- Mongrel2 support
- support for templates in vassals
- various threading fixes
- gcc-4.6 support
- support for logging via zeromq
- support for configuration passed via pipe/stdin
- pythonpath entries are now unlimited
- socket entries are unlimited
- pythonpath can be a glob
- lazy mode added
- new language-independent profiling subsystem
- support for configuration stored in a sqlite3 db
- allow workers to survive to syslogd death (when --log-syslog is used)
- fix traceback in Python 3.x
- support for uwsgi signals in threads
- plugin autoloading
- graceful reloading for threads
- new wsgi.input object
- support for alternative allocators (tcmalloc and jemalloc)
*** april 2011 ***
* 0.9.7.2 [20110406]
- new option --touch-reload <file> to reload the stack on <file> modification
--static-map <mountpoint=documentroot> allows to serve static files
- fixed --post-limit management
- disallow empty socket names
- implemented exception_info WSGI support
- new options --reload-on-as <n> and --reload-on-rss <n> allows
to recycle workers when their memory usage is higher than <n> MB
- fixed syslog support (use --log-syslog[=facility] to enable it)
- improved plugin loading system
- added support for RabbitMQ as event dispatcher for the Emperor
- fixed FreeBSD memory report
- PSGI plugin can be compiled without ithreads
- various Emperor fixes
- fixed a regression with setgroups()
- support for shared sockets (used in jails within network namespaces)
*** march 2011 ***
* 0.9.7.1 [20110326]
- fixed python stackless support
- added persistence for queue
- forbid daemonizing in vassal mode
- modifier1 30 is available again
- allow python modules to be mapped/aliased via http
- added --pidfile2 and --logfile-chown
- added UWSGI_CACHE_GET dynamic variable
- 304/If-Modified-Since support for --check-static
- option --check-cache for integrated caching
- option --map-socket to assign specific workers to socket
- fixed unix fd passing on older OSX versions
- fixed post-buffering without pep3333-input
- fixed python threading without uwsgi cores
- support for Linux network namespace
- build with sys.abiflags if necessary
* 0.9.7 [20110317]
- fixed psgi compilation on GNU systems
- improved --pep3333-input
- better error reporting on failed open/fopen
- fixed uGreen
- added greenlet support
- various solaris fixes
- new help system
- updated async support
- fixed uwsgi.cache_get in python
* 0.9.7-rc3 [20110312]
- added support for persistent cache (--cache-store <filename>)
- less verbose file monitoring
- fixed a race condition in emperor startup
- fixed erlang empty list encoding
- improved snmp support
- fixed cache modifier 111 for 3 and 4
- preliminary cpu-affinity support (Linux only)
- fixed ldap support
- auto-configure ldap compilation
- added --allowed-modifiers (allow only a subset of modifiers)
- fixed a bug with getopt_long
* 0.9.7-rc2 [20110309]
- added cron-like interface to signal framework
- improved Linux namespaces support
- fixed multithreading + --max-requests
- added support for reference in configuration files
* 0.9.7-rc1 [20110307]
- export %v in emperor mode
- fixed signal race condition in server reload
- fixed http router post handling bug
- added uwsgi.erlang_register_process in pyerl plugin
- fixed unix socket inherit
- fixed linux namespace support in recent kernel/gcc
- ported threading to python 3.2
- add build date to uWSGI startup info
- do not allow clustering without defining a socket
- kill all the gateways/daemons on startup errors
- fixed vacuum after chdir()
- fixed gateways reload
- re-added support for OpenBSD and NetBSD
- fixed post-buffering in python
- use erlang binary for python string
- fixed memory leak in pyerl plugin
- removed broken log rotation (post-poned)
- fixed no_argument options in ini and yaml parsing
* 0.9.7-beta1 [20110301]
- fully modular re-design
+3
View File
@@ -1,2 +1,5 @@
all:
python uwsgiconfig.py --build
clean:
python uwsgiconfig.py --clean
-2
View File
@@ -1,2 +0,0 @@
all:
python2.4 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python2.5 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python2.6 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python2.7 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python3.0 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python3.1 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python3.2 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python uwsgiconfig.py --build pylua
+29 -2
View File
@@ -160,20 +160,35 @@ static int uwsgi_map_location(request_rec *r)
return DECLINED;
}
static void log_err(const char *file, int line, request_rec *r,
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
static void log_err(const char *file, int line, int ami, request_rec *r,
apr_status_t status, const char *msg)
{
ap_log_rerror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, status, r, "uwsgi: %s", msg);
#else
static void log_err(const char *file, int line, request_rec *r,
apr_status_t status, const char *msg)
{
ap_log_rerror(file, line, APLOG_ERR, status, r, "uwsgi: %s", msg);
#endif
}
static void log_debug(const char *file, int line, request_rec *r, const
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
static void log_debug(const char *file, int line, int ami, request_rec *r, const
char *msg)
{
/*
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, msg);
ap_log_rerror(file, line, APLOG_WARNING, APR_SUCCESS, r, "uwsgi: %s", msg);
*/
ap_log_rerror(file, line, APLOG_MODULE_INDEX, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
#else
static void log_debug(const char *file, int line, request_rec *r, const
char *msg) {
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
#endif
}
/* buffered socket implementation (buckets are overkill) */
@@ -412,7 +427,11 @@ send_headers(request_rec *r, struct sockbuff *s)
apr_table_t *t;
apr_status_t rv = 0;
apr_port_t port = 0;
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
GET_PORT(port, r->useragent_addr);
#else
GET_PORT(port, r->connection->remote_addr);
#endif
uwsgi_cfg *cfg = our_dconfig(r);
log_debug(APLOG_MARK,r, "sending headers");
@@ -430,7 +449,11 @@ send_headers(request_rec *r, struct sockbuff *s)
add_header(t, "REQUEST_METHOD", (char *) r->method);
add_header(t, "QUERY_STRING", r->args ? r->args : "");
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
add_header(t, "SERVER_SOFTWARE", ap_get_server_description());
#else
add_header(t, "SERVER_SOFTWARE", ap_get_server_version());
#endif
add_header(t, "SERVER_ADMIN", r->server->server_admin);
add_header(t, "SERVER_NAME", (char *) ap_get_server_name(r));
add_header(t, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)));
@@ -438,7 +461,11 @@ send_headers(request_rec *r, struct sockbuff *s)
add_header(t, "SERVER_PROTOCOL", r->protocol);
add_header(t, "REQUEST_URI", original_uri(r));
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
add_header(t, "REMOTE_ADDR", r->useragent_ip);
#else
add_header(t, "REMOTE_ADDR", r->connection->remote_ip);
#endif
add_header(t, "REMOTE_PORT", apr_psprintf(r->pool, "%d", port));
add_header(t, "REMOTE_USER", r->user);
add_header(t, "DOCUMENT_ROOT", (char *) ap_document_root(r));
+124 -54
View File
@@ -2,7 +2,7 @@
*** uWSGI/mod_uwsgi ***
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
Copyright 2009-2012 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -37,11 +37,18 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
*/
#include <unistd.h>
#include <ctype.h>
#include "apr_strings.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "httpd.h"
#include "http_core.h"
#include "http_protocol.h"
#include "http_config.h"
#include "http_log.h"
#include "util_script.h"
#include <sys/socket.h>
#include <sys/un.h>
@@ -51,7 +58,6 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
#include <fcntl.h>
#define MAX_VARS 64
#define DEFAULT_SOCK "/tmp/uwsgi.sock"
typedef struct {
@@ -73,6 +79,8 @@ typedef struct {
char script_name[256];
char scheme[9];
int cgi_mode ;
int max_vars;
int empty_remote_user;
} uwsgi_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
@@ -83,8 +91,18 @@ static uint16_t uwsgi_swap16(uint16_t x) {
}
#endif
static int uwsgi_add_var(struct iovec *vec, int i, char *key, char *value, uint16_t *pkt_size) {
static int uwsgi_add_var(struct iovec *vec, int i, request_rec *r, char *key, char *value, uint16_t *pkt_size) {
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
#if APR_IS_BIGENDIAN
if (i+6 > c->max_vars) {
#else
if (i+4 > c->max_vars) {
#endif
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: max number of uwsgi variables reached. consider increasing it with uWSGImaxVars directive");
return i;
}
#if APR_IS_BIGENDIAN
char *ptr;
@@ -150,6 +168,9 @@ static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
c->modifier1 = 0 ;
c->modifier2 = 0 ;
c->cgi_mode = 0 ;
c->max_vars = 128;
c->script_name[0] = 0;
c->empty_remote_user = 1;
return c;
}
@@ -164,6 +185,14 @@ static void *uwsgi_dir_config(apr_pool_t *p, char *dir) {
c->modifier1 = 0 ;
c->modifier2 = 0 ;
c->cgi_mode = 0 ;
c->max_vars = 128;
c->empty_remote_user = 1;
c->script_name[0] = 0;
if (dir) {
if (strcmp(dir, "/")) {
strncpy(c->script_name, dir, 255);
}
}
return c;
}
@@ -243,11 +272,8 @@ static int uwsgi_handler(request_rec *r) {
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
#if APR_IS_BIGENDIAN
struct iovec uwsgi_vars[(MAX_VARS*6)+1] ;
#else
struct iovec uwsgi_vars[(MAX_VARS*4)+1] ;
#endif
struct iovec *uwsgi_vars;
int vecptr = 1 ;
char pkt_header[4];
uint16_t pkt_size = 0;
@@ -315,68 +341,62 @@ static int uwsgi_handler(request_rec *r) {
}
#if APR_IS_BIGENDIAN
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*6)+1);
#else
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*4)+1);
#endif
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->useragent_ip, &pkt_size) ;
#else
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
#endif
//
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user, &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
else if (c->empty_remote_user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", "", &pkt_size) ;
}
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
if (c->scheme[0] != 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
}
if (c->script_name[0] == '/') {
if (c->script_name[1] == 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", c->script_name, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
}
// SCRIPT_NAME = "/" is like SCRIPT_NAME = ""
if (c->script_name[0] != 0 && !(c->script_name[0] == '/' && c->script_name[1] == 0)) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", c->script_name, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
}
else {
if (r->path_info) {
if (strlen(r->path_info) <= 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri, (strlen(r->uri) - strlen(r->path_info) )) , &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->path_info, &pkt_size) ;
}
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri, &pkt_size) ;
}
headers = apr_table_elts(r->headers_in);
h = (apr_table_entry_t *) headers->elts;
// check for max vars (a bit ugly)
cnt = headers->nelts ;
if (cnt + 11 > MAX_VARS) {
cnt = MAX_VARS -11;
}
for(i=0;i< cnt;i++) {
for(i=0;i< headers->nelts;i++) {
if (h[i].key){
if (!strcasecmp(h[i].key, "Content-Type")) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_TYPE", h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_TYPE", h[i].val, &pkt_size) ;
}
else if (!strcasecmp(h[i].key, "Content-Length")) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
}
else {
penv = apr_pstrcat(r->pool, "HTTP_", h[i].key, NULL);
@@ -388,7 +408,7 @@ static int uwsgi_handler(request_rec *r) {
*cp = toupper(*cp);
}
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, penv, h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, penv, h[i].val, &pkt_size) ;
}
}
}
@@ -397,7 +417,7 @@ static int uwsgi_handler(request_rec *r) {
headers = apr_table_elts(r->subprocess_env);
h = (apr_table_entry_t*) headers->elts;
for (i = 0; i < headers->nelts; ++i) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, h[i].key, h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, h[i].key, h[i].val, &pkt_size) ;
}
@@ -418,11 +438,13 @@ static int uwsgi_handler(request_rec *r) {
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() %s", strerror(errno));
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt != pkt_size+4) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() returned wrong size");
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -434,6 +456,7 @@ static int uwsgi_handler(request_rec *r) {
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: read() client block failed !");
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -458,6 +481,7 @@ static int uwsgi_handler(request_rec *r) {
if (cnt == 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
@@ -467,6 +491,7 @@ static int uwsgi_handler(request_rec *r) {
if (errno != ECONNRESET) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else {
@@ -489,6 +514,7 @@ static int uwsgi_handler(request_rec *r) {
if (r->connection->aborted) {
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
@@ -508,6 +534,7 @@ static int uwsgi_handler(request_rec *r) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -521,6 +548,7 @@ static int uwsgi_handler(request_rec *r) {
if (!c->cgi_mode) {
if (uwsgi_http_status_read == 0) {
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -528,11 +556,13 @@ static int uwsgi_handler(request_rec *r) {
if (hret = ap_scan_script_header_err_brigade(r, bb, NULL)) {
apr_brigade_destroy(bb);
free(uwsgi_vars);
return hret;
}
}
free(uwsgi_vars);
return ap_pass_brigade(r->output_filters, bb) ;
}
@@ -564,6 +594,22 @@ static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const
}
static const char *cmd_uwsgi_max_vars(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
int val ;
if (cfg) {
c = cfg ;
}
else {
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
c->max_vars = atoi(value);
return NULL;
}
static const char * cmd_uwsgi_modifier1(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
@@ -598,7 +644,7 @@ static const char * cmd_uwsgi_force_cgi_mode(cmd_parms *cmd, void *cfg, const ch
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value)) {
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
c->cgi_mode = 1 ;
}
@@ -699,6 +745,28 @@ static const char * cmd_uwsgi_socket(cmd_parms *cmd, void *cfg, const char *path
return NULL ;
}
static const char * cmd_uwsgi_empty_remote_user(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
if (cfg) {
c = cfg ;
}
else {
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
c->empty_remote_user = 1;
}
else {
c->empty_remote_user = 0;
}
return NULL ;
}
static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE12("uWSGIsocket", cmd_uwsgi_socket, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path and optional timeout in seconds of uwsgi server socket"),
AP_INIT_TAKE1("uWSGIsocket2", cmd_uwsgi_socket2, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path of failover uwsgi server socket"),
@@ -707,6 +775,8 @@ static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
AP_INIT_TAKE1("uWSGIemptyRemoteUser", cmd_uwsgi_empty_remote_user, NULL, ACCESS_CONF, "Always include REMOTE_USER in the environment, even with an empty value (default true)"),
AP_INIT_TAKE1("uWSGImaxVars", cmd_uwsgi_max_vars, NULL, ACCESS_CONF, "Set the maximum allowed number of uwsgi variables (default 128)"),
{NULL}
};
+393 -156
View File
@@ -2,198 +2,435 @@
extern struct uwsgi_server uwsgi;
int async_get_timeout() {
struct wsgi_request* wsgi_req ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
// do not wait if there are cores running
if (!uwsgi.async_running) return 0;
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_timeout_expired) {
// do not wait if there are timeout expired
return 0;
}
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
}
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return -1;
struct wsgi_request *find_wsgi_req_proto_by_fd(int fd) {
return uwsgi.async_proto_fd_table[fd];
}
void async_expire_timeouts() {
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
return uwsgi.async_waiting_fd_table[fd];
}
struct wsgi_request* wsgi_req ;
int i ;
time_t deadline = time(NULL);
void runqueue_remove(struct uwsgi_async_request *u_request) {
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[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 ;
if (wsgi_req->async_waiting_fd != -1) {
event_queue_del_fd(uwsgi.async_queue, wsgi_req->async_waiting_fd);
uwsgi.async_waiting_fd_table[wsgi_req->async_waiting_fd] = -1;
wsgi_req->async_waiting_fd = -1;
wsgi_req->async_waiting_fd_monitored = 0;
}
}
}
struct uwsgi_async_request *parent = u_request->prev;
struct uwsgi_async_request *child = u_request->next;
if (parent) {
parent->next = child;
}
if (child) {
child->prev = parent;
}
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
if (u_request == uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last = parent;
}
free(u_request);
uwsgi.async_runqueue_cnt--;
}
void runqueue_push(struct wsgi_request *wsgi_req) {
struct uwsgi_async_request *uar;
if (uwsgi.async_runqueue == NULL) {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
uwsgi.async_runqueue_cnt++;
}
struct wsgi_request *find_first_available_wsgi_req() {
struct wsgi_request* wsgi_req;
int i ;
struct wsgi_request *wsgi_req;
// optimization
if (uwsgi.async_current_max > 1) {
if (uwsgi.wsgi_requests[uwsgi.async_current_max-1]->async_status == UWSGI_OK) {
//uwsgi_log("decreasing current max cores\n");
uwsgi.async_current_max--;
}
if (uwsgi.async_queue_unused_ptr < 0) {
return NULL;
}
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i] ;
if (wsgi_req->async_status == UWSGI_OK) {
// optimization
if (i > uwsgi.async_current_max-1) uwsgi.async_current_max = i+1;
wsgi_req->async_id = i;
return wsgi_req ;
wsgi_req = uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr];
uwsgi.async_queue_unused_ptr--;
return wsgi_req;
}
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
time_t current_time = time(NULL);
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for(;;) {
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (urbt == NULL) return;
if (urbt->key <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
uaf = wsgi_req->waiting_fds;
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
while(uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
current_uaf = uaf;
uaf = current_uaf->next;
free(current_uaf);
}
wsgi_req->waiting_fds = NULL;
// put th request in the runqueue
runqueue_push(wsgi_req);
continue;
}
break;
}
return NULL ;
}
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct wsgi_request* wsgi_req = NULL ;
int core_id = uwsgi.async_waiting_fd_table[fd];
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (core_id == -1) return NULL;
if (fd < 0) return ;
wsgi_req = uwsgi.wsgi_requests[core_id];
//if (wsgi_req->async_waiting_fd_type == etype) return wsgi_req ;
return wsgi_req;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
return NULL ;
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_read();
uad->prev = last_uad;
uad->next = NULL;
}
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
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 ;
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_read(uwsgi.async_queue, fd);
}
void async_write_all(char *data, size_t len) {
struct wsgi_request *wsgi_req;
int i;
ssize_t rlen ;
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
uwsgi_error("write()");
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, time(NULL)+timeout, wsgi_req);
}
}
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0) return ;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_write();
uad->prev = last_uad;
uad->next = NULL;
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_write(uwsgi.async_queue, fd);
}
void async_schedule_to_req(void) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
}
void *async_loop(void *arg1) {
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
struct uwsgi_rb_timer *min_timeout;
int timeout;
int is_a_new_connection;
int proto_parser_status;
time_t now, last_now = 0;
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
void *events = event_queue_alloc(64);
struct uwsgi_socket *uwsgi_sock;
uwsgi.async_runqueue = NULL;
uwsgi.async_runqueue_cnt = 0;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
}
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
else {
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
if (min_timeout) {
timeout = min_timeout->key - time(NULL);
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
}
}
else {
wsgi_req->response_size += rlen ;
timeout = -1;
}
}
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
// timeout ???
if (uwsgi.async_nevents == 0) {
async_expire_timeouts();
}
for(i=0;i<uwsgi.async_nevents;i++) {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
is_a_new_connection = 0;
// new request coming in ?
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (interesting_fd == uwsgi_sock->fd) {
is_a_new_connection = 1;
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
now = time(NULL);
if (now > last_now) {
uwsgi_log("async queue is full !!!\n");
last_now = now;
}
break;;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi_sock->arg) < 0) {
uwsgi_error("fcntl()");
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
}
#endif
if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
runqueue_push(uwsgi.wsgi_req);
}
break;
}
uwsgi_sock = uwsgi_sock->next;
}
if (!is_a_new_connection) {
// proto event
uwsgi.wsgi_req = find_wsgi_req_proto_by_fd(interesting_fd);
if (uwsgi.wsgi_req) {
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
// reset timeout
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
// parsing complete
if (!proto_parser_status) {
// remove fd from event poll and fd proto table
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
#endif
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
continue;
}
else if (proto_parser_status == -1) {
uwsgi_log("error parsing request\n");
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
close(interesting_fd);
continue;
}
// re-add timer
async_add_timeout(uwsgi.wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
continue;
}
// app event
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
// unknown fd, remove it (for safety)
if (uwsgi.wsgi_req == NULL) {
close(interesting_fd);
continue;
}
// remove all the fd monitors and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
uwsgi.wsgi_req->async_ready_fd = 1;
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
}
}
}
}
void async_unpause_all() {
struct wsgi_request *wsgi_req ;
int i;
// event queue managed, give cpu to runqueue
if (!current_request)
current_request = uwsgi.async_runqueue;
if (uwsgi.async_runqueue_cnt) {
uwsgi.wsgi_req = current_request->wsgi_req;
uwsgi.schedule_to_req();
uwsgi.wsgi_req->switches++;
next_async_request = current_request->next;
// request ended ?
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
// remove all the monitored fds and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
// remove from the list
runqueue_remove(current_request);
uwsgi_close_request(uwsgi.wsgi_req);
// push wsgi_request in the unused stack
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from suspended list
runqueue_remove(current_request);
}
current_request = next_async_request;
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
}
}
}
struct wsgi_request * async_loop() {
struct wsgi_request *wsgi_req ;
int i ;
int ret;
uwsgi.async_running = -1 ;
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->sigwait) {
uwsgi_log("waiting for signal\n");
continue;
}
else if (wsgi_req->async_waiting_fd != -1 && !wsgi_req->async_waiting_fd_monitored) {
// add fd to monitoring
ret = -1;
if (wsgi_req->async_waiting_fd_type == ASYNC_IN) {
ret = event_queue_add_fd_read(uwsgi.async_queue, wsgi_req->async_waiting_fd);
}
else if (wsgi_req->async_waiting_fd_type == ASYNC_OUT) {
ret = event_queue_add_fd_write(uwsgi.async_queue, wsgi_req->async_waiting_fd);
}
if (ret < 0) {
// 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;
}
uwsgi.async_waiting_fd_table[wsgi_req->async_waiting_fd] = wsgi_req->async_id;
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
uwsgi.wsgi_req = wsgi_req ;
uwsgi_log("!!! getting new part\n");
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);;
wsgi_req->switches++;
if (wsgi_req->async_status < UWSGI_AGAIN) {
return wsgi_req;
}
}
}
}
return NULL;
+13
View File
@@ -0,0 +1,13 @@
import struct
import sys
import os
filename = sys.argv[1]
size = os.path.getsize(filename)
f = open(filename, 'r')
print(f.read())
f.close()
print(struct.pack("<Q", size))
+5
View File
@@ -0,0 +1,5 @@
import sys
import uwsgi
print("i am the bootstrap for uwsgi.SymbolsImporter")
sys.meta_path.insert(0, uwsgi.SymbolsImporter())
+4
View File
@@ -0,0 +1,4 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("pygments_zip"))
+5
View File
@@ -0,0 +1,5 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("django_zip:djenv/lib/python2.6/site-packages"))
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("djapp_zip"))
+4
View File
@@ -0,0 +1,4 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.ZipImporter("data://0"))
+3
View File
@@ -0,0 +1,3 @@
import uwsgi
print uwsgi.extract("data://0")
+1
View File
@@ -0,0 +1 @@
object file for embedded files will be put here
+19 -5
View File
@@ -1,7 +1,10 @@
[uwsgi]
xml = true
xml = auto
ini = true
yaml = true
json = auto
sqlite3 = auto
zeromq = auto
snmp = true
sctp = false
spooler = true
@@ -12,23 +15,34 @@ threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = false
ldap = auto
pcre = auto
stackless = false
routing = auto
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = python, ping, nagios, rpc, fastrouter, http
embedded_plugins = python, ping, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
[python]
paste = true
web3 = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embed_files = bootstrap3.py,django.zip,djapp.zip
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = default
embed_files = embedme.py,uwsgidecorators.py
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, gevent
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = null
as_shared_library = true
+4 -32
View File
@@ -1,33 +1,5 @@
[uwsgi]
xml = true
ini = true
snmp = true
sctp = false
erlang = false
spooler = false
embedded = false
udp = true
multicast = false
threading = true
sendfile = true
nagios = true
proxy = true
minterpreters = true
async = true
ugreen = false
http = true
evdis = false
ldap = true
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins = python, ping, rack
bin_name = uwsgi
plugin_dir = .
embedded_plugins =
[python]
paste = true
web3 = true
inherit = default
plugins = python, ping, rack, psgi, cache, http, fastrouter
plugin_dir = plugins
embedded_plugins = null
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = default
plugin_dir = /usr/lib/uwsgi
embedded_plugins = null
-4
View File
@@ -1,7 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,lua
[python]
paste = true
web3 = true
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = symcall
as_shared_library = true
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = pyuwsgi.so
embedded_plugins = pyuwsgi,python,ping,cache,nagios,rpc,ugreen
as_shared_library = true
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = rack, ping, nagios, rpc
embedded_plugins = rack, ping, cache, nagios, rpc, fastrouter, http, ugreen
+14 -2
View File
@@ -2,6 +2,9 @@
xml = true
ini = true
yaml = true
json = false
sqlite3 = false
zeromq = false
snmp = false
sctp = false
spooler = true
@@ -10,14 +13,23 @@ udp = true
multicast = false
threading = true
sendfile = true
nagios = false
minterpreters = true
async = true
ldap = true
pcre = true
routing = true
debug = false
unbit = true
xml_implementation = libxml2
xml_implementation = expat
yaml_implementation = auto
malloc_implementation = libc
plugins =
bin_name = /opt/unbit/bin/uwsgi
append_version = unbit
plugin_dir = /opt/unbit/uwsgi_plugins
embedded_plugins =
locking = auto
event = auto
timer = auto
filemonitor = auto
+2
View File
@@ -1,4 +1,6 @@
[uwsgi]
inherit = unbit
json = false
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
+49
View File
@@ -0,0 +1,49 @@
[uwsgi]
xml = false
ini = true
yaml = false
json = false
sqlite3 = false
zeromq = false
snmp = false
sctp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = false
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins =
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
[python]
paste = true
web3 = true
+234 -357
View File
@@ -2,145 +2,91 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_subscriber_name *uwsgi_get_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint64_t ovl;
struct uwsgi_subscriber *usub;
struct uwsgi_subscriber_name *ret = NULL;
usub = (struct uwsgi_subscriber *) uwsgi_dict_get(udict, key, keylen, &ovl);
if (usub == NULL || !ovl) return NULL;
if (!usub->nodes) return NULL;
if (usub && ovl) {
ret = &usub->names[usub->current];
// dead node
if (ret->len == 0) {
if (usub->current == usub->nodes-1) {
usub->nodes--;
}
// retry with another node (if available)
if (usub->nodes > 0) {
usub->current++;
if (usub->current >= usub->nodes) usub->current = 0;
return uwsgi_get_subscriber(udict, key, keylen);
}
}
if (usub->nodes > 1) {
usub->current++;
if (usub->current >= usub->nodes) usub->current = 0;
}
}
return ret;
}
void uwsgi_add_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *address, uint64_t address_len) {
char *ptr;
uint64_t vallen = 0;
struct uwsgi_subscriber *usub, nusub;
int found = 0;
int i;
ptr = uwsgi_dict_get(udict, key, keylen, &vallen);
if (ptr && vallen) {
usub = (struct uwsgi_subscriber *) ptr;
for(i=0;i<(int)usub->nodes;i++) {
if (!uwsgi_strncmp(usub->names[i].name, usub->names[i].len, address, address_len)) {
found = 1;
break;
}
}
if (!found) {
found = usub->nodes;
// check for unallocated slot
for(i=0;i<(int)usub->nodes;i++) {
if (usub->names[i].len == 0) {
found = i;
break;
}
}
usub->names[found].len = address_len;
memcpy(usub->names[found].name, address, address_len);
if (found == (int) usub->nodes) {
usub->nodes++;
}
}
return;
}
else {
nusub.nodes = 1;
nusub.current = 0;
memcpy(nusub.names[0].name, address, address_len);
uwsgi_dict_set(udict, key, keylen, (char *) &nusub, sizeof(struct uwsgi_subscriber));
}
}
struct uwsgi_dict *uwsgi_dict_create(uint64_t items, uint64_t blocksize) {
void uwsgi_init_cache() {
int i;
struct uwsgi_dict *udict = (struct uwsgi_dict *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict) {
uwsgi_error("mmap()");
exit(1);
}
if (!uwsgi.cache_blocksize)
uwsgi.cache_blocksize = UMAX16;
if (!blocksize) blocksize = 4096;
uwsgi.cache_hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache_hashtable) {
uwsgi_error("mmap()");
exit(1);
}
if (blocksize % uwsgi.page_size != 0) {
uwsgi_log("invalid shared dictionary blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) udict->blocksize, uwsgi.page_size);
exit(1);
}
memset(uwsgi.cache_hashtable, 0, sizeof(uint64_t) * UMAX16);
udict->blocksize = blocksize;
udict->max_items = items;
uwsgi.cache_unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache_unused_stack) {
uwsgi_error("mmap()");
exit(1);
}
udict->hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->hashtable) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.cache_unused_stack, 0, sizeof(uint64_t) * uwsgi.cache_max_items);
memset(udict->hashtable, 0, sizeof(uint64_t) * UMAX16);
// the first cache item is always zero
uwsgi.shared->cache_first_available_item = 1;
uwsgi.shared->cache_unused_stack_ptr = 0;
udict->unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->unused_stack) {
uwsgi_error("mmap()");
exit(1);
}
//uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (uwsgi.cache_store) {
uwsgi.cache_filesize = (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items);
int cache_fd;
struct stat cst;
memset(udict->unused_stack, 0, sizeof(uint64_t) * udict->max_items);
if (stat(uwsgi.cache_store, &cst)) {
uwsgi_log("creating a new cache store file: %s\n", uwsgi.cache_store);
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (cache_fd >= 0) {
// fill the caching store
if (ftruncate(cache_fd, uwsgi.cache_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
if ((size_t) cst.st_size != uwsgi.cache_filesize || !S_ISREG(cst.st_mode)) {
uwsgi_log("invalid cache store file. Please remove it or fix cache blocksize/items to match its size\n");
exit(1);
}
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
uwsgi_log("recovered cache from backing store file: %s\n", uwsgi.cache_store);
}
udict->items = (struct uwsgi_dict_item *) mmap(NULL, sizeof(struct uwsgi_dict_item) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->items) {
uwsgi_error("mmap()");
exit(1);
}
if (cache_fd < 0) {
uwsgi_error_open(uwsgi.cache_store);
exit(1);
}
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, uwsgi.cache_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
uwsgi_cache_fix();
udict->data = mmap(NULL, udict->blocksize * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->data) {
uwsgi_error("mmap()");
exit(1);
}
}
else {
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
}
}
if (!uwsgi.cache_items) {
uwsgi_error("mmap()");
exit(1);
}
for(i=0;i< (int) udict->max_items;i++) {
memset(&udict->items[i], 0, sizeof(struct uwsgi_dict_item));
}
/*
uwsgi.cache = mmap(NULL, uwsgi.cache_blocksize * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache) {
uwsgi_error("mmap()");
exit(1);
}
*/
udict->first_available_item = 1;
udict->unused_stack_ptr = 0;
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
udict->lock = uwsgi_mmap_shared_lock();
uwsgi_lock_init(udict->lock);
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
return udict;
uwsgi_log("*** Cache subsystem initialized: %dMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n", ((uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024),
(unsigned long long) sizeof(struct uwsgi_cache_item), (unsigned long long) sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, (unsigned long long) uwsgi.cache_blocksize * uwsgi.cache_max_items);
}
uint32_t djb33x_hash(char *key, int keylen) {
@@ -156,89 +102,6 @@ uint32_t djb33x_hash(char *key, int keylen) {
}
inline uint64_t uwsgi_dict_get_index(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
uint64_t slot = udict->hashtable[hash_key];
struct uwsgi_dict_item *udi;
udi = &udict->items[slot];
// first round
if (udi->djbhash != hash) goto cycle;
if (udi->keysize != keylen) goto cycle;
if (memcmp(udi->key, key, keylen)) goto cycle;
return slot;
cycle:
while(udi->next) {
slot = udi->next;
udi = &udict->items[slot];
if (udi->djbhash != hash) continue;
if (udi->keysize != keylen) continue;
if (!memcmp(udi->key, key, keylen)) return slot;
}
return 0;
}
char *uwsgi_dict_get(struct uwsgi_dict *udict, char *key, uint16_t keylen, uint64_t *valsize) {
uint64_t index = uwsgi_dict_get_index(udict, key, keylen);
if (index) {
*valsize = udict->items[index].valsize;
udict->items[index].hits++;
return udict->data+(index*udict->blocksize);
}
return NULL;
}
int uwsgi_dict_del(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint64_t index = 0;
struct uwsgi_dict_item *udi;
int ret = -1;
index = uwsgi_dict_get_index(udict, key, keylen);
if (index) {
udi = &udict->items[index] ;
udi->keysize = 0;
udi->valsize = 0;
udict->unused_stack_ptr++;
udict->unused_stack[udict->unused_stack_ptr] = index;
// try to return to initial condition...
if (index == udict->first_available_item-1) {
udict->first_available_item--;
}
ret = 0;
// relink collisioned entry
if (udi->prev) {
udict->items[udi->prev].next = udi->next;
}
if (udi->next) {
udict->items[udi->next].prev = udi->prev;
}
if (!udi->prev && !udi->next) {
// reset hashtable entry
udict->hashtable[udi->djbhash % 0xffff] = 0;
}
udi->djbhash = 0;
udi->prev = 0;
udi->next = 0;
}
return ret;
}
inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
@@ -248,13 +111,14 @@ inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint64_t slot = uwsgi.cache_hashtable[hash_key];
struct uwsgi_cache_item *uci;
uint64_t rounds = 0;
//uwsgi_log("found slot %d for key %d\n", slot, hash_key);
uci = &uwsgi.cache_items[slot];
// first round
if (uci->djbhash != hash) goto cycle;
if (uci->djbhash != hash) return 0;
if (uci->keysize != keylen) goto cycle;
if (memcmp(uci->key, key, keylen)) goto cycle;
@@ -264,7 +128,20 @@ cycle:
while(uci->next) {
slot = uci->next;
uci = &uwsgi.cache_items[slot];
if (uci->djbhash != hash) continue;
rounds++;
if (rounds > uwsgi.cache_max_items) {
uwsgi_log("ALARM !!! cache-loop (and potential deadlock) detected slot = %llu prev = %llu next = %llu\n", uci->next, slot, uci->prev, uci->next);
// terrible case: the whole uWSGI stack can deadlock, leaving only the master alive
// if the master is avalable, trigger a brutal reload
if (uwsgi.master_process) {
kill(uwsgi.workers[0].pid, SIGTERM);
}
// otherwise kill the current worker (could be pretty useless...)
else {
exit(1);
}
}
if (uci->djbhash != hash) return 0;
if (uci->keysize != keylen) continue;
if (!memcmp(uci->key, key, keylen)) return slot;
}
@@ -291,13 +168,14 @@ char *uwsgi_cache_get(char *key, uint16_t keylen, uint64_t *valsize) {
return NULL;
}
int uwsgi_cache_del(char *key, uint16_t keylen) {
int uwsgi_cache_del(char *key, uint16_t keylen, uint64_t index) {
uint64_t index = 0;
struct uwsgi_cache_item *uci;
int ret = -1;
index = uwsgi_cache_get_index(key, keylen);
if (!index)
index = uwsgi_cache_get_index(key, keylen);
if (index) {
uci = &uwsgi.cache_items[index] ;
uci->keysize = 0;
@@ -314,9 +192,15 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
if (uci->prev) {
uwsgi.cache_items[uci->prev].next = uci->next;
}
else {
// set next as the new entry point (could be 0)
uwsgi.cache_hashtable[uci->djbhash % 0xffff] = uci->next;
}
if (uci->next) {
uwsgi.cache_items[uci->next].prev = uci->prev;
}
if (!uci->prev && !uci->next) {
// reset hashtable entry
//uwsgi_log("!!! resetted hashtable entry !!!\n");
@@ -325,11 +209,33 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
uci->djbhash = 0;
uci->prev = 0;
uci->next = 0;
uci->expires = 0;
}
return ret;
}
void uwsgi_cache_fix() {
uint64_t i;
for(i=0;i< uwsgi.cache_max_items;i++) {
// valid record ?
if (uwsgi.cache_items[i].keysize) {
if (!uwsgi.cache_items[i].prev) {
// put value in hash_table
uwsgi.cache_hashtable[ uwsgi.cache_items[i].djbhash % 0xffff] = i;
}
}
else {
// put this record in unused stack
uwsgi.shared->cache_first_available_item = i;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = i;
}
}
}
int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint16_t flags) {
uint64_t index = 0, last_index = 0 ;
@@ -378,6 +284,9 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
ret = 0;
// now put the value in the 16bit hashtable
slot = uci->djbhash % 0xffff;
// reset values
uci->prev = 0;
uci->next = 0;
if (uwsgi.cache_hashtable[slot] == 0) {
uwsgi.cache_hashtable[slot] = index;
@@ -395,172 +304,140 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
uci->prev = last_index;
}
}
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = &uwsgi.cache_items[index] ;
if (expires) {
expires += time(NULL);
uci->expires = expires;
}
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
uci->valsize = vallen;
ret = 0;
}
end:
return ret;
}
int uwsgi_dict_set(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *val, uint64_t vallen) {
/* THIS PART IS HEAVILY OPTIMIZED: PERFORMANCE NOT ELEGANCE !!! */
uint64_t index = 0, last_index = 0 ;
void *cache_thread_loop(void *fd_ptr) {
struct uwsgi_dict_item *udi, *udii;
int *fd_tmp = (int *) fd_ptr;
int fd = *fd_tmp;
int i;
ssize_t len;
char uwsgi_packet[UMAX16+4];
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi_packet;
char *val;
uint64_t vallen;
char *key;
uint16_t keylen;
struct pollfd ctl_poll;
char *watermark;
struct sockaddr_un ctl_sun;
socklen_t ctl_sun_len;
int ret = -1;
int slot;
ctl_poll.events = POLLIN;
if (!keylen || !vallen) return -1;
for(;;) {
ctl_sun_len = sizeof(struct sockaddr_un);
pthread_mutex_lock(&uwsgi.cache_server_lock);
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
ctl_poll.fd = accept(fd, (struct sockaddr *) &ctl_sun, &ctl_sun_len);
if (udict->first_available_item >= udict->max_items && !udict->unused_stack_ptr) {
uwsgi_log("*** DANGER dictionary %p is FULL !!! ***\n", udict);
goto end;
}
pthread_mutex_unlock(&uwsgi.cache_server_lock);
index = uwsgi_dict_get_index(udict, key, keylen);
if (!index) {
if (udict->unused_stack_ptr) {
index = udict->unused_stack[udict->unused_stack_ptr];
udict->unused_stack_ptr--;
}
else {
index = udict->first_available_item;
if (udict->first_available_item < udict->max_items) {
udict->first_available_item++;
}
}
udi = &udict->items[index] ;
udi->djbhash = djb33x_hash(key, keylen);
udi->hits = 0;
memcpy(udi->key, key, keylen);
memcpy(udict->data+(index*udict->blocksize), val, vallen);
// set this as late as possibile (to reduce races risk)
udi->valsize = vallen;
udi->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
slot = udi->djbhash % 0xffff;
if (udict->hashtable[slot] == 0) {
udict->hashtable[slot] = index;
}
else {
// append to first available next
last_index = udict->hashtable[slot];
udii = &udict->items[ last_index ];
while(udii->next) {
last_index = udii->next;
udii = &udict->items[ last_index ];
}
udii->next = index;
udi->prev = last_index;
}
}
end:
return ret;
}
void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) data;
uint64_t tmp_vallen = 0;
if (vallen > 0) {
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && tmp_vallen > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, val, vallen);
}
}
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && vallen > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen);
if (ctl_poll.fd < 0) {
uwsgi_error("cache accept()");
continue;
}
i = 0;
while(i < 4) {
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (len <= 0) {
uwsgi_error("cache poll()");
goto clear;
}
else {
wsgi_req->response_size = write(wsgi_req->poll.fd, "HTTP/1.0 404 Not Found\r\n\r\n<h1>Not Found</h1>", 44);
len = read(ctl_poll.fd, uwsgi_packet+i, 4-i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i+=len;
}
if (uh->pktsize == 0) goto clear;
while(i < 4+uh->pktsize) {
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (len <= 0) {
uwsgi_error("cache poll()");
goto clear;
}
len = read(ctl_poll.fd, uwsgi_packet+i, (4+uh->pktsize)-i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i+=len;
}
watermark = uwsgi_packet+4+uh->pktsize;
// get first parameter
memcpy(&keylen, uwsgi_packet+4, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
#endif
if (uwsgi_packet+6+keylen > watermark) goto clear;
key = uwsgi_packet+6+keylen+2;
memcpy(&keylen, key-2, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
#endif
if (key+keylen > watermark) goto clear;
val = uwsgi_cache_get(key, keylen, &vallen);
if (val && vallen > 0) {
if (write(ctl_poll.fd, val, vallen) < 0) {
uwsgi_error("cache write()");
}
}
}
}
int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uint64_t vallen = 0;
char *value;
char *argv[3];
uint8_t argc = 0;
switch(wsgi_req->uh.modifier2) {
case 0:
// get
if (wsgi_req->uh.pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh.pktsize = vallen;
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
wsgi_req->response_size += write(wsgi_req->poll.fd, value, vallen);
}
}
break;
case 1:
// set
if (wsgi_req->uh.pktsize > 0) {
argc = 3;
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
if (argc > 1) {
uwsgi_cache_set(argv[0], strlen(argv[0]), argv[1], strlen(argv[1]), 0, 0);
}
}
}
break;
case 2:
// del
if (wsgi_req->uh.pktsize > 0) {
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
}
break;
case 4:
// dict
if (wsgi_req->uh.pktsize > 0) {
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh.pktsize, cache_command, (void *) wsgi_req);
}
break;
case 5:
// get (uwsgi + stream)
if (wsgi_req->uh.pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
wsgi_req->response_size += write(wsgi_req->poll.fd, value, vallen);
}
else {
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
}
}
break;
clear:
close(ctl_poll.fd);
}
return 0;
return NULL;
}
struct uwsgi_plugin uwsgi_cache_plugin = {
int uwsgi_cache_server(char *socket, int threads) {
.name = "cache",
.modifier1 = 111,
.request = uwsgi_cache_request,
int *fd = uwsgi_malloc(sizeof(int));
int i;
pthread_t thread_id;
char *tcp_port = strchr(socket, ':');
if (tcp_port) {
*fd = bind_to_tcp(socket, uwsgi.listen_queue, tcp_port);
}
else {
*fd = bind_to_unix(socket, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
};
pthread_mutex_init(&uwsgi.cache_server_lock, NULL);
if (threads < 1) threads = 1;
uwsgi_log("*** cache-optimized server enabled on fd %d (%d threads) ***\n", *fd, threads);
for(i=0;i<threads;i++) {
pthread_create(&thread_id, NULL, cache_thread_loop, (void *) fd);
}
return *fd;
}
+363
View File
@@ -0,0 +1,363 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_UDP
static void cluster_manage_opt(char *key, uint16_t keylen, char *value, uint16_t vallen, void *foobar) {
add_exported_option( uwsgi_concat2n(key, keylen, "", 0), uwsgi_concat2n(value, vallen, "", 0), 0);
}
void cluster_setup() {
int rlen;
// get cluster configuration
if (uwsgi.cluster != NULL) {
// get multicast socket
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
// ask for cluster options only if bot pre-existent options are set
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
// now wait max 60 seconds and resend multicast request every 10 seconds
for (;;) {
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
continue;
}
waitfd:
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
if (rlen < 0) {
break;
}
else if (rlen > 0) {
// receive the packet
char clusterbuf[4096];
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
uwsgi_configure();
goto options_parsed;
}
else {
goto waitfd;
}
}
}
}
options_parsed:
if (!uwsgi.cluster_nodes)
uwsgi_cluster_add_me();
}
}
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
int i;
struct uwsgi_cluster_node *ucn;
char *tcp_port;
#ifdef UWSGI_DEBUG
uwsgi_log("adding node\n");
#endif
tcp_port = strchr(nucn->name, ':');
#ifndef UWSGI_ZEROMQ
if (tcp_port == NULL) {
#else
char *zmq_dash = strchr(nucn->name, '-');
if (tcp_port == NULL && zmq_dash == NULL) {
#endif
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
return;
}
// first check for already present node
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0) {
if (!strcmp(ucn->name, nucn->name)) {
ucn->status = UWSGI_NODE_OK;
ucn->last_seen = time(NULL);
// update requests
ucn->requests = nucn->requests;
return;
}
}
}
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] == 0) {
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
ucn->workers = nucn->workers;
ucn->ucn_addr.sin_family = AF_INET;
if (tcp_port) {
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
tcp_port[0] = 0;
}
if (nucn->name[0] == 0) {
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", nucn->name);
#endif
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
}
ucn->type = type;
// here memory can be freed, as it is allocated by uwsgi_concat2n
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
tcp_port[0] = ':';
}
ucn->last_seen = time(NULL);
ucn->requests = nucn->requests;
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
return;
}
}
uwsgi_log("unable to add node %s\n", nucn->name);
}
int uwsgi_cluster_add_me() {
const char *key1 = "hostname";
const char *key2 = "address";
const char *key3 = "workers";
const char *key4 = "requests";
char *ptrbuf;
uint16_t ustrlen;
char numproc[6];
#ifdef UWSGI_ZEROMQ
char uuid_zmq_str[37];
uuid_t uuid_zmq;
if (!uwsgi.sockets && !uwsgi.zeromq) {
#else
if (!uwsgi.sockets) {
#endif
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
exit(1);
}
snprintf(numproc, 6, "%d", uwsgi.numproc);
size_t len;
if (uwsgi.sockets) {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
uuid_generate(uuid_zmq);
uuid_unparse(uuid_zmq, uuid_zmq_str);
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#endif
else {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
char *buf = uwsgi_malloc(len);
ptrbuf = buf;
ustrlen = strlen(key1);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key1, strlen(key1));
ptrbuf += strlen(key1);
ustrlen = strlen(uwsgi.hostname);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
ptrbuf += strlen(uwsgi.hostname);
if (uwsgi.sockets && uwsgi.sockets->name) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uwsgi.sockets->name);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
ptrbuf += strlen(uwsgi.sockets->name);
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uuid_zmq_str);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
ptrbuf += strlen(uuid_zmq_str);
}
#endif
ustrlen = strlen(key3);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key3, strlen(key3));
ptrbuf += strlen(key3);
ustrlen = strlen(numproc);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, numproc, strlen(numproc));
ptrbuf += strlen(numproc);
ustrlen = strlen(key4);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key4, strlen(key4));
ptrbuf += strlen(key4);
ustrlen = 1;
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, "0", 1);
ptrbuf += 1;
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
free(buf);
#ifdef UWSGI_DEBUG
uwsgi_log("add_me() successfull\n");
#endif
return 0;
}
int uwsgi_cluster_join(char *name) {
int fd;
char *cp;
int broadcast = 0;
if (name[0] == ':') {
fd = bind_to_udp(name, 0, 1);
broadcast = 1;
}
else {
fd = bind_to_udp(name, 1, 0);
}
if (fd >= 0) {
cp = strchr(name, ':');
cp[0] = 0;
uwsgi.mc_cluster_addr.sin_family = AF_INET;
if (broadcast) {
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
}
else {
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
}
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
cp[0] = ':';
// announce my presence to all the nodes
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
}
else {
exit(1);
}
return fd;
}
char *uwsgi_cluster_best_node() {
int i;
int best_node = -1;
struct uwsgi_cluster_node *ucn;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
if (best_node == -1) {
best_node = i;
}
else {
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
best_node = i;
}
}
}
}
if (best_node == -1) {
return NULL;
}
uwsgi.shared->nodes[best_node].last_choosen = time(NULL);
return uwsgi.shared->nodes[best_node].name;
}
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
}
if (!uwsgi_strncmp("address", 7, key, keylen)) {
strncpy(ucn->name, val, UMIN(vallen, 100));
}
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->workers = atoi(tmpstr);
free(tmpstr);
}
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->requests = strtoul(tmpstr, NULL, 0);
free(tmpstr);
}
}
#endif
+25
View File
@@ -0,0 +1,25 @@
require 'stringio'
hello = proc do |signum|
puts "Hello i am signal #{signum}"
end
file_changed = proc do |signum|
puts "/tmp has been modified"
end
UWSGI.register_signal(17, '', hello)
UWSGI.register_signal(30, '', file_changed)
UWSGI.add_rb_timer(17 , 2)
UWSGI.add_timer(17 , 1)
UWSGI.add_file_monitor(30 , '/tmp')
puts UWSGI.signal_registered(1)
puts UWSGI.signal_registered(17)
run lambda { |env|
puts env.inspect
UWSGI.signal(17)
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World!\n")]
}
+68
View File
@@ -0,0 +1,68 @@
require 'stringio'
require 'uwsgidsl'
signal 17,'mule5' do |signum|
end
puts UWSGI::VERSION
puts UWSGI::NUMPROC
puts UWSGI::HOSTNAME
puts UWSGI::OPT.inspect
timer 2 do |signum|
puts "ciao sono un dsl ruby: #{signum} #{UWSGI::OPT.inspect}"
end
timer 1,'mule1' do |signum|
puts "1 second elapsed (signum #{signum})"
end
filemon '/tmp' do |signum|
puts "/tmp has been modified"
end
cron 5,-1,-1,-1,-1 do |signum|
puts "cron ready #{signum}"
end
cron 58,-1,-1,-1,-1 do |signum|
puts "cron ready #{signum}"
end
postfork do
puts "fork() called"
end
rpc 'pippo' do
"i am an rpc function"
end
rpc 'pluto' do |x,y|
"i am another rpc function #{x} #{y}"
end
begin
foo_func
rescue
end
puts UWSGI.cache_exists('nilkey')
puts UWSGI.cache_exists?('nilkey')
UWSGI.cache_set!('foobar_key?a=1', UWSGI::OPT.inspect)
begin
puts UWSGI.cache_get(nil)
rescue
end
puts UWSGI.cache_get('foobar_key?a=1')
run lambda { |env|
puts env.inspect
UWSGI.setprocname("i am the uWSGI rack plugin")
UWSGI.signal(17)
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World! #{UWSGI.mem.inspect}\n")]
}
+99
View File
@@ -0,0 +1,99 @@
#!/bin/bash
# uwsgi - Use uwsgi to run python and wsgi web apps.
#
# chkconfig: - 85 15
# description: Use uwsgi to run python and wsgi web apps.
# processname: uwsgi
# author: Roman Vasilyev
# Source function library.
. /etc/rc.d/init.d/functions
PATH=/opt/uwsgi:/sbin:/bin:/usr/sbin:/usr/bin
prog=/usr/sbin/uwsgi
OWNER=nginx
NAME=uwsgi
DESC=uwsgi
#DAEMON_OPTS="-s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 4 -d /var/log/uwsgi.log --pidfile /var/run/$NAME.pid --pythonpath $PYTHONPATH --module $MODULE"
DAEMON_OPTS="-s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 16 -b 32768 -d /var/log/$NAME.log --pidfile /var/run/$NAME.pid --uid $OWNER"
[ -f /etc/sysconfig/uwsgi ] && . /etc/sysconfig/uwsgi
lockfile=/var/lock/subsys/uwsgi
start () {
echo -n "Starting $DESC: "
daemon $prog $DAEMON_OPTS
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop () {
echo -n "Stopping $DESC: "
killproc $prog
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
reload () {
echo "Reloading $NAME"
killproc $prog -HUP
RETVAL=$?
echo
}
force-reload () {
echo "Reloading $NAME"
killproc $prog -TERM
RETVAL=$?
echo
}
restart () {
stop
start
}
rh_status () {
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|force-reload)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
status)
rh_status
;;
*)
echo "Usage: $0 {start|stop|restart|reload|force-reload|status}" >&2
exit 2
;;
esac
exit 0
+53
View File
@@ -0,0 +1,53 @@
#include <Python.h>
void uwsgi_cgi_load_python() {
Py_Initialize();
}
void uwsgi_cgi_run_python(char *filename) {
char **e, *p;
PyObject *k, *env_value;
FILE *fp = fopen(filename, "r");
PySys_SetArgv(1, &filename);
PyObject *os_module = PyImport_ImportModule("os");
if (os_module) {
PyObject *os_module_dict = PyModule_GetDict(os_module);
PyObject *py_environ = PyDict_GetItemString(os_module_dict, "environ");
if (py_environ) {
for (e = environ; *e != NULL; e++) {
p = strchr(*e, '=');
if (p == NULL) continue;
k = PyString_FromStringAndSize(*e, (int)(p-*e));
if (k == NULL) {
PyErr_Print();
continue;
}
env_value = PyString_FromString(p+1);
if (env_value == NULL) {
PyErr_Print();
Py_DECREF(k);
continue;
}
if (PyObject_SetItem(py_environ, k, env_value)) {
PyErr_Print();
}
Py_DECREF(k);
Py_DECREF(env_value);
}
}
}
PyRun_AnyFileEx(fp, filename, 1);
}
+33
View File
@@ -0,0 +1,33 @@
# uwsgi --master --chdir /opt/graphite/webapp/graphite --module graphite_uwsgi ...
#
#
# this module will update a carbon server (used by the graphite tool: http://graphite.wikidot.com/)
# with requests count made by a Django app (and can track graphite itself as it is a Django app ;)
#
#
import os
import uwsgi
import time
from django.core.handlers.wsgi import WSGIHandler
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
CARBON_SERVER = "127.0.0.1:2003"
def update_carbon(signum):
# connect to the carbon server
carbon_fd = uwsgi.connect(CARBON_SERVER)
# send data to the carbon server
uwsgi.send(carbon_fd, "uwsgi.%s.requests %d %d\n" % (uwsgi.hostname, uwsgi.total_requests(), int(time.time())))
# close the connection with the carbon server
uwsgi.close(carbon_fd)
# register a new uwsgi signal (signum: 17)
uwsgi.register_signal(17, '', update_carbon)
# attach a timer of 10 seconds to signal 17
uwsgi.add_timer(17, 10)
# the Django app
application = WSGIHandler()
+15
View File
@@ -0,0 +1,15 @@
use IO::Socket::INET;
my $s = IO::Socket::INET->new(PeerAddr => '127.0.0.1', PeerPort => $ARGV[0]);
my $mountpoint = $ARGV[1];
my $app = $ARGV[2];
my $uwsgi_appid = pack('v', length('UWSGI_APPID')).'UWSGI_APPID'.pack('v', length($mountpoint)).$mountpoint;
my $uwsgi_script = pack('v', length('UWSGI_SCRIPT')).'UWSGI_SCRIPT'.pack('v', length($app)).$app;
$s->send(pack('CvC', 5, length($uwsgi_appid.$uwsgi_script),0).$uwsgi_appid.$uwsgi_script);
while((my $cnt = $s->recv(my $buf, 4096))> 0) {
print $buf;
}
+66
View File
@@ -0,0 +1,66 @@
import django
from django.core.management.base import BaseCommand
from django.conf import settings
import os
import sys
class Command(BaseCommand):
help = "Runs this project as a uWSGI application. Requires the uwsgi binary in system path."
http_port = '8000'
socket_addr = None
def handle(self, *args, **options):
for arg in args:
k,v = arg.split('=')
if k == 'http':
if self.http_port:
self.http_port = v
elif k == 'socket':
self.http_port = None
self.socket_addr = v
# load http and python plugin: first the specific version, otherwise try with the generic one
if self.http_port:
os.environ['UWSGI_PLUGINS'] = 'http,python%d%d:python' % (sys.version_info[0], sys.version_info[1])
else:
os.environ['UWSGI_PLUGINS'] = 'python%d%d:python' % (sys.version_info[0], sys.version_info[1])
# load the Django WSGI handler
os.environ['UWSGI_MODULE'] = 'django.core.handlers.wsgi:WSGIHandler()'
# DJANGO settings
if options['settings']:
os.environ['DJANGO_SETTINGS_MODULE'] = options['settings']
else:
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
# bind the http server to the default port
if self.http_port:
os.environ['UWSGI_HTTP'] = ':%s' % self.http_port
elif self.socket_addr:
os.environ['UWSGI_SOCKET'] = self.socket_addr
# map admin static files
os.environ['UWSGI_STATIC_MAP'] = '%s=%s' % (settings.ADMIN_MEDIA_PREFIX, os.path.join(django.__path__[0], 'contrib', 'admin', 'media'))
# remove sockets/pidfile at exit
os.environ['UWSGI_VACUUM'] = '1'
# retrieve/set the PythonHome
os.environ['UWSGI_PYHOME'] = sys.prefix
# increase buffer size a bit
os.environ['UWSGI_BUFFER_SIZE'] = '8192'
# add threads for concurrency
os.environ['UWSGI_THREADS'] = '8'
# enable the master process
os.environ['UWSGI_MASTER'] = '1'
# use uWSGI python module aliasing to fix the PYTHONPATH
os.environ['UWSGI_PYMODULE_ALIAS'] = '%s=./' % os.path.basename(os.getcwd())
# exec the uwsgi binary
os.execvp('uwsgi', ('uwsgi',))
def usage(self, subcomand):
return r"""
run this project on the uWSGI server
http=PORT run the embedded http server on port PORT
socket=ADDR bind the uwsgi server on address ADDR (this will disable the http server)
"""
+11
View File
@@ -0,0 +1,11 @@
from tasksconsumer import enqueue
def application(env, sr):
sr('200 OK', [('Content-Type','text/html')])
enqueue(queue='fast', pippo='pluto')
return "Task enqueued"
+9
View File
@@ -0,0 +1,9 @@
from tasksconsumer import *
@queueconsumer('fast', 4)
def fast_queue(arguments):
print "fast", arguments
@queueconsumer('slow')
def slow_queue(arguments):
print "foobar", arguments
+44
View File
@@ -0,0 +1,44 @@
from uwsgidecorators import *
import Queue
from threading import Thread
queues = {}
class queueconsumer(object):
def __init__(self, name, num=1, **kwargs):
self.name = name
self.num = num
self.queue = Queue.Queue()
self.threads = []
self.func = None
queues[self.name] = self
@staticmethod
def consumer(self):
while True:
req = self.queue.get()
print req
self.func(req)
self.queue.task_done()
def __call__(self, f):
self.func = f
for i in range(self.num):
t = Thread(target=self.consumer,args=(self,))
self.threads.append(t)
t.daemon = True
t.start()
@spool
def spooler_enqueuer(arguments):
if 'queue' in arguments:
queue = arguments['queue']
queues[queue].queue.put(arguments)
else:
raise Exception("You have to specify a queue name")
def enqueue(*args, **kwargs):
return spooler_enqueuer.spool(*args, **kwargs)
+3 -1
View File
@@ -12,4 +12,6 @@ env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --no-orphans avoid workers without master
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -m simple_app --logto $LOGTO -M -p 4
# --die-on-term could be a good idea
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
COMMAND=./uwsgi
CONFIG_FILE=
FIRST=0
for ARG in $@;do
if [ $FIRST -eq 0 ];then
FIRST=1
else
ARGS="$ARGS $ARG"
fi
done
export UWSGI_INHERIT=CONFIG_FILE
export UWSGI_PYRUN=$1
export UWSGI_PYARGV=$ARGS
exec $COMMAND
+4
View File
@@ -1,5 +1,9 @@
require 'rubygems'
require 'socket'
begin
require 'bundler/setup'
rescue LoadError
end
require 'rack'
require 'rack/content_length'
require 'rack/rewindable_input'
+123
View File
@@ -0,0 +1,123 @@
import mmap
import os
import struct
import array
import time
import sys
from optparse import OptionParser
class Cache:
def __init__(self, filename, cache_slots, block_size=65536, sample_sleep=1):
self.block_size = block_size
self.cache_slots = cache_slots
self.key_size = 2048
self.item_size = 2 + 2 + 4 + 8 + 8 + 8 + 8 + 8 + self.key_size
self.block_size_start = self.item_size * self.cache_slots
fd = os.open(filename, os.O_RDONLY)
self.cache_store = mmap.mmap(fd, 0, mmap.MAP_SHARED, mmap.PROT_READ)
self.sample_sleep = sample_sleep
self.samples = 0
self.history = []
self.cache_full = 0
self.cache_empty = 0
self.cache_items = 0
self.block_sizes = 0
def store_read_item_block(self, position):
pos = self.cache_store.tell()
# uwsgi cache stores cache entries first and then the blocks
self.cache_store.seek(self.block_size_start + (position * self.block_size))
buf = self.cache_store.read(self.block_size)
self.cache_store.seek(pos)
return buf
def store_read_item(self, position):
buf = self.cache_store.read(self.item_size)
fields = struct.unpack_from('@HHIQQQQQ2048c', buf)
key = array.array('c', fields[8:self.key_size+8]).tostring().rstrip('\x00')
if [x for x in key if x!= '\x00']:
buf = self.store_read_item_block(position)
value = array.array('c', buf).tostring().rstrip('\x00')
else:
value = ''
return (position, key, value, len(value))
def read(self):
data = [self.store_read_item(i) for i in range(self.cache_slots)]
self.cache_store.seek(0)
self.update_stats(data)
if self.sample_sleep:
time.sleep(self.sample_sleep)
return data
def update_stats(self, data):
# data is a list of (position, key, value, len(value)) tuples
items = len([1 for x in data if x[3] > 0])
self.cache_items += items
full, empty = items == self.cache_slots, items == 0
if full:
self.cache_full += 1
if empty:
self.cache_empty += 1
self.samples += 1
block_sizes = sum([x[3] for x in data])
self.block_sizes += block_sizes
self.history.append({'full': full, 'empty': empty, 'data': data, \
'items': items, 'block_sizes': block_sizes})
def dump(self):
return {
'samples': self.samples,
'history': self.history,
'cache_slots': self.cache_slots,
'sample_sleep': self.sample_sleep,
'cache_empty': self.cache_empty,
'cache_full': self.cache_full,
'cache_items': self.cache_items,
'block_sizes': self.block_sizes,
}
def show_dump(self):
d = self.dump()
print
print "Recorded %d samples (%d second(s) sleep between samples)" % \
(d['samples'], d['sample_sleep'])
print "Cache empty %d times, full %d times, %.2f items on average" % \
(d['cache_empty'], d['cache_full'], d['cache_items'] / d['samples'])
print "Block size average size: %d bytes" % \
(d['block_sizes'] / d['cache_items'] * 8)
print "Data in cache average: %d bytes" % \
(d['block_sizes'] / d['samples'] * 8)
def main(options):
cache = Cache(options.cache_store, options.cache_slots, options.block_size,
options.sleep_time)
print "Recording..."
while True:
try:
data = cache.read()
except KeyboardInterrupt:
cache.show_dump()
sys.exit(0)
if __name__ == '__main__':
parser = OptionParser()
parser.add_option("-s", "--cache-slots", dest="cache_slots", type="int",
help="Slots available in the cache, uwsgi cache option")
parser.add_option("-c", "--cache-store", dest="cache_store", default="uwsgi.cache",
help="The filename of the cache store, uwsgi cache-store option. Default: uwsgi.cache")
parser.add_option("-b", "--block-size", dest="block_size", default=65536, type="int",
help="The size of the cache block, uwsgi cache-blocksize option. Default: 65536")
parser.add_option("-t", "--sleep-time", dest="sleep_time", default=1, type="int",
help="The time to sleep between each sample. Default: 1")
(options, args) = parser.parse_args()
if not options.cache_slots:
parser.error('Option -s / --cache-slots is mandatory')
main(options)
+14
View File
@@ -0,0 +1,14 @@
service uwsgi
{
disable = no
id = uwsgi-000
type = UNLISTED
socket_type = stream
server = /root/uwsgi/uwsgi
server_args = --chdir /root/uwsgi/ --module welcome --logto /tmp/uwsgi.log
port = 3031
bind = 127.0.0.1
user = root
wait = yes
}
+2
View File
@@ -0,0 +1,2 @@
[uwsgi]
show-config = true
+133
View File
@@ -0,0 +1,133 @@
#!./uwsgi --import decoratortest -s :3035 -M --spooler myspool --enable-threads -p 8 --spooler-ordered
import uwsgi
from uwsgidecorators import *
from uwsgicc import app as application
import time
# register rpc function helloworld
@rpc("helloworld")
def hello2():
return "[RPC] Hello World"
# register signal 1
@signal(1)
def what_time_is_it(num):
print(time.asctime())
# register signal 100
@signal(100, target='workers')
def what_time_is_it(num):
print("*** I AM THE WORKER %d AT %s ***" % (uwsgi.worker_id(), time.asctime()))
# a 3 seconds timer
@timer(3)
def salut(num):
print("Salut !!! 3 seconds elapsed and signal %d raised" % num)
# a 10 seconds red black timer (executed by the spooler)
@rbtimer(10, target='spooler')
def tenseconds(num):
print("red black timer !!! 10 seconds elapsed and signal %d raised" % num)
# monitor /tmp directory
@filemon("/tmp")
def tmpmodified(num):
print("/tmp has been modified")
# spool a long running task
@spool
def a_long_task(args):
for i in xrange(1,10):
print("%s = %d" % ( str(args), i))
print(uwsgi.call('helloworld'))
time.sleep(1)
# continuosly spool a long running task
@spoolforever
def an_infinite_task(args):
for i in xrange(1,4):
print("infinite: %d %s" % (i, str(args)))
print(uwsgi.call('helloworld'))
uwsgi.signal(100)
time.sleep(1)
# spool a task after 5 seconds
@spool
def delayed_task(args):
print("*** I am a delayed spool job. It is %s [%s]***" % (time.asctime(), str(args)))
# send a signal to all workers
uwsgi.signal(100)
@spool
def big_body_task(args):
print("*** managing a task with a body of %d bytes ***" % len(args['body']))
print(args['body'].swapcase())
# run a task every hour
@cron(59, -1, -1, -1, -1)
def one_hour_passed(num):
print("received signal %d after 1 hour" % num)
@thread
def a_running_thread():
while True:
time.sleep(2)
print("i am a no-args thread")
@thread
def a_running_thread_with_args(who):
while True:
time.sleep(2)
print("Hello %s (from arged-thread)" % who)
@postfork
@thread
def a_post_fork_thread():
while True:
time.sleep(3)
if uwsgi.i_am_the_spooler():
print("Hello from a thread in the spooler")
else:
print("Hello from a thread in worker %d" % uwsgi.worker_id())
@postfork
def fork_happened():
print("fork() has been called [1]")
@postfork
def fork_happened2():
if uwsgi.i_am_the_spooler():
return
print("worker %d is waiting for signal 100..." % uwsgi.worker_id())
uwsgi.signal_wait(100)
print("worker %d received signal %d" % (uwsgi.worker_id(), uwsgi.signal_received()))
print("fork() has been called [2] wid: %d" % uwsgi.worker_id())
@postfork
@lock
def locked_func():
print("starting locked function on worker %d" % uwsgi.worker_id())
for i in xrange(1, 5):
time.sleep(1)
print("[locked %d] waiting..." % uwsgi.worker_id())
print("done with locked function on worker %d" % uwsgi.worker_id())
print(uwsgi.call('helloworld'))
spool_filename = a_long_task.spool({'foo':'bar'}, hello='world')
print("spool filename = %s" % spool_filename)
an_infinite_task.spool(foo='bar', priority=3)
when = int(time.time())+5
print("scheduling a delayed task at %d" % when)
delayed_task.spool(foo2='bar2', at=when)
a_running_thread()
a_running_thread_with_args("uWSGI")
uwsgi_source_file = open('uwsgi.c','r')
print(big_body_task.spool(priority=9,filename='uwsgi.c',body=uwsgi_source_file.read()))
uwsgi_source_file.close()
+4 -3
View File
@@ -14,10 +14,11 @@ def index(request):
w['load'] = (100 * (w['running_time']/1000))/total_load
w['last_spawn_str'] = time.ctime(w['last_spawn'])
spooler_jobs = uwsgi.spooler_jobs()
jobs = []
for j in spooler_jobs:
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
if 'spooler' in uwsgi.opt:
spooler_jobs = uwsgi.spooler_jobs()
for j in spooler_jobs:
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
'started_on': time.ctime(uwsgi.started_on),
+29
View File
@@ -0,0 +1,29 @@
from django.template.base import TemplateDoesNotExist
from django.template.loader import BaseLoader
from django.conf import settings
try:
import uwsgi
on_uwsgi = True
except:
on_uwsgi = False
class Loader(BaseLoader):
is_usable = on_uwsgi
def symbolize(self, name):
return name.replace('.','_').replace('/','_').replace('-','_')
def load_template_source(self, template_name, template_dirs=None):
filename = 'templates_' + self.symbolize(template_name)
for app in settings.INSTALLED_APPS:
try:
symbol = "%s_%s" % (self.symbolize(app), filename)
return (uwsgi.embedded_data(symbol), "sym://%s" % symbol)
except:
pass
raise TemplateDoesNotExist(template_name)
+694 -103
View File
@@ -5,29 +5,98 @@
extern struct uwsgi_server uwsgi;
extern char **environ;
int emperor_queue;
char *emperor_absolute_dir;
void emperor_send_stats(int);
struct uwsgi_instance {
struct uwsgi_instance *ui_prev;
struct uwsgi_instance *ui_next;
struct uwsgi_instance *ui_prev;
struct uwsgi_instance *ui_next;
char name[0xff];
pid_t pid ;
char name[0xff];
pid_t pid;
int status;
time_t born;
time_t last_mod;
int status;
time_t born;
time_t last_mod;
time_t last_loyal;
uint64_t respawns;
uint64_t respawns;
int use_config;
int pipe[2];
int pipe[2];
int pipe_config[2];
char *config;
uint32_t config_len;
int loyal;
int zerg;
uid_t uid;
gid_t gid;
};
struct uwsgi_instance *ui;
static void royal_death(int signum) {
if (uwsgi.vassals_stop_hook) {
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
uwsgi_log("running vassal stop-hook: %s %s\n", uwsgi.vassals_stop_hook, c_ui->name);
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
uwsgi_error("setenv()");
}
int stop_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_stop_hook, c_ui->name);
uwsgi_log("%s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
c_ui = c_ui->ui_next;
}
}
uwsgi_notify("The Emperor is buried.");
exit(0);
}
void emperor_stats() {
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
uwsgi_log("vassal instance %s (last modified %d) status %d loyal %d zerg %d\n",c_ui->name, c_ui->last_mod, c_ui->status, c_ui->loyal, c_ui->zerg);
c_ui = c_ui->ui_next;
}
}
struct uwsgi_instance *emperor_get_by_fd(int fd) {
struct uwsgi_instance *c_ui = ui;
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
if (c_ui->pipe[0] == fd) {
return c_ui;
}
}
return NULL;
}
struct uwsgi_instance *emperor_get(char *name) {
struct uwsgi_instance *c_ui = ui;
while(c_ui->ui_next) {
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
if (!strcmp(c_ui->name, name)) {
@@ -50,8 +119,25 @@ void emperor_del(struct uwsgi_instance *c_ui) {
// this will destroy the whole uWSGI instance (and workers)
close(c_ui->pipe[0]);
if (c_ui->use_config) {
close(c_ui->pipe_config[0]);
}
if (uwsgi.vassals_stop_hook) {
uwsgi_log("running vassal stop-hook: %s %s\n", uwsgi.vassals_stop_hook, c_ui->name);
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
uwsgi_error("setenv()");
}
int stop_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_stop_hook, c_ui->name);
uwsgi_log("%s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
}
uwsgi_log("removed uwsgi instance %s\n", c_ui->name);
if (c_ui->zerg) {
uwsgi.emperor_broodlord_count--;
}
free(c_ui);
}
@@ -71,44 +157,93 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
// reload the uWSGI instance
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
}
if (c_ui->use_config) {
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("write()");
}
}
else {
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
}
}
c_ui->respawns++;
c_ui->respawns++;
c_ui->last_mod = mod;
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(char *name, time_t born) {
void emperor_add(char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
struct uwsgi_instance *c_ui = ui;
struct uwsgi_instance *n_ui = NULL;
pid_t pid ;
char *argv[4];
char *uef ;
pid_t pid;
char **vassal_argv;
char *uef;
char **uenvs;
int counter;
char *colon = NULL;
int i;
while(c_ui->ui_next) {
c_ui = c_ui->ui_next;
}
usleep(uwsgi.emperor_throttle*1000);
if (uwsgi.emperor_tyrant) {
if (uid == 0 || gid == 0) {
uwsgi_log("[emperor-tyrant] invalid permissions for file %s\n", name);
return;
}
}
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
}
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
memset(n_ui, 0, sizeof(struct uwsgi_instance));
if (config) {
n_ui->use_config = 1;
n_ui->config = config;
n_ui->config_len = config_size;
}
c_ui->ui_next = n_ui;
#ifdef UWSGI_DEBUG
uwsgi_log("c_ui->ui_next = %p\n", c_ui->ui_next);
#endif
n_ui->ui_prev = c_ui;
if (strchr(name,':')) {
n_ui->zerg = 1;
uwsgi.emperor_broodlord_count++;
}
memcpy(n_ui->name, name, strlen(name));
n_ui->born = born;
n_ui->uid = uid;
n_ui->gid = gid;
n_ui->last_mod = born;
// start without loyalty
n_ui->last_loyal = born;
n_ui->loyal = 0;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
uwsgi_error("socketpair()");
goto clear;
}
event_queue_add_fd_read(emperor_queue, n_ui->pipe[0]);
if (n_ui->use_config) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
uwsgi_error("socketpair()");
goto clear;
}
}
// TODO pre-start hook
// a new uWSGI instance will start
pid = fork();
if (pid < 0) {
@@ -118,11 +253,40 @@ void emperor_add(char *name, time_t born) {
n_ui->pid = pid;
// close the right side of the pipe
close(n_ui->pipe[1]);
if (n_ui->use_config) {
close(n_ui->pipe_config[1]);
}
if (n_ui->use_config) {
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) <= 0) {
uwsgi_error("write()");
}
close(n_ui->pipe_config[0]);
}
return;
}
else {
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
if (setgid(gid)) {
uwsgi_error("setgid()");
exit(1);
}
if (setgroups(0, NULL)) {
uwsgi_error("setgroups()");
exit(1);
}
if (setuid(uid)) {
uwsgi_error("setuid()");
exit(1);
}
}
unsetenv("UWSGI_RELOADS");
unsetenv("NOTIFY_SOCKET");
uef = uwsgi_num2str(n_ui->pipe[1]);
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
@@ -131,17 +295,28 @@ void emperor_add(char *name, time_t born) {
}
free(uef);
if (n_ui->use_config) {
uef = uwsgi_num2str(n_ui->pipe_config[1]);
if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
}
free(uef);
}
uenvs = environ;
while(*uenvs) {
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
char *ne = uwsgi_concat2("UWSGI_", *uenvs+13);
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
break;
}
free(oe);
#ifdef UWSGI_DEBUG
uwsgi_log("putenv %s\n", ne);
#endif
if (putenv(ne)) {
uwsgi_error("putenv()");
@@ -156,24 +331,110 @@ void emperor_add(char *name, time_t born) {
// close the left side of the pipe
close(n_ui->pipe[0]);
if (n_ui->use_config) {
close(n_ui->pipe_config[0]);
}
counter = 4;
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
while(uct) {
counter+=2;
uct = uct->next;
}
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
argv[0] = uwsgi.binary_path;
if (!strcmp(name+(strlen(name)-4), ".xml")) argv[1] = "--xml";
if (!strcmp(name+(strlen(name)-4), ".ini")) argv[1] = "--ini";
if (!strcmp(name+(strlen(name)-4), ".yml")) argv[1] = "--yaml";
if (!strcmp(name+(strlen(name)-5), ".yaml")) argv[1] = "--yaml";
argv[2] = name;
argv[3] = NULL;
vassal_argv[0] = uwsgi.binary_path;
if (uwsgi.emperor_broodlord) {
colon = strchr(name, ':');
if (colon) {
colon[0] = 0;
}
}
// initialize to a default value
vassal_argv[1] = "--inherit";
if (!strcmp(name + (strlen(name) - 4), ".xml"))
vassal_argv[1] = "--xml";
if (!strcmp(name + (strlen(name) - 4), ".ini"))
vassal_argv[1] = "--ini";
if (!strcmp(name + (strlen(name) - 4), ".yml"))
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 3), ".js"))
vassal_argv[1] = "--json";
if (!strcmp(name + (strlen(name) - 5), ".json"))
vassal_argv[1] = "--json";
if (colon) {
colon[0] = ':';
}
vassal_argv[2] = name;
if (uwsgi.emperor_magic_exec) {
if (!access(name, R_OK|X_OK)) {
vassal_argv[2] = uwsgi_concat2("exec://", name);
}
}
counter = 3;
uct = uwsgi.vassals_templates;
while(uct) {
vassal_argv[counter] = "--inherit";
vassal_argv[counter+1] = uct->value;
counter+=2;
uct = uct->next;
}
vassal_argv[counter] = NULL;
// disable stdin
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0)) {
uwsgi_error("dup2()");
exit(1);
}
close(stdin_fd);
}
// close all of the unneded fd
for(i=3;i<(int)uwsgi.max_fd;i++) {
if (n_ui->use_config) {
if (i == n_ui->pipe_config[1])
continue;
}
if (i != n_ui->pipe[1]) {
close(i);
}
}
if (uwsgi.vassals_start_hook) {
uwsgi_log("running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name);
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
uwsgi_error("setenv()");
}
int start_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_start_hook, n_ui->name);
uwsgi_log("%s start-hook returned %d\n", n_ui->name, start_hook_ret);
}
// start !!!
if (execvp(argv[0], argv)) {
if (execvp(vassal_argv[0], vassal_argv)) {
uwsgi_error("execvp()");
}
uwsgi_log("is the uwsgi binary in your system PATH ?\n");
// never here
exit(1);
exit(UWSGI_EXILE_CODE);
}
clear:
clear:
free(n_ui);
c_ui->ui_next = NULL;
@@ -196,156 +457,486 @@ void emperor_loop() {
glob_t g;
int i;
struct dirent *de;
char *amqp_port;
int amqp_fd = -1;
char *amqp_routing_key;
void *events;
int nevents;
int interesting_fd;
char notification_message[64];
struct rlimit rl;
uwsgi.emperor_stats_fd = -1;
signal(SIGPIPE, SIG_IGN);
uwsgi_unix_signal(SIGINT, royal_death);
uwsgi_unix_signal(SIGTERM, royal_death);
uwsgi_unix_signal(SIGQUIT, royal_death);
uwsgi_unix_signal(SIGUSR1, emperor_stats);
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
uwsgi_log("*** starting uWSGI Emperor ***\n");
if (getrlimit(RLIMIT_NOFILE, &rl)) {
uwsgi_error("getrlimit()");
exit(1);
}
if (!glob(uwsgi.emperor_dir, GLOB_MARK, NULL, &g)) {
if (g.gl_pathc == 1 && g.gl_pathv[0][strlen(g.gl_pathv[0])-1] == '/' ) {
simple_mode = 1;
if (chdir(uwsgi.emperor_dir)) {
uwsgi_error("chdir()");
exit(1);
}
}
uwsgi.max_fd = rl.rlim_cur;
emperor_queue = event_queue_init();
events = event_queue_alloc(64);
if (uwsgi.has_emperor) {
uwsgi_log("*** starting uWSGI sub-Emperor ***\n");
}
else {
uwsgi_error("glob()");
exit(1);
uwsgi_log("*** starting uWSGI Emperor ***\n");
}
if (uwsgi.emperor_stats) {
char *tcp_port = strchr(uwsgi.emperor_stats, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
uwsgi.emperor_stats_fd = bind_to_tcp(uwsgi.emperor_stats, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
uwsgi.emperor_stats_fd = bind_to_unix(uwsgi.emperor_stats, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
event_queue_add_fd_read(emperor_queue, uwsgi.emperor_stats_fd);
uwsgi_log("*** Emperor stats server enabled on %s fd: %d ***\n", uwsgi.emperor_stats, uwsgi.emperor_stats_fd);
}
amqp_port = strchr(uwsgi.emperor_dir, ':');
if (amqp_port) {
if (uwsgi.emperor_amqp_vhost == NULL) uwsgi.emperor_amqp_vhost = "/";
if (uwsgi.emperor_amqp_username == NULL) uwsgi.emperor_amqp_username = "guest";
if (uwsgi.emperor_amqp_password == NULL) uwsgi.emperor_amqp_password = "guest";
reconnect:
while(amqp_fd == -1) {
uwsgi_log("connecting to AMQP server...\n");
amqp_fd = uwsgi_connect(uwsgi.emperor_dir, -1, 0);
if (amqp_fd < 0) {
sleep(1);
}
}
uwsgi_log("subscribing to queue...\n");
if (uwsgi_amqp_consume_queue(amqp_fd, uwsgi.emperor_amqp_vhost, uwsgi.emperor_amqp_username, uwsgi.emperor_amqp_password, "", "uwsgi.emperor", "fanout") < 0) {
close(amqp_fd);
amqp_fd = -1;
sleep(1);
goto reconnect;
}
event_queue_add_fd_read(emperor_queue, amqp_fd);
}
else {
if (!glob(uwsgi.emperor_dir, GLOB_MARK|GLOB_NOCHECK, NULL, &g)) {
if (g.gl_pathc == 1 && g.gl_pathv[0][strlen(g.gl_pathv[0]) - 1] == '/') {
simple_mode = 1;
if (chdir(uwsgi.emperor_dir)) {
uwsgi_error("chdir()");
exit(1);
}
}
}
else {
uwsgi_error("glob()");
exit(1);
}
globfree(&g);
emperor_absolute_dir = uwsgi_malloc(PATH_MAX+1);
if (realpath(".", emperor_absolute_dir) == NULL) {
uwsgi_error("realpath()");
exit(1);
}
}
ui = &ui_base;
for(;;) {
int freq = 0 ;
for (;;) {
if (!i_am_alone) {
diedpid = waitpid(uwsgi.emperor_pid, &waitpid_status, WNOHANG);
if (diedpid < 0) {
uwsgi_error("waitpid()");
}
else if (diedpid > 0) {
if (diedpid < 0 || diedpid > 0) {
i_am_alone = 1;
}
}
nevents = event_queue_wait_multi(emperor_queue, freq, events, 64);
freq = 3;
for (i = 0; i<nevents;i++) {
interesting_fd = event_queue_interesting_fd(events, i);
if (amqp_fd > -1 && interesting_fd == amqp_fd ) {
uint64_t msgsize;
char *config = uwsgi_amqp_consume(amqp_fd, &msgsize, &amqp_routing_key);
if (!config) {
uwsgi_log("problem with RabbitMQ server, trying reconnection...\n");
event_queue_del_fd(emperor_queue, amqp_fd, event_queue_read());
close(amqp_fd);
amqp_fd = -1;
goto reconnect;
}
if (amqp_routing_key) {
uwsgi_log("AMQP routing_key = %s\n", amqp_routing_key);
char *config_file = uwsgi_concat2("emperor://", amqp_routing_key);
free(amqp_routing_key);
ui_current = emperor_get(config_file);
if (ui_current) {
// ignore event if i am not loyal
if (!ui_current->loyal) continue;
free(ui_current->config);
ui_current->config = config;
ui_current->config_len = msgsize;
if (!msgsize) {
// SAFE
emperor_del(ui_current);
}
else {
emperor_respawn(ui_current, time(NULL));
}
}
else {
if (msgsize > 0) {
emperor_add(config_file, time(NULL), config, msgsize, 0, 0);
}
}
free(config_file);
}
else {
if (msgsize) {
if (msgsize >= 0xff) { free(config); continue; }
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s\n", (int)msgsize, config);
#endif
char *config_file = uwsgi_concat2n(config, msgsize, "", 0);
free(config);
if (strncmp(config_file, "http://", 7)) {
if (stat(config_file, &st)) {
free(config_file);
continue;
}
if (!S_ISREG(st.st_mode)) {
free(config_file);
continue;
}
}
ui_current = emperor_get(config_file);
if (ui_current) {
// ignore event if i am not loyal
if (!ui_current->loyal) continue;
emperor_respawn(ui_current, time(NULL));
}
else {
emperor_add(config_file, time(NULL), NULL, 0, 0, 0);
}
free(config_file);
}
}
}
else if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1 && interesting_fd == uwsgi.emperor_stats_fd) {
emperor_send_stats(uwsgi.emperor_stats_fd);
}
else {
ui_current = emperor_get_by_fd(interesting_fd);
if (ui_current) {
char byte;
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
if (!ui_current->config_len) {
emperor_del(ui_current);
}
}
else {
if (byte == 17) {
ui_current->loyal = 1;
uwsgi_log("*** vassal %s is now loyal ***\n", ui_current->name);
// TODO post-start hook
}
else if (byte == 22) {
emperor_stop(ui_current);
}
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
char *zerg_name = uwsgi_concat3(ui_current->name,":","zerg");
emperor_add(zerg_name, time(NULL), NULL, 0, ui_current->uid, ui_current->gid);
free(zerg_name);
}
}
}
else {
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
event_queue_del_fd(emperor_queue, interesting_fd, event_queue_read());
close(interesting_fd);
}
}
}
if (amqp_fd == -1) {
if (simple_mode) {
DIR *dir = opendir(".");
while((de = readdir(dir)) != NULL) {
if (!strcmp(de->d_name+(strlen(de->d_name)-4), ".xml") ||
!strcmp(de->d_name+(strlen(de->d_name)-4), ".ini") ||
!strcmp(de->d_name+(strlen(de->d_name)-4), ".yml") ||
!strcmp(de->d_name+(strlen(de->d_name)-5), ".yaml")
while ((de = readdir(dir)) != NULL) {
if (!strcmp(de->d_name + (strlen(de->d_name) - 4), ".xml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".ini") ||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".yml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".yaml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 3), ".js") ||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".json")
) {
if (strlen(de->d_name) >= 0xff) continue;
if (stat(de->d_name, &st)) continue;
if (strlen(de->d_name) >= 0xff)
continue;
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (!S_ISREG(st.st_mode)) continue;
ui_current = emperor_get(de->d_name);
if (ui_current) {
// check if uid or gid are changed, in such case, sotp the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
emperor_stop(ui_current);
continue;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(de->d_name, st.st_mtime);
emperor_add(de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
}
closedir(dir);
}
else {
if (glob(uwsgi.emperor_dir, GLOB_MARK, NULL, &g)) {
if (glob(uwsgi.emperor_dir, GLOB_MARK|GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("glob()");
continue;
}
for(i=0;i<(int)g.gl_pathc;i++) {
if (!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-4), ".xml") ||
!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-4), ".ini") ||
!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-4), ".yml") ||
!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-5), ".yaml")
) {
for (i = 0; i < (int) g.gl_pathc; i++) {
if (!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".xml") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".ini") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".yml") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 3), ".js") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".json") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".yaml")
) {
if (strlen(g.gl_pathv[i]) >= 0xff) continue;
if (strlen(g.gl_pathv[i]) >= 0xff)
continue;
if (stat(g.gl_pathv[i], &st)) continue;
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode)) continue;
if (!S_ISREG(st.st_mode))
continue;
ui_current = emperor_get(g.gl_pathv[i]);
ui_current = emperor_get(g.gl_pathv[i]);
if (ui_current) {
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
if (ui_current) {
// check if uid or gid are changed, in such case, sotp the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
emperor_stop(ui_current);
continue;
}
}
}
else {
emperor_add(g.gl_pathv[i], st.st_mtime);
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
}
globfree(&g);
}
}
// check for removed instances
ui_current = ui;
has_children = 0;
while(ui_current->ui_next) {
ui_current = ui_current->ui_next;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
has_children++;
}
if (uwsgi.notify) {
if (snprintf(notification_message, 64, "The Emperor is governing %d vassals", has_children) >= 34) {
uwsgi_notify(notification_message);
}
}
if (has_children) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
else {
// vacuum
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
diedpid = 0;
}
if (diedpid < 0) {
uwsgi_error("waitpid()");
}
ui_current = ui;
while(ui_current->ui_next) {
ui_current = ui_current->ui_next;
if (ui_current->pid == diedpid) {
if (ui_current->status == 0) {
// respawn an accidentally dead instance
emperor_add(ui_current->name, ui_current->last_mod);
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
// check loyalty if not in simple/glob mode
if (amqp_fd > -1) {
if (!ui_current->loyal && (time(NULL)-ui_current->last_loyal) > 60) {
uwsgi_log("!!! no loyalty showed by instance %s !!!\n", ui_current->name);
// SAFE
emperor_del(ui_current);
break;
}
}
if (ui_current->status == 1) {
if (ui_current->config) free(ui_current->config);
// SAFE
emperor_del(ui_current);
break;
}
else if (!ui_current->use_config && strncmp(ui_current->name, "http://",7) && stat(ui_current->name, &st) && !ui_current->zerg) {
emperor_stop(ui_current);
}
else if (ui_current->pid == diedpid) {
if (ui_current->status == 0) {
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
// SAFE
emperor_del(ui_current);
}
else {
// UNSAFE
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
emperor_del(ui_current);
}
break;
}
else if (ui_current->status == 1) {
// remove 'marked for dead' instance
if (ui_current->config) free(ui_current->config);
// SAFE
emperor_del(ui_current);
break;
}
}
else if (ui_current->status == 1) {
emperor_del(ui_current);
break;
}
else if (stat(ui_current->name, &st)) {
emperor_stop(ui_current);
}
}
}
sleep(3);
}
}
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
void emperor_send_stats(int fd) {
struct sockaddr_un client_src;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
stats_send("\"emperor\": \"%s\",\n", uwsgi.emperor_dir);
fprintf(output,"\"emperor_tyrant\": %d,\n", uwsgi.emperor_tyrant);
fprintf(output, "\"vassals\": [\n");
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
fprintf(output,"\t{");
stats_send("\"id\": \"%s\", ", c_ui->name);
fprintf(output,"\"pid\": %d, ", (int) c_ui->pid);
stats_send_llu( "\"born\": %llu, ", c_ui->born);
stats_send_llu( "\"last_mod\": %llu, ", c_ui->last_mod);
fprintf(output,"\"loyal\": %d, ", c_ui->loyal);
fprintf(output,"\"zerg\": %d, ", c_ui->zerg);
fprintf(output,"\"uid\": %d, ", (int)c_ui->uid);
fprintf(output,"\"gid\": %d, ", (int)c_ui->gid);
stats_send_llu( "\"respawns\": %llu ", c_ui->respawns);
c_ui = c_ui->ui_next;
if (c_ui) {
fprintf(output,"},\n");
}
else {
fprintf(output,"}\n");
}
}
fprintf(output,"]}\n");
fclose(output);
}
+77 -26
View File
@@ -6,6 +6,9 @@ extern struct uwsgi_server uwsgi;
#include <port.h>
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int event_queue_init() {
int port = port_create();
@@ -18,7 +21,7 @@ int event_queue_init() {
return port;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
if (port_dissociate(eq, PORT_SOURCE_FD, fd)) {
uwsgi_error("port_disassociate");
@@ -28,6 +31,17 @@ int event_queue_del_fd(int eq, int fd) {
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
@@ -67,7 +81,7 @@ void *event_queue_alloc(int nevents) {
int event_queue_interesting_fd(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
return (int) pe[id].portev_user;
return (long) pe[id].portev_user;
}
return (int) pe[id].portev_object;
@@ -76,12 +90,11 @@ int event_queue_interesting_fd(void *events, int id) {
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
uint_t nget;
int i;
uint_t nget = 1;
timespec_t ts;
port_event_t *pe;
if (timeout > 0) {
if (timeout >= 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_getn(eq, events, nevents, &nget, &ts);
@@ -99,13 +112,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
}
pe = (port_event_t *) events;
for(i=0;i<nget;i++) {
if (pe[i].portev_source == PORT_SOURCE_FD) {
if (port_associate(eq, pe[i].portev_source, pe[i].portev_object, pe[i].portev_events, NULL)) {
uwsgi_error("port_associate");
}
}
}
return nget;
}
@@ -143,8 +149,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
*interesting_fd = (int) pe.portev_user;
uwsgi_log("port event interesting_fd: %d\n", *interesting_fd);
*interesting_fd = (long) pe.portev_user;
}
else {
*interesting_fd = (int) pe.portev_object;
@@ -160,10 +165,14 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
#include <sys/epoll.h>
#define UWSGI_EVENT_IN EPOLLIN
#define UWSGI_EVENT_OUT EPOLLOUT
int event_queue_init() {
int epfd;
epfd = epoll_create(256);
if (epfd < 0) {
@@ -207,12 +216,13 @@ int event_queue_fd_write_to_read(int eq, int fd) {
return fd;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.data.fd = fd;
ee.events = event;
if (epoll_ctl(eq, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
@@ -298,6 +308,10 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
#endif
#ifdef UWSGI_EVENT_USE_KQUEUE
#define UWSGI_EVENT_IN EVFILT_READ
#define UWSGI_EVENT_OUT EVFILT_WRITE
int event_queue_init() {
int kfd = kqueue();
@@ -314,11 +328,13 @@ int event_queue_fd_write_to_read(int eq, int fd) {
struct kevent kev;
#ifndef __FreeBSD__
EV_SET(&kev, fd, EVFILT_WRITE, EV_DISABLE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
#endif
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
@@ -329,11 +345,11 @@ int event_queue_fd_write_to_read(int eq, int fd) {
return fd;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
EV_SET(&kev, fd, event, EV_DELETE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
@@ -388,7 +404,8 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
}
if (ret < 0) {
uwsgi_error("kevent()");
if (errno != EINTR)
uwsgi_error("kevent()");
}
return ret;
@@ -404,7 +421,8 @@ int event_queue_interesting_fd(void *events, int id) {
int event_queue_interesting_fd_has_error(void *events, int id) {
struct kevent *ev = (struct kevent *) events;
if ( ( (ev[id].flags == EV_ERROR) || (ev[id].flags == EV_EOF) || (ev[id].flags == (EV_EOF|EV_ERROR))) ) {
// DO NOT CHECK FOR EOF !!!
if ( ev[id].flags & EV_ERROR ) {
return 1;
}
return 0;
@@ -428,7 +446,8 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
}
if (ret < 0) {
uwsgi_error("kevent()");
if (errno != EINTR)
uwsgi_error("kevent()");
}
if (ret > 0) {
@@ -463,7 +482,7 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
fo.fo_ctime = st.st_ctim;
fmon_id++;
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) fmon_id)) {
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) (long) fmon_id)) {
uwsgi_error("port_associate()");
return -1;
}
@@ -493,7 +512,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
fo.fo_atime = st.st_atim;
fo.fo_mtime = st.st_mtim;
fo.fo_ctime = st.st_ctim;
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)id)) {
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)(long)id)) {
uwsgi_error("port_associate()");
return NULL;
}
@@ -516,7 +535,7 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(filename);
return -1;
}
@@ -552,6 +571,16 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifdef OBSOLETE_LINUX_KERNEL
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
return -1;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#else
#include <sys/inotify.h>
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
@@ -578,7 +607,9 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
*id = inotify_add_watch(ifd, filename, IN_ATTRIB|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MODIFY|IN_MOVE_SELF|IN_MOVED_FROM|IN_MOVED_TO);
#ifdef UWSGI_DEBUG
uwsgi_log("added watch %d for filename %s\n", *id, filename);
#endif
if (add_to_queue) {
return event_queue_add_fd_read(eq, ifd);
@@ -617,7 +648,9 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
}
else {
items = isize/(sizeof(struct inotify_event));
#ifdef UWSGI_DEBUG
uwsgi_log("inotify returned %d items\n", items);
#endif
for(j=0;j<items;j++) {
iie = &bie[j];
for(i=0;i<ushared->files_monitored_cnt;i++) {
@@ -640,6 +673,8 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#endif
#endif
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
@@ -670,13 +705,23 @@ enum
static int timerfd_create (clockid_t __clock_id, int __flags) {
#ifdef __amd64__
return syscall(283, __clock_id, __flags);
#elif defined(__i386__)
return syscall(322, __clock_id, __flags);
#else
return -1;
#endif
}
static int timerfd_settime (int __ufd, int __flags,
__const struct itimerspec *__utmr,
struct itimerspec *__otmr) {
#ifdef __amd64__
return syscall(286, __ufd, __flags, __utmr, __otmr);
#elif defined(__i386__)
return syscall(325, __ufd, __flags, __utmr, __otmr);
#endif
}
#endif
@@ -748,7 +793,7 @@ int event_queue_add_timer(int eq, int *id, int sec) {
timer_id++;
pnotif.portnfy_port = eq;
pnotif.portnfy_user = (void *) timer_id;
pnotif.portnfy_user = (void *) (long) timer_id;
sigev.sigev_notify = SIGEV_PORT;
sigev.sigev_value.sival_ptr = &pnotif;
@@ -803,8 +848,6 @@ int event_queue_add_timer(int eq, int *id, int sec) {
*id = timer_id ;
timer_id++;
uwsgi_log("registering timer %d\n", sec);
EV_SET(&kev, *id, EVFILT_TIMER, EV_ADD, 0, sec*1000, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
@@ -831,3 +874,11 @@ struct uwsgi_timer *event_queue_ack_timer(int id) {
}
#endif
inline int event_queue_read() {
return UWSGI_EVENT_IN;
}
inline int event_queue_write() {
return UWSGI_EVENT_OUT;
}
+7
View File
@@ -0,0 +1,7 @@
use POSIX;
open CONFIG,'welcome.ini';
dup2(fileno(CONFIG), 17);
exec './uwsgi','--ini','fd://17';
+27 -1
View File
@@ -2,10 +2,36 @@ require 'fiber'
class SuspendingBody
def each
for i in 1..10
for i in 1..3
yield "number: #{i}\n"
UWSGI.async_sleep(1)
puts "sleep..."
Fiber.yield
end
fd = UWSGI.async_connect("81.174.68.52:80")
UWSGI.wait_fd_write(fd, 3)
Fiber.yield
io = IO.new(fd)
puts "connected"
io.syswrite("GET /uwsgi/export/1081%3A362d695b2f25/plugins/fiber/fiber.c HTTP/1.0\r\n")
io.syswrite("Host: projects.unbit.it\r\n")
io.syswrite("\r\n")
UWSGI.wait_fd_read(fd, 3)
Fiber.yield
puts "data available"
begin
while body = io.sysread(fd)
yield body
Fiber.yield
end
rescue
end
io.close
end
end
+12
View File
@@ -0,0 +1,12 @@
from flask import Flask, request
app = Flask(__name__)
app.debug = True
@app.route('/')
def hello_world():
return "<form method='POST' enctype='multipart/form-data' action='/upload'><input type='text' name='pippo'/><input type='file' name='ufile'/><input type='submit' value='upload'/></form>"
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
return str(len(request.form.get('pippo', 'boh'))) + request.form.get('pippo', 'boh')
return request.files['ufile'].read()
+108 -74
View File
@@ -2,121 +2,155 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_gateway *register_fat_gateway(char *name, void (*loop)(void)) {
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(int)) {
struct uwsgi_gateway *ug;
int num=1,i;
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
if (ushared->gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<uwsgi.gateways_cnt;i++) {
if (!strcmp(name, uwsgi.gateways[i].name)) {
for(i=0;i<ushared->gateways_cnt;i++) {
if (!strcmp(name, ushared->gateways[i].name)) {
num++;
}
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
ug = &ushared->gateways[ushared->gateways_cnt];
ug->pid = 0;
ug->name = name;
ug->loop = loop;
ug->num = num;
ug->fullname = fullname;
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
uwsgi_error("socketpair()");
}
if (!uwsgi.master_process)
gateway_respawn(ushared->gateways_cnt);
ushared->gateways_cnt++;
uwsgi.gateways_cnt++;
return ug;
}
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
pid_t gw_pid;
pid_t orig_pid = getpid();
struct uwsgi_gateway *ug;
int num=1,i;
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<uwsgi.gateways_cnt;i++) {
if (!strcmp(name, uwsgi.gateways[i].name)) {
num++;
}
}
gw_pid = fork();
if (gw_pid < 0) {
uwsgi_error("fork()");
return NULL;
}
if (!uwsgi.master_process) {
if (gw_pid > 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = orig_pid;
}
else {
if (gw_pid == 0) {
if (uwsgi.master_as_root) uwsgi_as_root();
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = gw_pid;
}
ug->name = name;
ug->loop = loop;
ug->num = num;
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
uwsgi.gateways_cnt++;
return ug;
}
void gateway_respawn(int id) {
pid_t gw_pid;
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
struct uwsgi_gateway *ug = &ushared->gateways[id];
if (uwsgi.master_process)
uwsgi.shared->gateways_harakiri[id] = 0;
gw_pid = fork();
gw_pid = uwsgi_fork(ug->fullname);
if (gw_pid < 0) {
uwsgi_error("fork()");
return;
}
if (gw_pid == 0) {
uwsgi_fixup_fds(0, 0, ug);
if (uwsgi.master_as_root) uwsgi_as_root();
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
ug->loop();
uwsgi.mypid = getpid();
signal(SIGALRM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
signal(SIGTERM, end_me);
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
ug->loop(id);
// never here !!! (i hope)
exit(1);
}
ug->pid = gw_pid;
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
ug->respawns++;
if (ug->respawns == 1) {
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
else {
uwsgi_log( "respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
}
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *name, char *owner) {
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
uwsgi_sock = uwsgi.gateway_sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
uwsgi_sock->fd = -1;
uwsgi_sock->shared = 0;
uwsgi_sock->name = name;
uwsgi_sock->owner = owner;
return uwsgi_sock;
}
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int fd, char *owner) {
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
uwsgi_sock = uwsgi.gateway_sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
uwsgi_sock->fd = fd;
uwsgi_sock->name = uwsgi_getsockname(fd);
uwsgi_sock->owner = owner;
return uwsgi_sock;
}
void uwsgi_gateway_go_cheap(char *gw_id, int queue, int *i_am_cheap) {
uwsgi_log("[%s pid %d] no more nodes available. Going cheap...\n", gw_id, (int) uwsgi.mypid);
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
event_queue_del_fd(queue, ugs->fd, event_queue_read());
}
ugs = ugs->next;
}
*i_am_cheap = 1;
}
+27
View File
@@ -0,0 +1,27 @@
[uwsgi]
master = true
processes = 4
threads = 8
; initialize 4 sockets with 4 different protocols
socket = :3031
socket = :3032
socket = :3033
socket = :3034
socket-protocol = 0,uwsgi
socket-protocol = 1,http
socket-protocol = 2,fastcgi
socket-protocol = 3,uwsgidump
; add a cache with 1000 items of 96k
cache = 1000
cache-blocksize = 98304
log-micros = true
module = heavytest
mount = /cc=uwsgicc/__init__.py
+14
View File
@@ -0,0 +1,14 @@
import uwsgi
import werkzeug.testapp
uwsgi.cache_set("/cache/get", "HTTP 1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>I am the uWSGI cache</h1>")
def app001(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return "PATH_INFO=%s" % env['PATH_INFO']
def app002(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return "requests: %d" % uwsgi.total_requests()
uwsgi.applications = { '':werkzeug.testapp.test_app, '/app001':app001, '/app002':app002 }
+23
View File
@@ -0,0 +1,23 @@
import uwsgi
if uwsgi.loop == 'gevent':
import gevent
print uwsgi.version
print uwsgi.workers()
try:
uwsgi.cache_set('foo', "Hello World from cache")
except:
pass
def application(env, start_response):
if uwsgi.loop == 'gevent':
gevent.sleep()
start_response('200 OK', [('Content-Type', 'text/html')])
yield "foobar<br/>"
if uwsgi.loop == 'gevent':
gevent.sleep(3)
yield str(env['wsgi.input'].fileno())
yield "<h1>Hello World</h1>"
try:
yield uwsgi.cache_get('foo')
except:
pass
+25
View File
@@ -0,0 +1,25 @@
uWSGI version <b><?=uwsgi_version()?></b><br/>
workerd id: <b><?=uwsgi_worker_id()?></b><br/>
master pid: <b><?=uwsgi_masterpid()?></b><br/>
uri: <b><?= $_SERVER['REQUEST_URI'] ?></b><br/>
docroot: <b><?= $_SERVER['DOCUMENT_ROOT'] ?></b><br/>
PATH_INFO: <b><?= $_SERVER['PATH_INFO'] ?></b><br/>
<? uwsgi_signal(17) ?>
<? uwsgi_setprocname("test test test"); ?>
rpc result:<br/>
<? echo uwsgi_rpc("", "hello", "one", "two", "three"); ?>
<?
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
uwsgi_cache_update('foobar', $_POST['cache_val']);
}
?>
<form method="POST">
<input type="text" name="cache_val" value="<?=uwsgi_cache_get('foobar')?>"/>
<input type="submit" value="cache set" />
</form>
+24 -31
View File
@@ -14,7 +14,7 @@ void ini_rstrip(char *line) {
off_t i;
for(i = strlen(line)-1;i>=0; i--) {
if (line[i] == ' ' || line[i] == '\t') {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
line[i] = 0;
continue;
}
@@ -28,7 +28,7 @@ char *ini_lstrip(char *line) {
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
if (line[i] == ' ' || line[i] == '\t') {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
}
@@ -67,6 +67,11 @@ char *ini_get_line(char *ini, off_t size) {
}
}
// check if it is a stupid file without \n at the end
if (ptr > ini) {
return ptr;
}
return NULL;
}
@@ -84,11 +89,17 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
int lines = 1;
struct option *lopt, *aopt;
char *section_asked = "uwsgi";
char *colon;
colon = uwsgi_get_last_char(file, ':');
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
@@ -96,7 +107,9 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
}
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
if (file[0] != 0) {
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
}
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
@@ -126,32 +139,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
lopt = uwsgi.long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(key, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
add_exported_option(0, (char *)key);
}
else {
if (aopt->has_arg == optional_argument) {
if (!strcmp("true", val)) {
val = NULL;
}
}
if (aopt->has_arg == no_argument) {
if (!strcmp("false", val) || val[0] == '0') {
lopt++;
continue;
}
}
manage_opt(aopt->val, val);
}
}
lopt++;
}
add_exported_option((char *)key, val, 0);
}
}
}
@@ -162,6 +150,11 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
if (colon) {
colon[0] = ':';
}
}
#endif
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>it.unbit.uwsgi.emperor</string>
<key>ProgramArguments</key>
<array>
<string>/Users/roberta/uwsgi/uwsgi</string>
<string>--emperor</string>
<string>/Users/*/Library/uwsgi/*.{xml,ini,yml,yaml,js}</string>
</array>
</dict>
</plist>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>it.unbit.uwsgi</string>
<key>ProgramArguments</key>
<array>
<string>/Users/roberta/uwsgi/uwsgi</string>
<string>--socket</string>
<string>:3032</string>
<string>--module</string>
<string>welcome</string>
<string>--master</string>
<string>--die-on-term</string>
</array>
</dict>
</plist>
+111
View File
@@ -0,0 +1,111 @@
#ifdef UWSGI_JSON
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#include <jansson.h>
/*
I really love the jansson library...
*/
void uwsgi_json_config(char *file, char *magic_table[]) {
int len = 0;
char *json_data;
const char *key;
json_t *root;
json_error_t error;
json_t *config;
json_t *config_value, *config_array_item;
void *config_iter;
char *object_asked = "uwsgi";
char *colon;
int i;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
object_asked = colon+1;
}
}
uwsgi_log("[uWSGI] getting JSON configuration from %s\n", file);
json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
#ifdef JANSSON_MAJOR_VERSION
root = json_loads(json_data, 0, &error);
#else
root = json_loads(json_data, &error);
#endif
if (!root) {
uwsgi_log("error parsing JSON data: line %d %s\n", error.line, error.text);
exit(1);
}
config = json_object_get(root, object_asked);
if (!json_is_object(config)) {
uwsgi_log("you must define a object named %s in your JSON data\n", object_asked);
exit(1);
}
config_iter = json_object_iter(config);
while(config_iter) {
key = json_object_iter_key(config_iter);
config_value = json_object_iter_value(config_iter);
if (json_is_string(config_value)) {
add_exported_option((char *)key, (char *) json_string_value(config_value), 0);
}
else if (json_is_true(config_value)) {
add_exported_option((char *)key, strdup("1"), 0);
}
else if (json_is_false(config_value) || json_is_null(config_value)) {
add_exported_option((char *)key, strdup("0"), 0);
}
else if (json_is_integer(config_value)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_value)), 0);
}
else if (json_is_array(config_value)) {
for(i=0;i<(int)json_array_size(config_value);i++) {
config_array_item = json_array_get(config_value, i);
if (json_is_string(config_array_item)) {
add_exported_option((char *)key, (char *) json_string_value(config_array_item), 0);
}
else if (json_is_true(config_array_item)) {
add_exported_option((char *)key, strdup("1"), 0);
}
else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
add_exported_option((char *)key, strdup("0"), 0);
}
else if (json_is_integer(config_array_item)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
}
}
}
config_iter = json_object_iter_next(config, config_iter);
}
}
#endif
+176 -120
View File
@@ -6,6 +6,14 @@ extern struct uwsgi_server uwsgi;
#include <ldap.h>
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
#ifndef ldap_unbind_ext_s
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
@@ -37,71 +45,143 @@ int calc_ldap_name(char *name) {
return strlen(name) + counter;
}
void uwsgi_ldap_schema_dump_ldif() {
struct option *aopt, *lopt;
struct uwsgi_ldap_entry {
int num;
char names[1024];
int has_arg;
};
void uwsgi_name_to_ldap(char *src, char *dst) {
lopt = uwsgi.long_options;
int i;
int counter = 30000;
char *ptr = dst;
memset(dst, 0, 1024);
strcat(dst, " 'uWSGI");
ptr+= 7;
for(i=0;i< (int)strlen(src);i++) {
if (src[i] == '-') {
i++;
*ptr++= toupper( (int) src[i]);
}
else {
*ptr++= src[i];
}
}
strcat(dst, "'");
}
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (uwsgi_list_has_str(ule->names, name+1)) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct uwsgi_option *op = uwsgi.options;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
*count = 0;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*uwsgi_count_options(op));
while( op && op->name ) {
uwsgi_name_to_ldap((char *)op->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry) goto next;
entry = &ule[*count] ;
entry->num = *count;
strcpy(entry->names, ldap_name);
*count = *count+1;
entry->has_arg = op->type;
next:
op++;
}
return ule;
}
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
int i;
int items;
uwsgi_log("\n");
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
uwsgi_log("objectClass: olcSchemaConfig\n");
uwsgi_log("cn: uwsgi\n");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
if (aopt->flag) {
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter);
counter++;
for(i=0;i<items;i++) {
entry = &ule[i];
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val);
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
if (aopt->has_arg) {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
lopt++;
}
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
lopt = uwsgi.long_options;
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
for(i=0;i<items;i++) {
uwsgi_log("uWSGI");
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
uwsgi_log(" $ ");
lopt++;
}
uwsgi_log("uWSGInull ))\n");
@@ -111,75 +191,55 @@ void uwsgi_ldap_schema_dump_ldif() {
exit(0);
}
void uwsgi_ldap_schema_dump() {
struct option *aopt, *lopt;
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
lopt = uwsgi.long_options;
int i;
int counter = 30000;
int items;
while( (aopt = lopt) ) {
if (!aopt->name)
break;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
if (aopt->flag) {
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter);
counter++;
}
else {
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val);
}
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
if (aopt->has_arg) {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
lopt++;
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
lopt = uwsgi.long_options;
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
for(i=0;i<items;i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGI");
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
uwsgi_log(" $ ");
lopt++;
}
uwsgi_log("uWSGInull ))\n");
exit(0);
}
void uwsgi_ldap_config() {
void uwsgi_ldap_config(char *url) {
LDAP *ldp;
LDAPMessage *results, *entry;
@@ -188,20 +248,13 @@ void uwsgi_ldap_config() {
char *attr;
char *uwsgi_attr;
char *url = "ldap:///";
char *url_slash;
int desired_version = LDAP_VERSION3;
int ret;
struct option *aopt, *lopt;
LDAPURLDesc *ldap_url;
if (uwsgi.ldap) {
url = uwsgi.ldap;
}
if (!ldap_is_ldap_url(url)) {
uwsgi_log("invalid LDAP url.\n");
exit(1);
@@ -211,6 +264,8 @@ void uwsgi_ldap_config() {
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
url_slash = strchr(url, '/');
url_slash = strchr(url_slash + 1, '/');
@@ -225,10 +280,17 @@ void uwsgi_ldap_config() {
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
#endif
#if LDAP_API_VERSION >= 3000
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ( (ldp = ldap_init( ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
@@ -255,9 +317,11 @@ void uwsgi_ldap_config() {
entry = ldap_first_entry(ldp, results);
int found = 0;
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr,"uWSGI",5)) {
found = 1;
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
if (!uwsgi_attr) {
uwsgi_error("malloc()");
@@ -271,7 +335,7 @@ void uwsgi_ldap_config() {
#endif
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_val;
// do not free uwsgi_attr/uwsgi_val;
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
if (!uwsgi_val) {
uwsgi_error("malloc()");
@@ -281,29 +345,21 @@ void uwsgi_ldap_config() {
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
lopt = uwsgi.long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(uwsgi_attr, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
add_exported_option(0, (char*) uwsgi_attr);
}
else {
manage_opt(aopt->val, uwsgi_val);
}
}
lopt++;
}
add_exported_option((char*) uwsgi_attr, uwsgi_val, 0);
free(bervalues);
}
else {
free(uwsgi_attr);
}
free(bervalues);
free(uwsgi_attr);
}
free(attr);
}
if (!found) {
uwsgi_log("no uWSGI LDAP entry found\n");
exit(1);
}
free(ber);
free(results);
+775
View File
@@ -0,0 +1,775 @@
#include "../uwsgi.h"
#define AMQP_CONNECTION_HEADER "AMQP\0\0\x09\x01"
#ifdef __BIG_ENDIAN__
#define ntohll(x) x
#else
#define ntohll(x) ( ( (uint64_t)(ntohl( (uint32_t)((x << 32) >> 32) )) << 32) | ntohl( ((uint32_t)(x >> 32)) ) )
#endif
#define htonll(x) ntohll(x)
#define amqp_send(a, b, c) if (send(a, b, c, 0) < 0) { uwsgi_error("send()"); return -1; }
struct amqp_frame_header {
char type;
uint16_t channel;
uint32_t size;
} __attribute__((__packed__));
struct amqp_frame_method {
uint16_t class_id;
uint16_t method_id;
} __attribute__((__packed__));
static char *amqp_simple_get_frame(int, struct amqp_frame_header *);
static char *amqp_get_method(int, uint16_t, uint16_t, uint32_t *);
static char *amqp_get_str(char *ptr, char *watermark) {
uint8_t str_size;
// over engeneering...
if (ptr+1 > watermark) return NULL;
str_size = *ptr;
if (ptr+1+str_size > watermark) return NULL;
return ptr+1+str_size;
}
static char *amqp_get_short(char *ptr, char *watermark, uint16_t *sv) {
uint16_t tmp_short;
if (ptr+2 > watermark) return NULL;
memcpy(&tmp_short, ptr, 2);
*sv = ntohs(tmp_short);
return ptr+2;
}
static char *amqp_get_long(char *ptr, char *watermark, uint32_t *lv) {
uint32_t tmp_long;
if (ptr+4 > watermark) return NULL;
memcpy(&tmp_long, ptr, 4);
*lv = ntohl(tmp_long);
return ptr+4;
}
static char *amqp_get_longlong(char *ptr, char *watermark, uint64_t *llv) {
uint64_t tmp_longlong;
if (ptr+8 > watermark) return NULL;
memcpy(&tmp_longlong, ptr, 8);
*llv = ntohll(tmp_longlong);
return ptr+8;
}
static int amqp_send_ack(int fd, uint64_t delivery_tag) {
uint32_t size = 4 + 8 + 1;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 60 method 80
amqp_send(fd, "\x00\x3C\x00\x50", 4);
// set delivery_tag
delivery_tag = htonll(delivery_tag);
amqp_send(fd, &delivery_tag, 8);
// empty bits
amqp_send(fd, "\0", 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
uint32_t size;
struct amqp_frame_header fh;
uint64_t delivery_tag;
uint64_t current_size = 0;
char *ptr;
char *watermark;
uint16_t sv;
char *frame = amqp_get_method(fd, 60, 60, &size);
if (!frame) return NULL;
ptr = frame+4;
watermark = frame+size;
// consumer_tag
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
// delivery_tag (needed for ack)
ptr = amqp_get_longlong(ptr, watermark, &delivery_tag); if (!ptr) goto clear;
// redelivered
if (ptr+1 > watermark) goto clear;
ptr++;
// exchange
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
// routing_key
if (ptr+1 > watermark) goto clear;
uint8_t rk_size = (uint8_t) *ptr;
ptr++;
if (ptr+rk_size > watermark) goto clear;
if (rk_size > 0) {
char *rkey = uwsgi_concat2n(ptr, rk_size, "", 0);
ptr+=rk_size;
*routing_key = rkey;
}
else {
*routing_key = NULL;
}
char *header = amqp_simple_get_frame(fd, &fh);
if (!header) goto clear;
if (fh.type != 2) goto clear2;
ptr = header;
watermark = ptr+fh.size;
// header class_id
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
// header weight
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
// message size;
ptr = amqp_get_longlong(ptr, watermark, msgsize); if (!ptr) goto clear2;
free(frame);
frame = NULL;
free(header);
header = NULL;
char *fullbody = uwsgi_malloc(*msgsize);
char *message;
while(current_size < *msgsize) {
message = amqp_simple_get_frame(fd, &fh);
if (!message) goto clear;
if (fh.type != 3) {
free(message);
goto clear3;
}
if (fh.size+current_size > *msgsize) {
free(message);
goto clear3;
}
memcpy(fullbody+current_size, message, fh.size);
current_size+=fh.size;
free(message);
}
if (amqp_send_ack(fd, delivery_tag) < 0) {
goto clear3;
}
return fullbody;
clear3:
free(fullbody);
return NULL;
clear2:
free(header);
clear:
free(frame);
return NULL;
}
static int amqp_send_exchange_declare( int fd, char *exchange, char *exchange_type) {
uint32_t size = 4 + 2 + (1 +strlen(exchange)) + (1 +strlen(exchange_type)) + 1 + 4;
uint8_t shortsize = strlen(exchange) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 40 method 10
amqp_send(fd, "\x00\x28\x00\x0A", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set exchange name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange, shortsize);
// set exchange type
shortsize = strlen(exchange_type);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange_type, shortsize);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_bind( int fd, char *queue, char *exchange) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + (1 +strlen(exchange)) + 1 + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 50 method 20
amqp_send(fd, "\x00\x32\x00\x14", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// set exchange name
shortsize = strlen(exchange);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange, shortsize);
// set empty routing-key
amqp_send(fd, "\0", 1);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_consume( int fd, char *queue) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 60 method 20
amqp_send(fd, "\x00\x3C\x00\x14", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// set tag name
amqp_send(fd, "\0", 1);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_wait_connection_start(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 10, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_exchange_declare_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 40, 11, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_basic_consume_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 60, 21, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_channel_open_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 20, 11, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_queue_bind_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 50, 21, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static char *amqp_wait_queue_declare_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 50, 11, &size);
char *queue = NULL;
char *ptr;
char *watermark;
if (frame) {
ptr = frame+4;
watermark = frame+size;
ptr = amqp_get_str(ptr, watermark); if (!ptr) { free(frame); return NULL; }
queue = uwsgi_concat2n(frame+5, *(frame+4), "", 0);
free(frame);
return queue;
}
return NULL;
}
static int amqp_wait_connection_open_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 41, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_connection_tune(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 30, &size);
uint16_t sv;
uint32_t lv;
char *watermark ;
char *ptr;
if (frame) {
ptr = frame+4;
watermark = frame+size;
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP max channels: %d\n", sv);
ptr = amqp_get_long(ptr, watermark, &lv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP max frame size: %d\n", lv);
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP heartbeath: %d\n", sv);
free(frame);
return 0;
}
return -1;
}
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
char *ptr = (char *) fh;
size_t len = 0, rlen;
while(len < 7) {
rlen = recv(fd, ptr, 7-len, 0);
if (rlen <= 0) {
uwsgi_error("recv()");
return NULL;
}
len += rlen;
ptr += rlen;
}
fh->channel = ntohs(fh->channel);
fh->size = ntohl(fh->size);
len = 0;
char *frame = uwsgi_malloc(fh->size+1);
ptr = frame;
while(len < fh->size+1) {
rlen = recv(fd, ptr, (fh->size+1)-len, 0);
if (rlen <= 0) {
uwsgi_error("recv()");
return NULL;
}
len += rlen;
ptr += rlen;
}
return frame;
}
static char *amqp_get_method(int fd, uint16_t class_id, uint16_t method_id, uint32_t *size) {
struct amqp_frame_header fh;
struct amqp_frame_method *fm;
char *frame = amqp_simple_get_frame(fd, &fh);
if (!frame) return NULL;
if (fh.type != 1) goto clear;
fm = (struct amqp_frame_method *) frame;
fm->class_id = ntohs(fm->class_id);
fm->method_id = ntohs(fm->method_id);
if (fm->class_id != class_id) goto clear;
if (fm->method_id != method_id) goto clear;
*size = fh.size;
return frame;
clear:
free(frame);
return NULL;
}
static int amqp_send_channel_open(int fd, uint16_t id) {
uint32_t size = 4 + 1;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 20 method 10
amqp_send(fd, "\x00\x14\x00\x0A", 4);
amqp_send(fd, "\0", 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int amqp_send_connection_open(int fd, char *vhost) {
uint8_t shortsize = strlen(vhost);
uint32_t size = 4 + 1 +strlen(vhost) + 2;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 28
amqp_send(fd, "\x00\x0A\x00\x28", 4);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, vhost, strlen(vhost));
shortsize = 0;
amqp_send(fd, &shortsize, 1);
amqp_send(fd, &shortsize, 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int amqp_send_connection_tune_ok(int fd, uint16_t max_chan, uint32_t max_frame_size, uint16_t heartbeat) {
uint32_t size = 4 + 2 + 4 + 2;
size = htonl(size);
max_chan = htons(max_chan);
max_frame_size = htonl(max_frame_size);
heartbeat = htons(heartbeat);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 15
amqp_send(fd, "\x00\x0A\x00\x1F", 4);
amqp_send(fd, &max_chan, 2);
amqp_send(fd, &max_frame_size, 4);
amqp_send(fd, &heartbeat, 2);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_declare(int fd, char *queue) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 50 method 10
amqp_send(fd, "\x00\x32\x00\x0A", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static char *amqp_get_queue(int fd, char *queue) {
if (amqp_send_queue_declare(fd, queue) < 0) {
return NULL;
}
return amqp_wait_queue_declare_ok(fd);
}
static int amqp_send_connection_start_ok(int fd, char *mech, char *sasl_response, int sasl_response_size, char *locale) {
uint32_t size = 4 + 4 + (1 +strlen(mech)) + (4 + sasl_response_size) + (1 + strlen(locale));
uint8_t shortsize ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 11
amqp_send(fd, "\x00\x0A\x00\x0B", 4);
// send empty client properties
amqp_send(fd, "\0\0\0\0", 4);
// send mechanism short string
shortsize = strlen(mech);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, mech, strlen(mech));
// send sasl response
size = htonl(sasl_response_size);
amqp_send(fd, &size, 4);
amqp_send(fd, sasl_response, sasl_response_size);
// send locale
shortsize = strlen(locale);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, locale, strlen(locale));
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int uwsgi_amqp_consume_queue(int fd, char *vhost, char *username, char *password, char *queue, char *exchange, char *exchange_type) {
char *auth = uwsgi_concat4n("\0",1, username, strlen(username), "\0",1, password, strlen(password));
if (send(fd, AMQP_CONNECTION_HEADER, 8, 0) < 0) {
uwsgi_error("send()");
return -1;
}
if (amqp_wait_connection_start(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.start\n");
return -1;
}
uwsgi_log("sending Connection.start-ok\n");
if (amqp_send_connection_start_ok(fd, "PLAIN", auth, strlen(username)+strlen(password)+2, "en_US") < 0) {
free(auth);
uwsgi_log("AMQP error sending Connection.start-ok\n");
return -1;
}
free(auth);
if (amqp_wait_connection_tune(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.tune\n");
return -1;
}
uwsgi_log("sending Connection.tune-ok\n");
if (amqp_send_connection_tune_ok(fd, 0, 0xffff, 0) < 0) {
uwsgi_log("AMQP error sending Connection.tune-ok\n");
return -1;
}
uwsgi_log("sending Connection.open\n");
if (amqp_send_connection_open(fd, vhost) < 0) {
uwsgi_log("AMQP error sending Connection.open\n");
return -1;
}
if (amqp_wait_connection_open_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.open-ok\n");
return -1;
}
uwsgi_log("sending Channel.open\n");
if (amqp_send_channel_open(fd, 1) < 0) {
uwsgi_log("AMQP error sending Channel.open\n");
return -1;
}
if (amqp_wait_channel_open_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Channel.open-ok\n");
return -1;
}
queue = amqp_get_queue(fd, queue);
if (!queue) {
uwsgi_log("AMQP error sending Queue.declare\n");
return -1;
}
if (exchange) {
if (amqp_send_exchange_declare(fd, exchange, exchange_type) < 0) {
uwsgi_log("AMQP error sending Exchange.declare\n");
free(queue);
return -1;
}
if (amqp_wait_exchange_declare_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Exchange.declare-ok\n");
free(queue);
return -1;
}
if (amqp_send_queue_bind(fd, queue, exchange) < 0) {
uwsgi_log("AMQP error sending Queue.bind\n");
free(queue);
return -1;
}
if (amqp_wait_queue_bind_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Queue.bind-ok\n");
free(queue);
return -1;
}
}
if (amqp_send_queue_consume(fd, queue) < 0) {
uwsgi_log("AMQP error sending Basic.consume\n");
free(queue);
return -1;
}
if (amqp_wait_basic_consume_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Basic.consume-ok\n");
free(queue);
return -1;
}
free(queue);
uwsgi_log("AMQP subscription done, waiting for events...\n");
return 0;
}
+202
View File
@@ -0,0 +1,202 @@
/*
common functions for various routers (fastrouter, http...)
*/
static void uwsgi_corerouter_setup_sockets(char *gw_id) {
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(gw_id, ugs->owner)) {
#ifdef UWSGI_SCTP
if (!ugs->subscription && !ugs->sctp) {
#else
if (!ugs->subscription) {
#endif
if (ugs->name[0] == '=') {
int shared_socket = atoi(ugs->name+1);
if (shared_socket >= 0) {
ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
ugs->shared = 1;
if (ugs->fd == -1) {
uwsgi_log("unable to use shared socket %d\n", shared_socket);
exit(1);
}
ugs->name = uwsgi_getsockname(ugs->fd);
}
}
else if (!uwsgi_startswith("fd://", ugs->name, 5 )) {
int fd_socket = atoi(ugs->name+5);
if (fd_socket >= 0) {
ugs->fd = fd_socket;
ugs->name = uwsgi_getsockname(ugs->fd);
if (!ugs->name) {
uwsgi_log("unable to use file descriptor %d as socket\n", fd_socket);
exit(1);
}
}
}
else {
ugs->port = strchr(ugs->name, ':');
if (ugs->fd == -1) {
if (ugs->port) {
ugs->fd = bind_to_tcp(ugs->name, uwsgi.listen_queue, ugs->port);
ugs->port++;
ugs->port_len = strlen(ugs->port);
}
else {
ugs->fd = bind_to_unix(ugs->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
}
}
// put socket in non-blocking mode
uwsgi_socket_nb(ugs->fd);
uwsgi_log("%s bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
}
else if (ugs->subscription) {
if (ugs->fd == -1) {
ugs->fd = bind_to_udp(ugs->name, 0, 0);
uwsgi_socket_nb(ugs->fd);
}
uwsgi_log("%s subscription server bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
}
#ifdef UWSGI_SCTP
else if (ugs->sctp) {
if (ugs->fd == -1) {
ugs->fd = bind_to_sctp(ugs->name);
}
uwsgi_log("%s SCTP server bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
}
#endif
}
ugs = ugs->next;
}
}
static void *uwsgi_corerouter_setup_event_queue(char *gw_id, int id, int nevents, int *efd, int cheap) {
*efd = event_queue_init();
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(gw_id, ugs->owner)) {
if (!cheap || ugs->subscription) {
event_queue_add_fd_read(*efd, ugs->fd);
}
ugs->gateway = &ushared->gateways[id];
}
ugs = ugs->next;
}
return event_queue_alloc(nevents);
}
static void __attribute__ ((unused)) uwsgi_corerouter_manage_subscription(char *gw_id, int id, struct uwsgi_gateway_socket *ugs, int queue, struct uwsgi_subscribe_slot **subscriptions, int regexp, void (*parse_hook) (char *, uint16_t, char *, uint16_t, void *), int cheap, int *i_am_cheap) {
int i;
struct uwsgi_subscribe_req usr;
char bbuf[4096];
ssize_t len = recv(ugs->fd, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(queue, ugs->fd);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf + 4, len - 4, parse_hook, &usr);
// subscribe request ?
if (bbuf[3] == 0) {
if (uwsgi_add_subscribe_node(subscriptions, &usr, regexp) && *i_am_cheap) {
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
event_queue_add_fd_read(queue, ugs->fd);
}
ugs = ugs->next;
}
*i_am_cheap = 0;
uwsgi_log("[%s pid %d] leaving cheap mode...\n", gw_id, (int) uwsgi.mypid);
}
}
//unsubscribe
else {
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, regexp);
if (node && node->len) {
if (node->death_mark == 0)
uwsgi_log("[%s pid %d] %.*s => marking %.*s as failed\n", gw_id, (int) uwsgi.mypid, (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
node->failcnt++;
node->death_mark = 1;
// check if i can remove the node
if (node->reference == 0) {
uwsgi_remove_subscribe_node(subscriptions, node);
}
if (*subscriptions == NULL && cheap && !*i_am_cheap) {
uwsgi_gateway_go_cheap(gw_id, queue, i_am_cheap);
}
}
}
// propagate the subscription to other nodes
for (i = 0; i < ushared->gateways_cnt; i++) {
if (i == id)
continue;
if (!strcmp(ushared->gateways[i].name, gw_id)) {
if (send(ushared->gateways[i].internal_subscription_pipe[0], bbuf, len, 0) != len) {
uwsgi_error("send()");
}
}
}
}
}
static void __attribute__ ((unused)) uwsgi_corerouter_manage_internal_subscription(char *gw_id, int queue, int fd, struct uwsgi_subscribe_slot **subscriptions, int regexp, void (*parse_hook) (char *, uint16_t, char *, uint16_t, void *), int cheap, int *i_am_cheap) {
struct uwsgi_subscribe_req usr;
char bbuf[4096];
ssize_t len = recv(fd, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(queue, fd);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf + 4, len - 4, parse_hook, &usr);
// subscribe request ?
if (bbuf[3] == 0) {
if (uwsgi_add_subscribe_node(subscriptions, &usr, regexp) && *i_am_cheap) {
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
event_queue_add_fd_read(queue, ugs->fd);
}
ugs = ugs->next;
}
*i_am_cheap = 0;
uwsgi_log("[%s pid %d] leaving cheap mode...\n", gw_id, (int) uwsgi.mypid);
}
}
//unsubscribe
else {
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, regexp);
if (node && node->len) {
if (node->death_mark == 0)
uwsgi_log("[%s pid %d] %.*s => marking %.*s as failed\n", gw_id, (int) uwsgi.mypid, (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
node->failcnt++;
node->death_mark = 1;
// check if i can remove the node
if (node->reference == 0) {
uwsgi_remove_subscribe_node(subscriptions, node);
}
if (*subscriptions == NULL && cheap && !*i_am_cheap) {
uwsgi_gateway_go_cheap(gw_id, queue, i_am_cheap);
}
}
}
}
}
+165
View File
@@ -0,0 +1,165 @@
#include "../uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifndef CLONE_NEWUTS
#define CLONE_NEWUTS 0x04000000
#endif
#ifndef CLONE_NEWPID
#define CLONE_NEWPID 0x20000000
#endif
#ifndef CLONE_NEWIPC
#define CLONE_NEWIPC 0x08000000
#endif
#ifndef CLONE_NEWNET
#define CLONE_NEWNET 0x40000000
#endif
void linux_namespace_start(void *argv) {
for (;;) {
char stack[PTHREAD_STACK_MIN];
int waitpid_status;
uwsgi_log("*** jailing uWSGI in %s ***\n", uwsgi.ns);
int clone_flags = SIGCHLD | CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS;
if (uwsgi.ns_net) {
clone_flags |= CLONE_NEWNET;
}
pid_t pid = clone(uwsgi_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
if (pid == -1) {
uwsgi_error("clone()");
exit(1);
}
// run the post-jail scripts
if (setenv("UWSGI_JAIL_PID", uwsgi_num2str((int) pid), 1)) {
uwsgi_error("setenv()");
}
struct uwsgi_string_list *usl = uwsgi.exec_post_jail;
while(usl) {
uwsgi_log("running \"%s\" (post-jail)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
usl = usl->next;
}
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
pid = waitpid(pid, &waitpid_status, 0);
if (pid < 0) {
uwsgi_error("waitpid()");
exit(1);
}
// in Linux this is reliable
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == 1) {
exit(1);
}
uwsgi_log("pid %d ended. Respawning...\n", (int) pid);
}
// never here
}
void linux_namespace_jail() {
char *ns_tmp_mountpoint = NULL, *ns_tmp_mountpoint2 = NULL;
if (getpid() != 1) {
uwsgi_log("your kernel does not support linux pid namespace\n");
exit(1);
}
char *ns_hostname = strchr(uwsgi.ns, ':');
if (ns_hostname) {
ns_hostname[0] = 0;
ns_hostname++;
if (sethostname(ns_hostname, strlen(ns_hostname))) {
uwsgi_error("sethostname()");
}
}
FILE *procmounts;
char line[1024];
int unmounted = 1;
char *delim0, *delim1;
if (chdir(uwsgi.ns)) {
uwsgi_error("chdir()");
exit(1);
}
if (strcmp(uwsgi.ns, "/")) {
ns_tmp_mountpoint = uwsgi_concat2(uwsgi.ns, "/.uwsgi_ns_tmp_mountpoint");
mkdir(ns_tmp_mountpoint, S_IRWXU);
ns_tmp_mountpoint2 = uwsgi_concat2(ns_tmp_mountpoint, "/.uwsgi_ns_tmp_mountpoint");
mkdir(ns_tmp_mountpoint2, S_IRWXU);
if (mount(uwsgi.ns, ns_tmp_mountpoint, "none", MS_BIND, NULL)) {
uwsgi_error("mount()");
}
if (chdir(ns_tmp_mountpoint)) {
uwsgi_error("chdir()");
}
if (pivot_root(".", ns_tmp_mountpoint2)) {
uwsgi_error("pivot_root()");
exit(1);
}
if (chdir("/")) {
uwsgi_error("chdir()");
exit(1);
}
}
uwsgi_log("remounting /proc\n");
if (mount("proc", "/proc", "proc", 0, NULL)) {
uwsgi_error("mount()");
}
while (unmounted) {
unmounted = 0;
procmounts = fopen("/proc/self/mounts", "r");
while (fgets(line, 1024, procmounts) != NULL) {
delim0 = strchr(line, ' ');
delim0++;
delim1 = strchr(delim0, ' ');
*delim1 = 0;
if (!strcmp(delim0, "/") || !strcmp(delim0, "/proc"))
continue;
if (!umount(delim0)) {
unmounted++;
}
}
fclose(procmounts);
}
if (rmdir("/.uwsgi_ns_tmp_mountpoint/.uwsgi_ns_tmp_mountpoint")) {
uwsgi_error("rmdir()");
}
if (rmdir("/.uwsgi_ns_tmp_mountpoint")) {
uwsgi_error("rmdir()");
}
if (strcmp(uwsgi.ns, "/")) {
free(ns_tmp_mountpoint2);
free(ns_tmp_mountpoint);
}
}
+397
View File
@@ -0,0 +1,397 @@
#include "../uwsgi.h"
#ifdef OBSOLETE_LINUX_KERNEL
#ifndef __u16
#define __u16 u_int16_t
#endif
#ifndef __u32
#define __u32 u_int32_t
#endif
#ifndef __s32
#define __s32 int32_t
#endif
#ifndef __u8
#define __u8 u_int8_t
#endif
#endif
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#ifdef CLONE_NEWNET
#define NLMSG_TAIL(nmsg) \
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
#ifndef VETH_INFO_PEER
# define VETH_INFO_PEER 1
#endif
struct uwsgi_nl_req {
struct nlmsghdr nlmsg;
struct ifinfomsg ifinfomsg;
};
struct uwsgi_nl_ipreq {
struct nlmsghdr nlmsg;
struct ifaddrmsg ifaddrmsg;
};
struct uwsgi_nl_rtreq {
struct nlmsghdr nlmsg;
struct rtmsg rtmsg;
};
int uwsgi_nl_send(struct nlmsghdr *);
struct nlmsghdr *uwsgi_netlink_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
unr->ifinfomsg.ifi_family = AF_UNSPEC;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
nlmsg->nlmsg_type = RTM_NEWLINK;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
return nlmsg;
}
struct nlmsghdr *uwsgi_netlink_ip_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
uni->ifaddrmsg.ifa_family = AF_INET;
uni->ifaddrmsg.ifa_scope = 0;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
nlmsg->nlmsg_type = RTM_NEWADDR;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
return nlmsg;
}
struct nlmsghdr *uwsgi_netlink_rt_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
unr->rtmsg.rtm_family = AF_INET;
unr->rtmsg.rtm_table = RT_TABLE_MAIN;
unr->rtmsg.rtm_protocol = RTPROT_STATIC;
unr->rtmsg.rtm_scope = RT_SCOPE_UNIVERSE;
unr->rtmsg.rtm_type = RTN_UNICAST;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
nlmsg->nlmsg_type = RTM_NEWROUTE;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
return nlmsg;
}
int uwsgi_netlink_rt(char *src, char *dst, int dst_prefix, char *gw) {
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
struct rtattr *rta;
struct in_addr ia;
struct in_addr oa;
struct in_addr ga;
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
if (inet_pton(AF_INET, src, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
if (inet_pton(AF_INET, dst, &oa) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
if (inet_pton(AF_INET, gw, &ga) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_PREFSRC;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_DST;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &oa.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_GATEWAY;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ga.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
unr->rtmsg.rtm_src_len = 0;
unr->rtmsg.rtm_dst_len = dst_prefix;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_gw(char *iface, char *ip) {
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
struct rtattr *rta;
struct in_addr ia;
uint32_t zero = 0;
int index = if_nametoindex(iface);
if (!index) return -1;
if (inet_pton(AF_INET, ip, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_GATEWAY;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_DST;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &zero, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_OIF;
rta->rta_len = RTA_LENGTH(sizeof(int));
memcpy(RTA_DATA(rta), &index, sizeof(int));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_ip(char *iface, char *ip, int prefix) {
struct nlmsghdr *nlmsg = uwsgi_netlink_ip_alloc();
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
struct rtattr *rta;
struct in_addr ia;
int index = if_nametoindex(iface);
if (!index) return -1;
uni->ifaddrmsg.ifa_index = index;
uni->ifaddrmsg.ifa_prefixlen = prefix;
if (inet_pton(AF_INET, ip, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFA_LOCAL;
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFA_ADDRESS;
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_veth_attach(char *veth1, pid_t pid) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
struct rtattr *rta;
int index = if_nametoindex(veth1);
if (!index) return -1;
unr->ifinfomsg.ifi_index = index;
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_NET_NS_PID;
rta->rta_len = RTA_LENGTH(sizeof(pid_t));
memcpy(RTA_DATA(rta), &pid, sizeof(pid_t));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_ifup(char *iface) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
int index = if_nametoindex(iface);
if (!index) return -1;
unr->ifinfomsg.ifi_index = index;
unr->ifinfomsg.ifi_change |= IFF_UP;
unr->ifinfomsg.ifi_flags |= IFF_UP;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_del(char *iface) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
int index = if_nametoindex(iface);
if (!index) return -1;
nlmsg->nlmsg_type = RTM_DELLINK;
unr->ifinfomsg.ifi_index = index;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_veth(char *veth0, char *veth1) {
struct rtattr *rta, *rta0, *rta1, *rta2;
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
nlmsg->nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
// IFLA_LINKINFO
rta0 = NLMSG_TAIL(nlmsg);
rta0->rta_type = IFLA_LINKINFO;
rta0->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta0->rta_len);
// IFLA_INFO_KIND
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_INFO_KIND;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), "veth", 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
// IFLA_INFO_DATA
rta1 = NLMSG_TAIL(nlmsg);
rta1->rta_type = IFLA_INFO_DATA;
rta1->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta1->rta_len);
// VETH_INFO_PEER
rta2 = NLMSG_TAIL(nlmsg);
rta2->rta_type = VETH_INFO_PEER;
rta2->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta2->rta_len);
nlmsg->nlmsg_len += sizeof(struct ifinfomsg);
// IFLA_IFNAME
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_IFNAME;
rta->rta_len = RTA_LENGTH(strlen(veth1));
memcpy(RTA_DATA(rta), veth1, strlen(veth1));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta2->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta2;
rta1->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta1;
rta0->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta0;
// IFLA_IFNAME
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_IFNAME;
rta->rta_len = RTA_LENGTH(strlen(veth0));
memcpy(RTA_DATA(rta), veth0, strlen(veth0));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_nl_send(struct nlmsghdr *nlmsg) {
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = (void*)nlmsg,
.iov_len = nlmsg->nlmsg_len,
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
int ret;
int nlfd;
memset(&nladdr, 0, sizeof(struct sockaddr_nl));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (nlfd < 0) {
uwsgi_error("socket()");
free(nlmsg);
return -1;
}
ret = sendmsg(nlfd, &msg, 0);
if (ret < 0) {
uwsgi_error("sendmsg()");
free(nlmsg);
close(nlfd);
return -1;
}
ret = recvmsg(nlfd, &msg, 0);
if (ret < 0) {
uwsgi_error("recvmsg()");
free(nlmsg);
close(nlfd);
return -1;
}
if (nlmsg->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlmsg);
ret = err->error;
}
free(nlmsg);
close(nlfd);
return ret;
}
#endif
+26 -1
View File
@@ -19,12 +19,22 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../uwsgi.h"
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
struct rb_node *right = node->rb_right;
@@ -282,3 +292,18 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
#ifdef __clang__
void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#else
inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#endif
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
+8 -20
View File
@@ -18,7 +18,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -37,7 +37,6 @@ struct rb_root
struct rb_node *rb_node;
};
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(r) (!rb_color(r))
@@ -45,24 +44,13 @@ struct rb_root
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
void rb_insert_color(struct rb_node *, struct rb_root *);
void rb_erase(struct rb_node *, struct rb_root *);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
#ifdef __clang__
void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
#else
inline void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
#endif
+29
View File
@@ -0,0 +1,29 @@
/* function written by Ben Taylor (found in the qemu-devel list) */
#include "../uwsgi.h"
time_t timegm(struct tm *t) {
time_t tl, tb;
struct tm *tg;
tl = mktime (t);
if (tl == -1) {
t->tm_hour--;
tl = mktime (t);
if (tl == -1)
return -1; /* can't deal with output from strptime */
tl += 3600;
}
tg = gmtime (&tl);
tg->tm_isdst = 0;
tb = mktime (tg);
if (tb == -1) {
tg->tm_hour--;
tb = mktime (tg);
if (tb == -1)
return -1; /* can't deal with output from gmtime */
tb += 3600;
}
return (tl - (tb - tl));
}
+443 -93
View File
@@ -1,199 +1,549 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uli) {
uwsgi.registered_locks = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
uwsgi.registered_locks->id = id;
uwsgi.registered_locks->pid = 0;
if (rw) {
uwsgi.registered_locks->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
}
else {
uwsgi.registered_locks->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
}
uwsgi.registered_locks->rw = rw;
uwsgi.registered_locks->next = NULL;
return uwsgi.registered_locks;
}
while(uli) {
if (!uli->next) {
uli->next = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
if (rw) {
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
}
else {
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
}
uli->next->id = id;
uli->next->pid = 0;
uli->next->rw = rw;
uli->next->next = NULL;
return uli->next;
}
uli = uli->next;
}
uwsgi_log("*** DANGER: unable to allocate lock %s ***\n", id);
exit(1);
}
#ifdef UWSGI_LOCK_USE_MUTEX
#define UWSGI_LOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
#ifdef EOWNERDEAD
#define UWSGI_LOCK_ENGINE_NAME "pthread robust mutexes"
#else
#define UWSGI_LOCK_ENGINE_NAME "pthread mutexes"
#endif
#define UWSGI_LOCK_SIZE sizeof(pthread_mutex_t)
#ifdef OBSOLETE_LINUX_KERNEL
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutex_t)
#else
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlock_t)
#endif
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
void uwsgi_lock_init(void *lock) {
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
if (pthread_mutexattr_init((pthread_mutexattr_t *) lock)) {
pthread_mutexattr_t attr;
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
if (pthread_mutexattr_init(&attr)) {
uwsgi_log("unable to allocate mutexattr structure\n");
exit(1);
}
if (pthread_mutexattr_setpshared((pthread_mutexattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share mutex\n");
exit(1);
}
if (pthread_mutex_init((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t), (pthread_mutexattr_t *) lock)) {
#ifdef EOWNERDEAD
if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP)) {
uwsgi_log("unable to make the mutex 'robust'\n");
exit(1);
}
#endif
if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
pthread_mutexattr_destroy(&attr);
#ifndef EOWNERDEAD
uli->can_deadlock = 1;
#endif
return uli;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (pthread_mutex_trylock((pthread_mutex_t *) uli->lock_ptr) == 0 ) {
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
return uwsgi_lock_fast_check(uli);
#else
if (pthread_rwlock_trywrlock((pthread_rwlock_t *) uli->lock_ptr) == 0 ) {
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
return 0;
}
return uli->pid;
#endif
}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
#ifdef EOWNERDEAD
if (pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr) == EOWNERDEAD) {
uwsgi_log("[deadlock-detector] a process holding a robust mutex died. recovering...\n");
pthread_mutex_consistent_np((pthread_mutex_t *) uli->lock_ptr);
}
#else
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
#endif
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
uli->pid = 0;
}
void uwsgi_rlock(void *lock) {
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock_fast(uli);
#else
pthread_rwlock_rdlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
#endif
}
void uwsgi_wlock(void *lock) {
pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock_fast(uli);
#else
pthread_rwlock_wrlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
#endif
}
void uwsgi_rwunlock(void *lock) {
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_unlock_fast(uli);
#else
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = 0;
#endif
}
void uwsgi_lock(void *lock) {
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
#ifdef OBSOLETE_LINUX_KERNEL
return uwsgi_lock_fast_init(id);
#else
void uwsgi_unlock(void *lock) {
pthread_rwlockattr_t attr;
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
void uwsgi_rwlock_init(void *lock) {
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
if (pthread_rwlockattr_init(&attr)) {
uwsgi_log("unable to allocate rwlock structure\n");
exit(1);
}
if (pthread_rwlockattr_setpshared((pthread_rwlockattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
if (pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share rwlock\n");
exit(1);
}
if (pthread_rwlock_init((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t), (pthread_rwlockattr_t *) lock)) {
if (pthread_rwlock_init((pthread_rwlock_t *) uli->lock_ptr, &attr)) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
pthread_rwlockattr_destroy(&attr);
uli->can_deadlock = 1;
return uli;
#endif
}
#endif
#elif defined(UWSGI_LOCK_USE_UMTX)
#ifdef UWSGI_LOCK_USE_UMTX
/* Warning: FreeBSD is still not ready for process-shared UMTX */
#include <machine/atomic.h>
#include <sys/umtx.h>
#define UWSGI_LOCK_SIZE sizeof(struct umtx)
#define UWSGI_RWLOCK_SIZE sizeof(struct umtx)
#define UWSGI_LOCK_ENGINE_NAME "FreeBSD umtx"
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
void uwsgi_lock_init(void *lock) {
umtx_init((struct umtx*) lock);
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
umtx_init((struct umtx*) uli->lock_ptr);
return uli;
}
void uwsgi_lock(void *lock) {
umtx_lock(lock, 1);
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
umtx_lock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock(void *lock) {
umtx_unlock(lock, 1);
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
uli->pid = 0;
}
#endif
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (umtx_trylock((struct umtx*) uli->lock_ptr, (u_long) getpid() )) {
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
#elif defined(UWSGI_LOCK_USE_POSIX_SEM)
#define UWSGI_LOCK_SIZE sizeof(sem_t)
#define UWSGI_RWLOCK_SIZE sizeof(sem_t)
#define UWSGI_LOCK_ENGINE_NAME "POSIX semaphores"
#include <semaphore.h>
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
sem_init((sem_t*) uli->lock_ptr, 1, 1);
uli->can_deadlock = 1;
return uli;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
sem_wait((sem_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
sem_post((sem_t*) uli->lock_ptr);
uli->pid = 0;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (sem_trywait((sem_t *) uli->lock_ptr) == 0) {
sem_post((sem_t*) uli->lock_ptr);
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
#ifdef UWSGI_LOCK_USE_OSX_SPINLOCK
#elif defined(UWSGI_LOCK_USE_OSX_SPINLOCK)
#define UWSGI_LOCK_ENGINE_NAME "OSX spinlocks"
#define UWSGI_LOCK_SIZE sizeof(OSSpinLock)
#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock)
void uwsgi_lock_init(void *lock) {
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
memset(lock, 0, sizeof(OSSpinLock));
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
uli->can_deadlock = 1;
return uli;
}
void uwsgi_lock(void *lock) {
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
OSSpinLockLock((OSSpinLock *) lock);
OSSpinLockLock((OSSpinLock *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock(void *lock) {
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
OSSpinLockUnlock((OSSpinLock *) lock);
OSSpinLockUnlock((OSSpinLock *) uli->lock_ptr);
uli->pid = 0;
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (OSSpinLockTry((OSSpinLock *) uli->lock_ptr)) {
OSSpinLockUnlock((OSSpinLock *) uli->lock_ptr);
return 0;
}
return uli->pid;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
uli->can_deadlock = 1;
return uli;
}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
#else
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
#define uwsgi_lock_fast_check uwsgi_lock_ipcsem_check
#define uwsgi_lock_fast uwsgi_lock_ipcsem
#define uwsgi_unlock_fast uwsgi_unlock_ipcsem
#define uwsgi_rwlock_fast_init uwsgi_rwlock_ipcsem_init
#define uwsgi_rwlock_fast_check uwsgi_rwlock_ipcsem_check
#define uwsgi_rlock_fast uwsgi_rlock_ipcsem
#define uwsgi_wlock_fast uwsgi_wlock_ipcsem
#define uwsgi_rwunlock_fast uwsgi_rwunlock_ipcsem
#define UWSGI_LOCK_SIZE sizeof(int)
#define UWSGI_RWLOCK_SIZE sizeof(int)
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
#define UWSGI_IPCSEM_ATEXIT 1
#endif
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
#ifdef UWSGI_LOCK_USE_FLOCK
// used by ftok
static int counter = 1;
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} semu ;
int semid;
key_t myKey;
#define UWSGI_LOCK_SIZE 8
#define UWSGI_RWLOCK_SIZE 8
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
static int lock_counter = 0;
if (uwsgi.ftok) {
myKey = ftok(uwsgi.ftok, counter);
if (myKey < 0) {
uwsgi_error("ftok()");
exit(1);
}
counter++;
semid = semget(myKey, 1, IPC_CREAT|0666);
}
else {
semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL| 0666);
}
void uwsgi_lock_init(void *lock) {
if (semid < 0) {
uwsgi_error("semget()");
exit(1);
}
// do this now, to allows triggering of atexit hook in case of problems
memcpy(uli->lock_ptr, &semid, sizeof(int));
char filename[17];
if (snprintf(filename, 17, ".uwsgiflock%d", lock_counter) < 0) {
uwsgi_log("unable to create lock %d\n", lock_counter);
semu.val = 1;
if (semctl(semid, 0, SETVAL, semu)) {
uwsgi_error("semctl()");
exit(1);
}
int fd = open(filename, O_CREAT|O_RDWR|O_TRUNC);
if (fd < 0) {
uwsgi_error("open()");
exit(1);
}
memcpy(lock, &fd, sizeof(int));
return uli;
}
void uwsgi_lock(void *lock) {
void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
int fd;
memcpy(&fd, lock, sizeof(int));
if (flock(fd, LOCK_EX)) { uwsgi_error("flock()"); }
int semid;
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = SEM_UNDO;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semop(semid, &sb, 1)) {
uwsgi_error("semop()");
}
}
void uwsgi_unlock(void *lock) {
int fd;
memcpy(&fd, lock, sizeof(int));
if (flock(fd, LOCK_UN)) { uwsgi_error("flock()"); }
void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
int semid;
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = 1;
sb.sem_flg = SEM_UNDO;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semop(semid, &sb, 1)) {
uwsgi_error("semop()");
}
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
struct uwsgi_lock_item *uwsgi_rwlock_ipcsem_init(char *id) { return uwsgi_lock_ipcsem_init(id);}
void uwsgi_rlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
void uwsgi_wlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
void uwsgi_rwunlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_unlock_ipcsem(uli); }
// ipc cannot deadlock
pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
return 0;
}
void uwsgi_ipcsem_clear(void) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uwsgi.workers) goto clear;
if (uwsgi.mywid == 0) goto clear;
if (uwsgi.master_process && getpid() == uwsgi.workers[0].pid) goto clear;
if (!uwsgi.master_process && uwsgi.mywid == 1) goto clear;
return;
clear:
#ifdef UWSGI_DEBUG
uwsgi_log("removing sysvipc semaphores...\n");
#endif
void *uwsgi_mmap_shared_lock() {
void *addr = NULL;
addr = mmap(NULL, UWSGI_LOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (addr == NULL) {
uwsgi_error("mmap()");
exit(1);
while(uli) {
int semid = 0;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semctl(semid, 0, IPC_RMID)) {
uwsgi_error("semctl()");
}
uli = uli->next;
}
return addr;
}
void *uwsgi_mmap_shared_rwlock() {
void *addr = NULL;
addr = mmap(NULL, UWSGI_RWLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (addr == NULL) {
uwsgi_error("mmap()");
exit(1);
pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_ipcsem_check(uli); }
void uwsgi_setup_locking() {
// use the fastest avaikable locking
if (uwsgi.lock_engine) {
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
uwsgi_log_initial("lock engine: ipcsem\n");
atexit(uwsgi_ipcsem_clear);
uwsgi.lock_ops.lock_init = uwsgi_lock_ipcsem_init;
uwsgi.lock_ops.lock_check = uwsgi_lock_ipcsem_check;
uwsgi.lock_ops.lock = uwsgi_lock_ipcsem;
uwsgi.lock_ops.unlock = uwsgi_unlock_ipcsem;
uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_ipcsem_init;
uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_ipcsem_check;
uwsgi.lock_ops.rlock = uwsgi_rlock_ipcsem;
uwsgi.lock_ops.wlock = uwsgi_wlock_ipcsem;
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_ipcsem;
uwsgi.lock_size = 8;
uwsgi.rwlock_size = 8;
return;
}
}
return addr;
uwsgi_log_initial("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
#ifdef UWSGI_IPCSEM_ATEXIT
atexit(uwsgi_ipcsem_clear);
#endif
uwsgi.lock_ops.lock_init = uwsgi_lock_fast_init;
uwsgi.lock_ops.lock_check = uwsgi_lock_fast_check;
uwsgi.lock_ops.lock = uwsgi_lock_fast;
uwsgi.lock_ops.unlock = uwsgi_unlock_fast;
uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_fast_init;
uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_fast_check;
uwsgi.lock_ops.rlock = uwsgi_rlock_fast;
uwsgi.lock_ops.wlock = uwsgi_wlock_fast;
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_fast;
uwsgi.lock_size = UWSGI_LOCK_SIZE;
uwsgi.rwlock_size = UWSGI_RWLOCK_SIZE;
}
int uwsgi_fcntl_lock(int fd) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = 0;
int ret = fcntl(fd, F_SETLKW, &fl);
if (ret < 0)
uwsgi_error("fcntl()");
return ret;
}
int uwsgi_fcntl_is_locked(int fd) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = 0;
if (fcntl(fd, F_SETLK, &fl)) {
return 1;
}
return 0;
}
+195 -51
View File
@@ -19,10 +19,101 @@
extern struct uwsgi_server uwsgi;
void uwsgi_check_logrotate(void) {
char message[1024];
int need_rotation = 0;
int need_reopen = 0;
if (uwsgi.log_master) {
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
}
else {
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
}
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
need_rotation = 1;
}
if (uwsgi_check_touches(uwsgi.touch_logrotate)) {
need_rotation = 1;
}
if (uwsgi_check_touches(uwsgi.touch_logreopen)) {
need_reopen = 1;
}
if (need_rotation) {
char *rot_name = uwsgi.log_backupname;
int need_free = 0;
if (rot_name == NULL) {
char *ts_str = uwsgi_num2str((int) time(NULL));
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
free(ts_str);
need_free = 1;
}
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize, rot_name);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
if (rename(uwsgi.logfile, rot_name) == 0) {
// reopen logfile dup'it and eventually gracefully reload workers;
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
if (dup2(fd, uwsgi.original_log_fd) < 0) {
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
}
else {
uwsgi_error("unable to rotate log: rename()");
}
if (need_free)
free(rot_name);
}
else if (need_reopen) {
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
// reopen logfile;
close(uwsgi.original_log_fd);
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) time(NULL), uwsgi.logfile);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
}
}
void log_request(struct wsgi_request *wsgi_req) {
// optimize this (please)
char *time_request;
char time_request[26];
time_t microseconds, microseconds2;
int rlen;
int app_req = -1;
@@ -44,23 +135,40 @@ void log_request(struct wsgi_request *wsgi_req) {
#ifdef UWSGI_SENDFILE
char *msg1 = " via sendfile() ";
#endif
char *msg3 = " via route() ";
char *msg4 = " via offload() ";
struct uwsgi_app *wi;
if (wsgi_req->do_not_log)
return;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi.apps[wsgi_req->app_id];
wi = &uwsgi_apps[wsgi_req->app_id];
if (wi->requests > 0) {
app_req = wi->requests;
}
}
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
via = msg1;
}
#endif
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
// mark route() requests
if (wsgi_req->status == -17) {
via = msg3;
}
else if (wsgi_req->status == -30) {
via = msg4;
}
#ifdef __sun__
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, time_request, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, time_request);
#endif
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;
@@ -85,12 +193,9 @@ void log_request(struct wsgi_request *wsgi_req) {
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} ",
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
#else
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ",
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
#endif
logvec[logvecpos].iov_base = mempkt;
@@ -99,59 +204,40 @@ void log_request(struct wsgi_request *wsgi_req) {
}
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n",
(int) uwsgi.mypid,
wsgi_req->app_id,
app_req,
(unsigned long long ) uwsgi.workers[0].requests,
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
wsgi_req->remote_user_len, wsgi_req->remote_user,
wsgi_req->var_cnt,
wsgi_req->uh.pktsize,
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(unsigned long long) wsgi_req->response_size,
rt, tsize,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
wsgi_req->status,
wsgi_req->header_cnt,
(unsigned long long) wsgi_req->headers_size,
wsgi_req->switches, wsgi_req->async_id);
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
logvec[logvecpos].iov_base = logpkt;
logvec[logvecpos].iov_len = rlen;
// do not check for errors
rlen = writev(2, logvec, logvecpos+1);
rlen = writev(2, logvec, logvecpos + 1);
}
void get_memusage() {
void get_memusage(uint64_t * rss, uint64_t * vsz) {
#ifdef UNBIT
uwsgi.workers[uwsgi.mywid].vsz_size = syscall(356);
*vsz = syscall(356);
#elif defined(__linux__)
FILE *procfile;
int i;
procfile = fopen("/proc/self/stat", "r");
if (procfile) {
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &uwsgi.workers[uwsgi.mywid].rss_size);
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
if (i != 2) {
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
uwsgi_log("warning: invalid record in /proc/self/stat\n");
}
fclose(procfile);
}
uwsgi.workers[uwsgi.mywid].rss_size = uwsgi.workers[uwsgi.mywid].rss_size * uwsgi.page_size;
*rss = *rss * uwsgi.page_size;
#elif defined (__sun__)
psinfo_t info;
int procfd;
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;
if (read(procfd, (char *) &info, sizeof(info)) > 0) {
*rss = (uint64_t) info.pr_rssize * 1024;
*vsz = (uint64_t) info.pr_size * 1024;
}
close(procfd);
}
@@ -162,22 +248,35 @@ void get_memusage() {
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size;
uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size;
*rss = t_info.resident_size;
*vsz = t_info.virtual_size;
}
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
kvm_t *kv;
int cnt;
#if defined(__FreeBSD__)
kv = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, NULL);
#elif defined(__NetBSD__) || defined(__OpenBSD__)
kv = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
#else
kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
#endif
if (kv) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
struct kinfo_proc *kproc;
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
if (kproc && cnt > 0) {
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
*vsz = kproc->ki_size;
*rss = kproc->ki_rssize * uwsgi.page_size;
}
#elif defined(UWSGI_NEW_OPENBSD)
struct kinfo_proc *kproc;
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc), &cnt);
if (kproc && cnt > 0) {
*vsz = (kproc->p_vm_dsize + kproc->p_vm_ssize + kproc->p_vm_tsize) * uwsgi.page_size;
*rss = kproc->p_vm_rssize * uwsgi.page_size;
}
#elif defined(__NetBSD__) || defined(__OpenBSD__)
struct kinfo_proc2 *kproc2;
@@ -185,11 +284,11 @@ void get_memusage() {
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
if (kproc2 && cnt > 0) {
#ifdef __OpenBSD__
uwsgi.workers[uwsgi.mywid].vsz_size = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
*vsz = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
#else
uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
*vsz = kproc2->p_vm_msize * uwsgi.page_size;
#endif
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
*rss = kproc2->p_vm_rssize * uwsgi.page_size;
}
#endif
@@ -199,13 +298,58 @@ void get_memusage() {
area_info ai;
int32 cookie;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
uwsgi.workers[uwsgi.mywid].vsz_size += ai.ram_size;
if ( (ai.protection & B_WRITE_AREA) != 0) {
uwsgi.workers[uwsgi.mywid].rss_size += ai.ram_size;
*vsz = 0;
*rss = 0;
while (get_next_area_info(0, &cookie, &ai) == B_OK) {
*vsz += ai.ram_size;
if ((ai.protection & B_WRITE_AREA) != 0) {
*rss += ai.ram_size;
}
}
#endif
}
void uwsgi_register_logger(char *name, ssize_t(*func) (struct uwsgi_logger *, char *, size_t)) {
struct uwsgi_logger *ul = uwsgi.loggers, *old_ul;
if (!ul) {
uwsgi.loggers = uwsgi_malloc(sizeof(struct uwsgi_logger));
ul = uwsgi.loggers;
}
else {
while (ul) {
old_ul = ul;
ul = ul->next;
}
ul = uwsgi_malloc(sizeof(struct uwsgi_logger));
old_ul->next = ul;
}
ul->name = name;
ul->func = func;
ul->next = NULL;
ul->configured = 0;
ul->fd = -1;
ul->data = NULL;
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-logger] registered \"%s\"\n", ul->name);
#endif
}
struct uwsgi_logger *uwsgi_get_logger(char *name) {
struct uwsgi_logger *ul = uwsgi.loggers;
while (ul) {
if (!strcmp(ul->name, name)) {
return ul;
}
ul = ul->next;
}
return NULL;
}
+47
View File
@@ -0,0 +1,47 @@
[uwsgi]
for = 4031 14032 4033 14034 24035
socket = /tmp/%(_)/uwsgi.sock
socket = 192.*:%(_)
print = ciao %(_) hello %(_) bye %(_)
endfor =
socket = :4045
socket = :4046
socket = :4047
socket = :4048
socket = :4049
socket = :4050
socket = :4051
show-config =
if-env = PIPPO
print =
print = PIPPO e' definita e il suo valore e' %(_) boh
endif =
socket = :5051
socket = :5052
socket = :5053
socket = :5054
if-exists = /etc/services
print = il file %(_) esiste $(PATH)
endif =
if-exists = /etc/foobar
print = il file %(_) esiste $(PATH)
endif =
socket = :6060
if-file = /etc/fstab
socket = :7171
endif =
ifdir = /tmp
print = %(_) is a directory
endif=
+134 -106
View File
@@ -2,12 +2,16 @@
extern struct uwsgi_server uwsgi;
struct wsgi_request* threaded_current_wsgi_req() { return pthread_getspecific(uwsgi.tur_key); }
struct wsgi_request* simple_current_wsgi_req() { return uwsgi.wsgi_req; }
struct wsgi_request *threaded_current_wsgi_req() {
return pthread_getspecific(uwsgi.tur_key);
}
struct wsgi_request *simple_current_wsgi_req() {
return uwsgi.wsgi_req;
}
void uwsgi_register_loop(char *name, void *loop) {
if (uwsgi.loops_cnt >= MAX_LOOPS) {
uwsgi_log("you can define %d loops at max\n", MAX_LOOPS);
exit(1);
@@ -21,8 +25,8 @@ void uwsgi_register_loop(char *name, void *loop) {
void *uwsgi_get_loop(char *name) {
int i;
for(i=0;i<uwsgi.loops_cnt;i++) {
for (i = 0; i < uwsgi.loops_cnt; i++) {
if (!strcmp(name, uwsgi.loops[i].name)) {
return uwsgi.loops[i].loop;
}
@@ -36,157 +40,181 @@ void *simple_loop(void *arg1) {
long core_id = (long) arg1;
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
int i;
#ifdef UWSGI_THREADING
int i;
//PyThreadState *pts;
sigset_t smask;
if (uwsgi.threads > 1) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
#ifdef UWSGI_DEBUG
sigdelset(&smask, SIGSEGV);
#endif
pthread_sigmask(SIG_BLOCK, &smask, NULL);
for(i=0;i<0xFF;i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
/*
pts = PyThreadState_New(uwsgi.main_thread->interp);
pthread_setspecific(uwsgi.ut_save_key, (void *) pts);
*/
}
}
#endif
// initialize the main event queue to monitor sockets
int main_queue = event_queue_init();
uwsgi_add_sockets_to_queue(main_queue);
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(main_queue, uwsgi.signal_socket);
event_queue_add_fd_read(main_queue, uwsgi.my_signal_socket);
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
wsgi_req_setup(wsgi_req, core_id, NULL);
UWSGI_CLEAR_STATUS;
wsgi_req_setup(wsgi_req, core_id);
if (wsgi_req_accept(wsgi_req)) {
if (wsgi_req_accept(main_queue, wsgi_req)) {
continue;
}
if (wsgi_req_recv(wsgi_req)) {
uwsgi_destroy_request(wsgi_req);
continue;
}
uwsgi_close_request(wsgi_req);
}
pthread_exit(NULL);
//never here
// end of the loop
if (uwsgi.workers[uwsgi.mywid].destroy && uwsgi.workers[0].pid > 0) {
#ifdef __APPLE__
kill(uwsgi.workers[0].pid, SIGTERM);
#else
if (uwsgi.propagate_touch) {
kill(uwsgi.workers[0].pid, SIGHUP);
}
else {
gracefully_kill(0);
}
#endif
}
return NULL;
}
#ifdef UWSGI_ASYNC
void complex_loop() {
int current_async_timeout = 0;
int i, j;
int interesting_fd;
#ifdef UWSGI_ZEROMQ
void *zeromq_loop(void *arg1) {
sigset_t smask;
int i;
long core_id = (long) arg1;
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
uwsgi.zeromq_recv_flag = 0;
zmq_pollitem_t zmq_poll_items[3];
if (uwsgi.threads > 1) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
#ifdef UWSGI_DEBUG
sigdelset(&smask, SIGSEGV);
#endif
pthread_sigmask(SIG_BLOCK, &smask, NULL);
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
if (tmp_zmq_pull == NULL) {
uwsgi_error("zmq_socket()");
exit(1);
}
if (zmq_connect(tmp_zmq_pull, uwsgi.zmq_receiver) < 0) {
uwsgi_error("zmq_connect()");
exit(1);
}
pthread_setspecific(uwsgi.zmq_pull, tmp_zmq_pull);
}
}
if (uwsgi.signal_socket > -1) {
zmq_poll_items[0].socket = pthread_getspecific(uwsgi.zmq_pull);
zmq_poll_items[0].fd = -1;
zmq_poll_items[0].events = ZMQ_POLLIN;
zmq_poll_items[1].socket = NULL;
zmq_poll_items[1].fd = uwsgi.signal_socket;
zmq_poll_items[1].events = ZMQ_POLLIN;
zmq_poll_items[2].socket = NULL;
zmq_poll_items[2].fd = uwsgi.my_signal_socket;
zmq_poll_items[2].events = ZMQ_POLLIN;
}
struct wsgi_request *wsgi_req;
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
current_async_timeout = async_get_timeout();
wsgi_req_setup(wsgi_req, core_id, NULL);
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, current_async_timeout, uwsgi.async_events, 64);
async_expire_timeouts();
if (uwsgi.async_nevents < 0) {
continue;
}
uwsgi.edge_triggered = 1;
wsgi_req->socket = uwsgi.zmq_socket;
for(i=0; i<uwsgi.async_nevents;i++) {
interesting_fd = event_queue_interesting_fd(uwsgi.async_events, i);
if ( interesting_fd == uwsgi.sockets[0].fd) {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
// async system is full !!!
goto cycle;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
continue;
}
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi.sockets[0].arg) < 0) {
uwsgi_error("fcntl()");
continue;
}
}
#endif
if (wsgi_req_recv(uwsgi.wsgi_req)) {
continue;
}
if (uwsgi.wsgi_req->async_status == UWSGI_OK) {
goto reqclear;
}
if (uwsgi.signal_socket > -1) {
if (zmq_poll(zmq_poll_items, 3, -1) < 0) {
uwsgi_error("zmq_poll()");
continue;
}
else if ( interesting_fd == uwsgi.sockets_poll[uwsgi.sockets_cnt].fd) {
// wake up cores waiting for signal
char byte;
if (read(uwsgi.sockets_poll[uwsgi.sockets_cnt].fd, &byte, 1) == 1) {
}
else {
uwsgi_error("read()");
}
for(j=0;j<uwsgi.async_current_max;j++) {
wsgi_req = uwsgi.wsgi_requests[j] ;
if (wsgi_req->sigwait) {
wsgi_req->signal_received = byte;
wsgi_req->sigwait = 0;
}
}
}
else {
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
if (uwsgi.wsgi_req) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
uwsgi.wsgi_req->async_waiting_fd = -1;
uwsgi.wsgi_req->async_waiting_fd_monitored = 0;
uwsgi.wsgi_req->async_timeout = 0;
}
event_queue_del_fd(uwsgi.async_queue, interesting_fd);
if (zmq_poll_items[1].revents & ZMQ_POLLIN) {
uwsgi_receive_signal(uwsgi.signal_socket, "worker", uwsgi.mywid);
continue;
}
if (zmq_poll_items[2].revents & ZMQ_POLLIN) {
uwsgi_receive_signal(uwsgi.my_signal_socket, "worker", uwsgi.mywid);
continue;
}
if (zmq_poll_items[0].revents & ZMQ_POLLIN) {
wsgi_req->poll.fd = wsgi_req->socket->proto_accept(wsgi_req, uwsgi.zmq_socket->fd);
}
}
else {
wsgi_req->poll.fd = wsgi_req->socket->proto_accept(wsgi_req, uwsgi.zmq_socket->fd);
}
cycle:
uwsgi.wsgi_req = async_loop();
if (uwsgi.wsgi_req == NULL)
continue;
uwsgi.wsgi_req->async_status = UWSGI_OK;
reqclear:
uwsgi_close_request(uwsgi.wsgi_req);
if (wsgi_req->poll.fd >= 0) {
wsgi_req_recv(wsgi_req);
}
uwsgi_close_request(wsgi_req);
}
// end of the loop
return NULL;
}
#endif
+1211 -574
View File
File diff suppressed because it is too large Load Diff
+877
View File
@@ -0,0 +1,877 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void worker_wakeup() {
}
int uwsgi_calc_cheaper(void) {
int i;
static time_t last_check = 0;
int check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!last_check) last_check = time(NULL);
time_t now = time(NULL);
if (!check_interval)
check_interval = 1;
if ( (now - last_check) < check_interval) return 1;
last_check = now;
int needed_workers = uwsgi.cheaper_algo();
if (needed_workers > 0) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
if (uwsgi_respawn_worker(i))
return 0;
needed_workers--;
}
if (needed_workers == 0)
break;
}
}
else if (needed_workers < 0) {
int oldest_worker = 0;
time_t oldest_worker_spawn = INT_MAX;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
if (uwsgi.workers[i].last_spawn < oldest_worker_spawn) {
oldest_worker_spawn = uwsgi.workers[i].last_spawn;
oldest_worker = i;
}
}
}
if (oldest_worker > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("worker %d should die...\n", oldest_worker);
#endif
uwsgi.workers[oldest_worker].cheaped = 1;
uwsgi.workers[oldest_worker].manage_next_request = 0;
// wakeup task in case of wait
(void) kill(uwsgi.workers[oldest_worker].pid, SIGWINCH);
}
}
return 1;
}
/*
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
when all of the workers are busy, the overload_count is incremented.
as soon as overload_count is higher than uwsgi.cheaper_overload (--cheaper-overload options)
at most cheaper_step (default to 1) new workers are spawned.
when at least one worker is free, the overload_count is decremented and the idle_count is incremented.
If overload_count reaches 0, the system will count active workers (the ones uncheaped) and busy workers (the ones running a request)
if there is exacly 1 free worker we are in "stable state" (1 spare worker available). no worker will be touched.
if the number of active workers is higher than uwsgi.cheaper_count and at least uwsgi.cheaper_overload cycles are passed from the last
"cheap it" procedure, then cheap a worker.
Example:
10 processes
2 cheaper
2 cheaper step
3 cheaper_overload
1 second master cycle
there are 7 workers running (triggered by some kind of spike activity).
Of this, 6 are busy, 1 is free. We are in stable state.
After a bit the spike disappear and idle_count start to increase.
After 3 seconds (uwsgi.cheaper_overload cycles) the oldest worker will be cheaped. This will happens
every seconds (uwsgi.cheaper_overload cycles) til the number of workers is == uwsgi.cheaper_count.
If during the "cheap them all" procedure, an overload condition come again (another spike) the "cheap them all"
will be interrupted.
*/
int uwsgi_cheaper_algo_spare(void) {
int i;
static uint64_t overload_count = 0;
static uint64_t idle_count = 0;
// step 1 -> count the number of busy workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
// if a non-busy worker is found, the overload_count is decremented and stop the cycle
if (uwsgi.workers[i].busy == 0) {
if (overload_count > 0)
overload_count--;
goto healthy;
}
}
}
overload_count++;
idle_count = 0;
healthy:
// are we overloaded ?
if (overload_count > uwsgi.cheaper_overload) {
#ifdef UWSGI_DEBUG
uwsgi_log("overloaded !!!\n");
#endif
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step)
break;
}
}
// reset overload
overload_count = 0;
// return the maximum number of workers to spawn
return decheaped;
}
// we are no more overloaded
else if (overload_count == 0) {
// how many active workers ?
int active_workers = 0;
int busy_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
active_workers++;
if (uwsgi.workers[i].busy == 1)
busy_workers++;
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("active workers %d busy_workers %d\n", active_workers, busy_workers);
#endif
// special condition: uwsgi.cheaper running workers and 1 free
if (active_workers > busy_workers && active_workers - busy_workers == 1) {
#ifdef UWSGI_DEBUG
uwsgi_log("stable status: 1 spare worker\n");
#endif
return 0;
}
idle_count++;
if (active_workers > uwsgi.cheaper_count && idle_count % uwsgi.cheaper_overload == 0) {
// we are in "cheap them all"
return -1;
}
}
return 0;
}
/*
-- Cheaper, backlog algorithm (supported only on Linux) --
increse the number of workers when the listen queue is higher than uwsgi.cheaper_overload.
Decrese when lower.
*/
int uwsgi_cheaper_algo_backlog(void) {
int i;
#ifdef __linux__
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
#else
int backlog = 0;
#endif
if (backlog > (int)uwsgi.cheaper_overload) {
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step)
break;
}
}
// return the maximum number of workers to spawn
return decheaped;
}
else if (backlog < (int) uwsgi.cheaper_overload) {
int active_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
active_workers++;
}
}
if (active_workers > uwsgi.cheaper_count) {
return -1;
}
}
return 0;
}
// reload uWSGI, close unneded file descriptor, restore the original environment and re-exec the binary
void uwsgi_reload(char **argv) {
int i;
int waitpid_status;
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
}
uwsgi_log("binary reloading uWSGI...\n");
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
if (chdir(uwsgi.cwd)) {
uwsgi_error("chdir()");
}
/* check fd table (a module can obviosly open some fd on initialization...) */
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int)uwsgi.max_fd);
for (i = 3; i < (int)uwsgi.max_fd; i++) {
int found = 0;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (i == uwsgi_sock->fd) {
uwsgi_log("found fd %d mapped to socket %d (%s)\n", i, uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
found = 1;
break;
}
uwsgi_sock = uwsgi_sock->next;
}
if (!found) {
if (uwsgi.has_emperor) {
if (i == uwsgi.emperor_fd) {
found = 1;
}
}
}
if (uwsgi.log_master) {
if (uwsgi.original_log_fd > -1) {
if (i == uwsgi.original_log_fd) {
found = 1;
}
}
if (uwsgi.shared->worker_log_pipe[0] > -1) {
if (i == uwsgi.shared->worker_log_pipe[0]) {
found = 1;
}
}
if (uwsgi.shared->worker_log_pipe[1] > -1) {
if (i == uwsgi.shared->worker_log_pipe[1]) {
found = 1;
}
}
}
if (!found) {
#ifdef __APPLE__
fcntl(i, F_SETFD, FD_CLOEXEC);
#else
close(i);
#endif
}
}
#ifdef UWSGI_AS_SHARED_LIBRARY
return;
#else
uwsgi_log("running %s\n", uwsgi.binary_path);
uwsgi_flush_logs();
argv[0] = uwsgi.binary_path;
//strcpy (argv[0], uwsgi.binary_path);
if (uwsgi.log_master) {
if (uwsgi.original_log_fd > -1) {
dup2(uwsgi.original_log_fd, 1);
dup2(1, 2);
}
if (uwsgi.shared->worker_log_pipe[0] > -1) {
close(uwsgi.shared->worker_log_pipe[0]);
}
if (uwsgi.shared->worker_log_pipe[1] > -1) {
close(uwsgi.shared->worker_log_pipe[1]);
}
}
execvp(uwsgi.binary_path, argv);
uwsgi_error("execvp()");
// never here
exit(1);
#endif
}
void master_check_cluster_nodes() {
int i;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_STATIC && ucn->status == UWSGI_NODE_FAILED) {
// should i retry ?
if (uwsgi.master_cycles % ucn->errors == 0) {
if (!uwsgi_ping_node(i, uwsgi.wsgi_req)) {
ucn->status = UWSGI_NODE_OK;
uwsgi_log("re-enabled cluster node %d/%s\n", i, ucn->name);
}
else {
ucn->errors++;
}
}
}
else if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_DYNAMIC) {
// if the last_seen attr is higher than 30 secs ago, mark the node as dead
if ((uwsgi.current_time - ucn->last_seen) > 30) {
uwsgi_log_verbose("no presence announce in the last 30 seconds by node %s, i assume it is dead.\n", ucn->name);
ucn->name[0] = 0;
}
}
}
}
void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
int i;
// close the cache server
if (uwsgi.cache_server_fd != -1) {
close(uwsgi.cache_server_fd);
}
if (uwsgi.master_process) {
if (uwsgi.master_queue > -1)
close(uwsgi.master_queue);
// close gateways
if (!ug) {
for (i = 0; i < ushared->gateways_cnt; i++) {
close(ushared->gateways[i].internal_subscription_pipe[0]);
close(ushared->gateways[i].internal_subscription_pipe[1]);
}
}
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (ug && !strcmp(ug->name, ugs->owner)) {
ugs = ugs->next;
continue;
}
// do not close shared sockets !!!
if (!ugs->shared) {
close(ugs->fd);
}
ugs = ugs->next;
}
// fix the communication pipe
close(uwsgi.shared->worker_signal_pipe[0]);
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].signal_pipe[0] != -1)
close(uwsgi.workers[i].signal_pipe[0]);
if (i != wid) {
if (uwsgi.workers[i].signal_pipe[1] != -1)
close(uwsgi.workers[i].signal_pipe[1]);
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.i_am_a_spooler && uwsgi.i_am_a_spooler->pid != getpid()) {
if (uwsgi.shared->spooler_signal_pipe[0] != -1)
close(uwsgi.shared->spooler_signal_pipe[0]);
if (uwsgi.shared->spooler_signal_pipe[1] != -1)
close(uwsgi.shared->spooler_signal_pipe[1]);
}
#endif
if (uwsgi.shared->mule_signal_pipe[0] != -1)
close(uwsgi.shared->mule_signal_pipe[0]);
if (muleid == 0) {
if (uwsgi.shared->mule_signal_pipe[1] != -1)
close(uwsgi.shared->mule_signal_pipe[1]);
if (uwsgi.shared->mule_queue_pipe[1] != -1)
close(uwsgi.shared->mule_queue_pipe[1]);
}
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].signal_pipe[0] != -1)
close(uwsgi.mules[i].signal_pipe[0]);
if (muleid != i + 1) {
if (uwsgi.mules[i].signal_pipe[1] != -1)
close(uwsgi.mules[i].signal_pipe[1]);
if (uwsgi.mules[i].queue_pipe[1] != -1)
close(uwsgi.mules[i].queue_pipe[1]);
}
}
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (uwsgi.farms[i].signal_pipe[0] != -1)
close(uwsgi.farms[i].signal_pipe[0]);
if (muleid == 0) {
if (uwsgi.farms[i].signal_pipe[1] != -1)
close(uwsgi.farms[i].signal_pipe[1]);
if (uwsgi.farms[i].queue_pipe[1] != -1)
close(uwsgi.farms[i].queue_pipe[1]);
}
}
}
}
int uwsgi_respawn_worker(int wid) {
int respawns = uwsgi.workers[wid].respawn_count;
int i;
if (uwsgi.threaded_logger) {
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
}
pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
if (pid == 0) {
signal(SIGWINCH, worker_wakeup);
signal(SIGTSTP, worker_wakeup);
uwsgi.mywid = wid;
uwsgi.mypid = getpid();
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
// do not reset worker counters on reload !!!
//uwsgi.workers[uwsgi.mywid].requests = 0;
// ...but maintain a delta counter (yes this is racy in multithread)
uwsgi.workers[uwsgi.mywid].delta_requests = 0;
//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
uwsgi.workers[uwsgi.mywid].cheaped = 0;
uwsgi.workers[uwsgi.mywid].busy = 0;
uwsgi.workers[uwsgi.mywid].suspended = 0;
uwsgi.workers[uwsgi.mywid].sig = 0;
// reset the apps count with a copy from the master
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
uwsgi_fixup_fds(wid, 0, NULL);
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
if (uwsgi.master_process) {
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
}
}
return 1;
}
else if (pid < 1) {
uwsgi_error("fork()");
}
else {
if (respawns > 0) {
uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
}
else {
uwsgi_log("spawned uWSGI worker %d (pid: %d, cores: %d)\n", wid, pid, uwsgi.cores);
}
}
if (uwsgi.threaded_logger) {
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
}
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = ucron->minute;
uc_hour = ucron->hour;
uc_day = ucron->day;
uc_month = ucron->month;
uc_week = ucron->week;
// negative values as interval -1 = * , -5 = */5
if (ucron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (ucron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (ucron->month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (ucron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (ucron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (ucron->day >= 0 && ucron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, signal it ?
if (now - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = now;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
uwsgi_error("localtime()");
return;
}
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
uc_minute = current_cron->minute;
uc_hour = current_cron->hour;
uc_day = current_cron->day;
uc_month = current_cron->month;
uc_week = current_cron->week;
// negative values as interval -1 = * , -5 = */5
if (current_cron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (current_cron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (current_cron->month < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (current_cron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (current_cron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (current_cron->day >= 0 && current_cron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, run command ?
if (now - current_cron->last_job > 60) {
//call command
if (current_cron->command) {
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
}
}
current_cron->last_job = now;
}
}
current_cron = current_cron->next;
}
}
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
void uwsgi_send_stats(int fd) {
int i, j;
struct sockaddr_un client_src;
struct uwsgi_app *ua;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
#ifdef __linux__
stats_send_llu("\"listen_queue\": %llu,\n", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]);
stats_send_llu("\"listen_queue_errors\": %llu,\n", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]);
#endif
stats_send_llu("\"load\": %llu,\n", uwsgi.shared->load);
fprintf(output, "\"pid\": %d,\n", (int) (getpid()));
fprintf(output, "\"uid\": %d,\n", (int) (getuid()));
fprintf(output, "\"gid\": %d,\n", (int) (getgid()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
if (uwsgi.daemons) {
fprintf(output, "\"daemons\": [\n");
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
fprintf(output, "\t{ \"cmd\": \"%s\", \"pid\": %d, \"respawns\": %llu }", ud->command, (int) ud->pid, (unsigned long long) ud->respawns - 1);
if (ud->next)
fprintf(output, ",\n");
else {
fprintf(output, "\n");
}
ud = ud->next;
}
fprintf(output, "],\n");
}
fprintf(output, "\"locks\": [\n");
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
while (uli) {
if (uli->next) {
fprintf(output, "\t{ \"%s\": %d },\n", uli->id, (int) uli->pid);
}
else {
fprintf(output, "\t{ \"%s\": %d }\n", uli->id, (int) uli->pid);
}
uli = uli->next;
}
fprintf(output, "],\n");
fprintf(output, "\"workers\": [\n");
for (i = 0; i < uwsgi.numproc; i++) {
fprintf(output, "\t{");
fprintf(output, "\"id\": %d, ", uwsgi.workers[i + 1].id);
fprintf(output, "\"pid\": %d, ", (int) uwsgi.workers[i + 1].pid);
stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i + 1].requests);
stats_send_llu("\"delta_requests\": %llu, ", uwsgi.workers[i + 1].delta_requests);
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i + 1].exceptions);
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i + 1].signals);
stats_send_llu("\"static_offload_threads\": %llu, ", uwsgi.workers[i + 1].static_offload_threads);
if (uwsgi.workers[i + 1].cheaped) {
fprintf(output, "\"status\": \"cheap\", ");
}
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
fprintf(output, "\"status\": \"pause\", ");
}
else {
if (uwsgi.workers[i + 1].sig) {
fprintf(output, "\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
}
else if (uwsgi.workers[i + 1].busy) {
fprintf(output, "\"status\": \"busy\", ");
}
else {
fprintf(output, "\"status\": \"idle\", ");
}
}
stats_send_llu("\"rss\": %llu, ", uwsgi.workers[i + 1].rss_size);
stats_send_llu("\"vsz\": %llu, ", uwsgi.workers[i + 1].vsz_size);
stats_send_llu("\"running_time\": %llu, ", uwsgi.workers[i + 1].running_time);
stats_send_llu("\"last_spawn\": %llu, ", uwsgi.workers[i + 1].last_spawn);
stats_send_llu("\"respawn_count\": %llu, ", uwsgi.workers[i + 1].respawn_count);
stats_send_llu("\"tx\": %llu, ", uwsgi.workers[i + 1].tx);
stats_send_llu("\"avg_rt\": %llu, ", uwsgi.workers[i + 1].avg_response_time);
fprintf(output, "\"apps\": [\n");
for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
ua = &uwsgi.workers[i + 1].apps[j];
fprintf(output, "\t\t{ ");
fprintf(output, "\"id\": %d, ", j);
fprintf(output, "\"modifier1\": %d, ", ua->modifier1);
fprintf(output, "\"mountpoint\": \"%.*s\", ", ua->mountpoint_len, ua->mountpoint);
stats_send_llu("\"startup_time\": %llu, ", ua->startup_time);
stats_send_llu("\"requests\": %llu, ", ua->requests);
stats_send_llu("\"exceptions\": %llu, ", ua->exceptions);
if (ua->chdir) {
fprintf(output, "\"chdir\": \"%s\", ", ua->chdir);
}
else {
fprintf(output, "\"chdir\": \"\" ");
}
if (j == uwsgi.workers[i + 1].apps_cnt - 1) {
fprintf(output, "}\n");
}
else {
fprintf(output, "},\n");
}
}
fprintf(output, "\t\t]");
if (i == uwsgi.numproc - 1) {
fprintf(output, "}\n");
}
else {
fprintf(output, "},\n");
}
}
fprintf(output, "]}\n");
fclose(output);
}
void uwsgi_register_cheaper_algo(char *name, int(*func) (void)) {
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
if (!uca) {
uwsgi.cheaper_algos = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
uca = uwsgi.cheaper_algos;
}
else {
while (uca) {
if (!uca->next) {
uca->next = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
uca = uca->next;
break;
}
uca = uca->next;
}
}
uca->name = name;
uca->func = func;
uca->next = NULL;
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-cheaper-algo] registered \"%s\"\n", uca->name);
#endif
}
+4
View File
@@ -19,4 +19,8 @@
<module>trac.web.main:dispatch_request</module>
</uwsgi>
<uwsgi>
<socket>:3031</socket>
</uwsgi>
</unbit>
+23
View File
@@ -0,0 +1,23 @@
main = Server(
uuid="f400bf85-4538-4f7a-8908-67e313d515c2",
access_log="/logs/access.log",
error_log="/logs/error.log",
chroot="./",
default_host="192.168.173.18",
name="test",
pid_file="/run/mongrel2.pid",
port=6767,
hosts = [
Host(name="192.168.173.18", routes={
'/': Handler(send_spec='tcp://192.168.173.18:9999',
send_ident='54c6755b-9628-40a4-9a2d-cc82a816345e',
recv_spec='tcp://192.168.173.18:9998', recv_ident='')
})
]
)
settings = {'upload.temp_store':'tmp/mongrel2.upload.XXXXXX'}
servers = [main]
uwsgi = { 'socket':':3031', 'master':'true'}
+379
View File
@@ -0,0 +1,379 @@
/*
uWSGI mules are very simple workers only managing signals or running custom code in background.
By default they born in signal-only mode, but if you patch them (passing the script/code to run) they will became fully customized daemons.
*/
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_mule_handler(void);
void mule_send_msg(int fd, char *message, size_t len) {
socklen_t so_bufsize_len = sizeof(int);
int so_bufsize = 0;
if (write(fd, message, len) != (ssize_t) len) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** MULE MSG QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
}
else {
uwsgi_error("mule_send_msg()");
}
}
}
void uwsgi_mule(int id) {
int i;
pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
if (pid == 0) {
uwsgi.muleid = id;
// avoid race conditions
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = getpid();
uwsgi_fixup_fds(0, id, NULL);
uwsgi.my_signal_socket = uwsgi.mules[id-1].signal_pipe[1];
uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];
uwsgi_close_all_sockets();
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
if (uwsgi.mules[id-1].patch) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
// never here
break;
}
}
}
}
uwsgi_mule_handler();
}
else if (pid > 0) {
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = pid;
uwsgi_log("spawned uWSGI mule %d (pid: %d)\n", id, (int) pid);
}
}
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
struct uwsgi_mule_farm *umf = farm->mules;
while(umf) {
if (umf->mule->id == muleid) {
return 1;
}
umf = umf->next;
}
return 0;
}
int farm_has_signaled(int fd) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while(umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].signal_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
return 0;
}
int farm_has_msg(int fd) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while(umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].queue_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
return 0;
}
void uwsgi_mule_add_farm_to_queue(int queue) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
event_queue_add_fd_read(queue, uwsgi.farms[i].signal_pipe[1]);
event_queue_add_fd_read(queue, uwsgi.farms[i].queue_pipe[1]);
}
}
}
void uwsgi_mule_handler() {
ssize_t len;
uint8_t uwsgi_signal;
int rlen;
int interesting_fd;
// this must be configurable
char message[65536];
int mule_queue = event_queue_init();
event_queue_add_fd_read(mule_queue, uwsgi.signal_socket);
event_queue_add_fd_read(mule_queue, uwsgi.my_signal_socket);
event_queue_add_fd_read(mule_queue, uwsgi.mules[uwsgi.muleid-1].queue_pipe[1]);
event_queue_add_fd_read(mule_queue, uwsgi.shared->mule_queue_pipe[1]);
uwsgi_mule_add_farm_to_queue(mule_queue);
for(;;) {
rlen = event_queue_wait(mule_queue, -1, &interesting_fd);
if (rlen <= 0) {
continue;
}
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
}
}
else if (interesting_fd == uwsgi.mules[uwsgi.muleid-1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
len = read(interesting_fd, message, 65536);
if (len < 0) {
uwsgi_error("read()");
}
else {
int i,found = 0;
for(i=0;i<256;i++) {
if (uwsgi.p[i]->mule_msg) {
if (uwsgi.p[i]->mule_msg(message, len)) {
found = 1;
break;
}
}
}
if (!found)
uwsgi_log("*** mule %d received a %d bytes message ***\n", uwsgi.muleid, len);
}
}
}
}
struct uwsgi_mule *get_mule_by_id(int id) {
int i;
for(i=0;i<uwsgi.mules_cnt;i++) {
if (uwsgi.mules[i].id == id) {
return &uwsgi.mules[i];
}
}
return NULL;
}
struct uwsgi_farm *get_farm_by_name(char *name) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (!strcmp(uwsgi.farms[i].name, name)) {
return &uwsgi.farms[i];
}
}
return NULL;
}
struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **umf, struct uwsgi_mule *um) {
struct uwsgi_mule_farm *uwsgi_mf = *umf, *old_umf;
if (!uwsgi_mf) {
*umf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
uwsgi_mf = *umf;
}
else {
while(uwsgi_mf) {
old_umf = uwsgi_mf;
uwsgi_mf = uwsgi_mf->next;
}
uwsgi_mf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
old_umf->next = uwsgi_mf;
}
uwsgi_mf->mule = um;
uwsgi_mf->next = NULL;
return uwsgi_mf;
}
ssize_t uwsgi_mule_get_msg(int manage_signals, int manage_farms, char *message, size_t buffer_size, int timeout) {
ssize_t len = 0;
struct pollfd *mulepoll;
int count = 4;
int farms_count = 0;
uint8_t uwsgi_signal;
int i;
if (uwsgi.muleid == 0) return -1;
if (manage_signals) count = 2;
if (!manage_farms) goto next;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) farms_count++;
}
next:
if (timeout > -1) timeout = timeout*1000;
mulepoll = uwsgi_malloc(sizeof(struct pollfd) * (count+farms_count));
mulepoll[0].fd = uwsgi.mules[uwsgi.muleid-1].queue_pipe[1];
mulepoll[0].events = POLLIN;
mulepoll[1].fd = uwsgi.shared->mule_queue_pipe[1];
mulepoll[1].events = POLLIN;
if (count > 2) {
mulepoll[2].fd = uwsgi.signal_socket;
mulepoll[2].events = POLLIN;
mulepoll[3].fd = uwsgi.my_signal_socket;
mulepoll[3].events = POLLIN;
}
if (farms_count > 0) {
int tmp_cnt = 0;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
mulepoll[count+tmp_cnt].fd = uwsgi.farms[i].queue_pipe[1];
mulepoll[count+tmp_cnt].events = POLLIN;
tmp_cnt++;
}
}
}
int ret = poll(mulepoll, count+farms_count, timeout);
if (ret <= 0) {
uwsgi_error("poll");
}
else {
if (mulepoll[0].revents & POLLIN) {
len = read(uwsgi.mules[uwsgi.muleid-1].queue_pipe[1], message, buffer_size);
}
else if (mulepoll[1].revents & POLLIN) {
len = read(uwsgi.shared->mule_queue_pipe[1], message, buffer_size);
}
else {
if (count > 2) {
int interesting_fd = -1;
if (mulepoll[2].revents & POLLIN) {
interesting_fd = mulepoll[2].fd;
}
else if (mulepoll[3].revents & POLLIN) {
interesting_fd = mulepoll[3].fd;
}
if (interesting_fd > -1) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
}
// set the error condition
len = -1;
goto clear;
}
}
// read messages in the farm
for(i=0;i<farms_count;i++) {
if (mulepoll[count+i].revents & POLLIN) {
len = read(mulepoll[count+i].fd, message, buffer_size);
break;
}
}
}
}
if (len < 0) {
uwsgi_error("read()");
goto clear;
}
clear:
free(mulepoll);
return len;
}
void uwsgi_opt_add_mule(char *opt, char *value, void *foobar) {
uwsgi.mules_cnt++;
uwsgi_string_new_list(&uwsgi.mules_patches, value);
}
void uwsgi_opt_add_mules(char *opt, char *value, void *foobar) {
int i;
for(i=0;i<atoi(value);i++) {
uwsgi.mules_cnt++;
uwsgi_string_new_list(&uwsgi.mules_patches, NULL);
}
}
void uwsgi_opt_add_farm(char *opt, char *value, void *foobar) {
uwsgi.farms_cnt++;
uwsgi_string_new_list(&uwsgi.farms_list, value);
}
+27
View File
@@ -0,0 +1,27 @@
from uwsgidecorators import *
@timer(3, target='mule1')
def hello_timer(signum):
print "3 seconds elapsed"
@mulefunc
def conto_fino_a_dieci(uno, due, tre):
print "MULE ID %d: conto_fino_a_dieci" % uwsgi.mule_id(),uno,due,tre
@mulefunc(2)
def conto_fino_a_venti(uno, due, tre):
print "MULE ID %d: conto_fino_a_venti" % uwsgi.mule_id(),uno,due,tre
@mulefunc('topogigio')
def conto_fino_a_trenta(uno, due, tre):
print "MULE ID %d: conto_fino_a_trenta" % uwsgi.mule_id(),uno,due,tre
def application(e, sr):
conto_fino_a_dieci(1,2,3)
conto_fino_a_venti(4,5,6)
conto_fino_a_trenta(7,8,9)
sr('200 OK', [('Content-Type','text/html')])
return "MULE !!!"
+18 -4
View File
@@ -1,13 +1,27 @@
[uwsgi]
; socket 0
socket = :3033
; socket 1
socket = :3034
vacuum = true
; socket 2
socket = pippo1.sock
; socket 3
socket = pippo2.sock
; socket 4
socket = 127.0.0.1:1717
map-socket = 0:1,2,3,4
map-socket = 1:4
map-socket = 2:10
map-socket = 3:5,6,9
map-socket = 4:7,8,9
vacuum = true
memory-report = true
master = true
processes = 10
mount = /app1=werkzeug.testapp:test_app
mount = /app2=config:/Users/roberta/uwsgi/my.ini
mount = /app3=pinaxsite/deploy/pinax.wsgi
;mount = /app1=werkzeug.testapp:test_app
;mount = /app2=config:/Users/roberta/uwsgi/my.ini
;mount = /app3=pinaxsite/deploy/pinax.wsgi
+18 -2
View File
@@ -1,5 +1,14 @@
<uwsgi>
<!--
DO NOT USE <app> TAG !!!
It is deprecated and will be removed from 1.2
-->
<plugins>psgi</plugins>
<plugins>rack</plugins>
<http>:9090</http>
@@ -24,6 +33,8 @@
<module>werkzeug.testapp:test_app</module>
</app>
<app mountpoint="/foobar">werkzeug.testapp:test_app</app>
<app mountpoint="/trac">
<module>trac.web.main:dispatch_request</module>
</app>
@@ -32,11 +43,12 @@
<module>werkzeug.testapp:test_app</module>
</app>
<!-- eval is broken -->
<app mountpoint="/bzr">
<eval>
<eval>
from bzrlib.transport.http import wsgi
application = wsgi.make_app("mybzr", "/bzr", readonly=False)
</eval>
</eval>
</app>
<app domain="sirius002:9090">
@@ -47,4 +59,8 @@ application = wsgi.make_app("mybzr", "/bzr", readonly=False)
<rack>config2.ru</rack>
</app>
<app mountpoint="precise64.local">
<psgi>test.psgi</psgi>
</app>
</uwsgi>
+3 -8
View File
@@ -1,14 +1,9 @@
import werkzeug
def web3_app(environ):
status = b'200 OK'
headers = [(b'Content-type', b'text/plain')]
body = [b'I am a Web3 app\n']
return body, status, headers
import uwsgi
def zero_app(e,s):
s('200 OK', [ ('Content-Type', 'text/plain') ])
return ""
return "0"
def not_found(e,s):
s('404 Not Found', [ ('Content-Type', 'text/plain') ])
@@ -24,4 +19,4 @@ def internal_server_error(e, s):
s('500 Internal Server Error', [ ('Content-Type', 'text/plain') ])
return ""
applications = {'':web3_app, '/wsgi':wsgi_app, '/test':werkzeug.test_app, '/zero':zero_app, '/notfound':not_found, '/ise':internal_server_error}
uwsgi.applications = {'/wsgi':wsgi_app, '/test':werkzeug.test_app, '/zero':zero_app, '/notfound':not_found, '/ise':internal_server_error}
+11 -1
View File
@@ -2,6 +2,16 @@ import uwsgi
import struct
import sys
print sys.argv
if len(sys.argv) == 3:
chunks = uwsgi.send_message(sys.argv[1], 10, int(sys.argv[2]), '')
print uwsgi.send_uwsgi_message(sys.argv[1], int(sys.argv[2]), 10, int(sys.argv[3]), struct.pack("i", int(sys.argv[4])))
pkt = ''
for chunk in chunks:
pkt += chunk
print "%d = %d" % (int(sys.argv[2]), struct.unpack("I", pkt)[0])
elif len(sys.argv) == 4:
uwsgi.send_message(sys.argv[1], 10, int(sys.argv[2]), struct.pack("I", int(sys.argv[3])))
+72
View File
@@ -0,0 +1,72 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_systemd_notify(char *message) {
struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
struct iovec *iovec = msghdr->msg_iov;
iovec[0].iov_base = "STATUS=";
iovec[0].iov_len = 7;
iovec[1].iov_base = message;
iovec[1].iov_len = strlen(message);
iovec[2].iov_base = "\n";
iovec[2].iov_len = 1;
msghdr->msg_iovlen = 3;
sendmsg(uwsgi.notification_fd, msghdr, 0);
}
void uwsgi_systemd_notify_ready(void) {
struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
struct iovec *iovec = msghdr->msg_iov;
iovec[0].iov_base = "STATUS=uWSGI is ready\nREADY=1\n";
iovec[0].iov_len = 30;
msghdr->msg_iovlen = 1;
sendmsg(uwsgi.notification_fd, msghdr, 0);
}
void uwsgi_systemd_init(char *systemd_socket) {
struct sockaddr_un *sd_sun;
struct msghdr *msghdr;
uwsgi.notification_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (uwsgi.notification_fd < 0) {
uwsgi_error("socket()");
return;
}
sd_sun = uwsgi_malloc(sizeof(struct sockaddr_un));
memset(sd_sun, 0, sizeof(struct sockaddr_un));
sd_sun->sun_family = AF_UNIX;
strncpy(sd_sun->sun_path, systemd_socket, sizeof(sd_sun->sun_path));
if (sd_sun->sun_path[0] == '@') sd_sun->sun_path[0] = 0;
msghdr = uwsgi_malloc(sizeof(struct msghdr));
memset(msghdr, 0, sizeof(struct msghdr));
msghdr->msg_iov = uwsgi_malloc(sizeof(struct iovec)*3);
memset(msghdr->msg_iov, 0, sizeof(struct iovec)*3);
msghdr->msg_name = sd_sun;
msghdr->msg_namelen = sizeof(struct sockaddr_un);
uwsgi.notification_object = msghdr;
uwsgi.notify = uwsgi_systemd_notify;
uwsgi.notify_ready = uwsgi_systemd_notify_ready;
}
+241 -29
View File
@@ -2,63 +2,275 @@
extern struct uwsgi_server uwsgi;
void embed_plugins() {
static int plugin_already_loaded(const char *plugin) {
int i;
#ifdef UWSGI_EMBED_PLUGIN_PSGI
if (uwsgi.plugin_arg_psgi)
uwsgi_load_plugin(5, "psgi_plugin.so", uwsgi.plugin_arg_psgi, 0);
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->name) {
if (!strcmp(plugin, uwsgi.p[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
#ifdef UWSGI_EMBED_PLUGIN_LUA
if (uwsgi.plugin_arg_lua)
uwsgi_load_plugin(6, "lua_plugin.so", uwsgi.plugin_arg_lua, 0);
return 1;
}
}
if (uwsgi.p[i]->alias) {
if (!strcmp(plugin, uwsgi.p[i]->alias)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
}
#ifdef UWSGI_EMBED_PLUGIN_RACK
if (uwsgi.plugin_arg_rack)
uwsgi_load_plugin(7, "rack_plugin.so", uwsgi.plugin_arg_rack, 0);
for(i=0;i<uwsgi.gp_cnt;i++) {
if (uwsgi.gp[i]->name) {
if (!strcmp(plugin, uwsgi.gp[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
if (uwsgi.gp[i]->alias) {
if (!strcmp(plugin, uwsgi.gp[i]->alias)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
}
return 0;
}
int uwsgi_load_plugin(int modifier, char *plugin, char *pargs, int absolute) {
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
void *plugin_handle = NULL;
char *plugin_abs_path = NULL;
char *plugin_filename = NULL;
int need_free = 0;
char *plugin_name = plugin;
char *plugin_symbol_name_start = plugin;
void *plugin_handle;
char *plugin_name;
char *plugin_entry_symbol;
struct uwsgi_plugin *up;
char linkpath_buf[1024], linkpath[1024];
int linkpath_size;
if (absolute) {
plugin_name = malloc(strlen(plugin) + 1);
memcpy(plugin_name, plugin, strlen(plugin) + 1);
}
else {
plugin_name = uwsgi_concat4(UWSGI_PLUGIN_DIR, "/", plugin, "_plugin.so");
char *colon = strchr(plugin_name, ':');
if (colon) {
colon[0] = 0;
modifier = atoi(plugin_name);
plugin_name = colon+1;
colon[0] = ':';
}
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
free(plugin_name);
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
need_free = 1;
}
plugin_symbol_name_start = plugin_name;
// step 1: check for absolute plugin (stop if it fails)
if (strchr(plugin_name, '/')) {
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
if (!plugin_handle) {
if (!has_option)
uwsgi_log( "%s\n", dlerror());
goto end;
}
plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/');
plugin_symbol_name_start++;
plugin_abs_path = plugin_name;
goto success;
}
// step dir, check for user-supplied plugins directory
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
while(pdir) {
plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name);
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
if (plugin_handle) {
plugin_abs_path = plugin_filename;
//free(plugin_filename);
goto success;
}
free(plugin_filename);
plugin_filename = NULL;
pdir = pdir->next;
}
// last step: search in compile-time plugin_dir
if (!plugin_handle) {
plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name);
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
plugin_abs_path = plugin_filename;
//free(plugin_filename);
}
success:
if (!plugin_handle) {
uwsgi_log( "%s\n", dlerror());
if (!has_option)
uwsgi_log( "%s\n", dlerror());
}
else {
plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin");
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start)-3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
if (!up) {
// is it a link ?
memset(linkpath_buf, 0, 1024);
memset(linkpath, 0, 1024);
if ((linkpath_size = readlink(plugin_abs_path, linkpath_buf, 1023)) > 0) {
do {
linkpath_buf[linkpath_size] = '\0';
strncpy(linkpath, linkpath_buf, linkpath_size+1);
} while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0);
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", linkpath);
#endif
free(plugin_entry_symbol);
up = dlsym(plugin_handle, plugin_entry_symbol);
char *slash = uwsgi_get_last_char(linkpath, '/');
if (!slash) {
slash = linkpath;
}
else {
slash++;
}
plugin_entry_symbol = uwsgi_concat2n(slash, strlen(slash)-3, "",0);
up = dlsym(plugin_handle, plugin_entry_symbol);
}
}
if (up) {
if (!up->name) {
uwsgi_log("the loaded plugin (%s) has no .name attribute\n", plugin_name);
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
free(plugin_entry_symbol);
return NULL;
}
if (plugin_already_loaded(up->name)) {
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
free(plugin_entry_symbol);
return NULL;
}
if (has_option) {
struct uwsgi_option *op = up->options;
int found = 0;
while (op && op->name) {
if (!strcmp(has_option, op->name)) {
found = 1;
break;
}
op++;
}
if (!found) {
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
free(plugin_entry_symbol);
return NULL;
}
}
if (modifier != -1) {
fill_plugin_table(modifier, up);
}
else {
fill_plugin_table(up->modifier1, up);
}
return 1;
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
free(plugin_entry_symbol);
if (up->on_load)
up->on_load();
return plugin_handle;
}
uwsgi_log( "%s\n", dlerror());
if (!has_option)
uwsgi_log( "%s\n", dlerror());
}
end:
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
return NULL;
}
int uwsgi_try_autoload(char *option) {
DIR *d;
struct dirent *dp;
// step dir, check for user-supplied plugins directory
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
while(pdir) {
d = opendir(pdir->value);
if (d) {
while ((dp = readdir(d)) != NULL) {
if (uwsgi_endswith(dp->d_name, "_plugin.so")) {
char *filename = uwsgi_concat3(pdir->value, "/", dp->d_name);
if (uwsgi_load_plugin(-1, filename, option)) {
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
free(filename);
closedir(d);
// add new options
build_options();
return 1;
}
free(filename);
}
}
closedir(d);
}
pdir = pdir->next;
}
// last step: search in compile-time plugin_dir
d = opendir(UWSGI_PLUGIN_DIR);
if (!d) return 0;
while((dp = readdir(d)) != NULL) {
if (uwsgi_endswith(dp->d_name, "_plugin.so")) {
char *filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", dp->d_name);
if (uwsgi_load_plugin(-1, filename, option)) {
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
free(filename);
closedir(d);
// add new options
build_options();
return 1;
}
free(filename);
}
}
closedir(d);
return 0;
return -1;
}
+47 -17
View File
@@ -1,28 +1,58 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
/* uwsgi ADMIN|10 */
int uwsgi_request_admin(struct wsgi_request *wsgi_req) {
uint32_t opt_value = 0;
int i;
ssize_t len;
if (wsgi_req->uh.pktsize >= 4) {
if (wsgi_req->uh.pktsize != 0 && wsgi_req->uh.pktsize != 4)
return UWSGI_OK;
// write request
if (wsgi_req->uh.pktsize == 4) {
memcpy(&opt_value, wsgi_req->buffer, 4);
// TODO: check endianess ?
}
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
// ACK
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
i = write(wsgi_req->poll.fd, wsgi_req, 4);
if (i != 4) {
uwsgi_error("write()");
}
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
// ACK
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
len = write(wsgi_req->poll.fd, wsgi_req, 4);
if (len != 4) {
uwsgi_error("write()");
}
}
// get request
else {
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh.modifier2, uwsgi.shared->options[wsgi_req->uh.modifier2]);
wsgi_req->uh.modifier1 = 10;
wsgi_req->uh.pktsize = 4;
len = write(wsgi_req->poll.fd, wsgi_req, 4);
if (len != 4) {
uwsgi_error("write()");
return UWSGI_OK;
}
len = write(wsgi_req->poll.fd, (char *) &uwsgi.shared->options[wsgi_req->uh.modifier2], 4);
if (len != 4) {
uwsgi_error("write()");
}
}
return UWSGI_OK;
}
struct uwsgi_plugin admin_plugin = {
.name = "admin",
.modifier1 = 10,
.request = uwsgi_request_admin,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='admin'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['admin_plugin']
+105
View File
@@ -0,0 +1,105 @@
#include "../../uwsgi.h"
void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) data;
uint64_t tmp_vallen = 0;
if (vallen > 0) {
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && tmp_vallen > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("cache value size: %llu\n", tmp_vallen);
#endif
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
}
}
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && vallen > 0) {
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
}
else {
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\n<h1>Not Found</h1>", 44);
}
}
}
}
int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uint64_t vallen = 0;
char *value;
char *argv[3];
uint16_t argvs[3];
uint8_t argc = 0;
switch(wsgi_req->uh.modifier2) {
case 0:
// get
if (wsgi_req->uh.pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh.pktsize = vallen;
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, value, vallen);
}
}
break;
case 1:
// set
if (wsgi_req->uh.pktsize > 0) {
argc = 3;
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, argvs, &argc)) {
if (argc > 1) {
uwsgi_cache_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0);
}
}
}
break;
case 2:
// del
if (wsgi_req->uh.pktsize > 0) {
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize, 0);
}
break;
case 3:
case 4:
// dict
if (wsgi_req->uh.pktsize > 0) {
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh.pktsize, cache_command, (void *) wsgi_req);
}
break;
case 5:
// get (uwsgi + stream)
if (wsgi_req->uh.pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, value, vallen);
}
else {
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
}
}
break;
}
return 0;
}
struct uwsgi_plugin cache_plugin = {
.name = "cache",
.modifier1 = 111,
.request = uwsgi_cache_request,
};
@@ -1,7 +1,7 @@
NAME='proxy'
NAME='cache'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['proxy']
GCC_LIST = ['cache']

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