Compare commits

..
429 Commits
Author SHA1 Message Date
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
147 changed files with 12934 additions and 6820 deletions
+8
View File
@@ -42,3 +42,11 @@ 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
+1
View File
@@ -17,3 +17,4 @@ Charles Duffy
Lukas Lalinsky
Steven Fernandez
Łukasz Mierzwa
Roy Marples
+27
View File
@@ -1,3 +1,30 @@
*** 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]
-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));
+12 -1
View File
@@ -2,7 +2,7 @@
*** uWSGI/mod_uwsgi ***
Copyright 2009-2011 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>
@@ -346,7 +353,11 @@ static int uwsgi_handler(request_rec *r) {
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) {
+7 -3
View File
@@ -1,5 +1,5 @@
[uwsgi]
xml = true
xml = auto
ini = true
yaml = true
json = auto
@@ -15,19 +15,20 @@ threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = auto
pcre = auto
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, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket
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
@@ -35,6 +36,9 @@ event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+4 -4
View File
@@ -2,7 +2,7 @@
xml = true
ini = true
yaml = true
json = true
json = false
sqlite3 = false
zeromq = false
snmp = false
@@ -15,12 +15,12 @@ threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = true
pcre = false
pcre = true
routing = true
debug = false
unbit = true
xml_implementation = libxml2
xml_implementation = expat
yaml_implementation = auto
malloc_implementation = libc
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
+31 -7
View File
@@ -83,8 +83,7 @@ void uwsgi_init_cache() {
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
uwsgi.cache_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.cache_lock);
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
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);
@@ -112,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;
@@ -128,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;
}
@@ -155,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;
@@ -178,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");
@@ -189,6 +209,7 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
uci->djbhash = 0;
uci->prev = 0;
uci->next = 0;
uci->expires = 0;
}
return ret;
@@ -263,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;
+10 -2
View File
@@ -2,7 +2,15 @@
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;
@@ -31,8 +39,8 @@ void cluster_setup() {
else if (rlen > 0) {
// receive the packet
char clusterbuf[4096];
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, manage_string_opt, NULL)) {
uwsgi_configure();
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
uwsgi_configure(-1);
goto options_parsed;
}
else {
+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;
}
+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
+49 -5
View File
@@ -336,7 +336,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
}
counter = 4;
struct uwsgi_config_template *uct = uwsgi.vassals_templates;
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
while(uct) {
counter+=2;
uct = uct->next;
@@ -352,6 +352,9 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
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"))
@@ -368,19 +371,46 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
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->filename;
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<sysconf(_SC_OPEN_MAX);i++) {
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);
}
@@ -435,6 +465,7 @@ void emperor_loop() {
int nevents;
int interesting_fd;
char notification_message[64];
struct rlimit rl;
uwsgi.emperor_stats_fd = -1;
@@ -446,6 +477,13 @@ void emperor_loop() {
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
if (getrlimit(RLIMIT_NOFILE, &rl)) {
uwsgi_error("getrlimit()");
exit(1);
}
uwsgi.max_fd = rl.rlim_cur;
emperor_queue = event_queue_init();
@@ -515,7 +553,11 @@ reconnect:
exit(1);
}
globfree(&g);
emperor_absolute_dir = realpath(".", NULL);
emperor_absolute_dir = uwsgi_malloc(PATH_MAX+1);
if (realpath(".", emperor_absolute_dir) == NULL) {
uwsgi_error("realpath()");
exit(1);
}
}
ui = &ui_base;
@@ -627,7 +669,9 @@ reconnect:
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
emperor_del(ui_current);
if (!ui_current->config_len) {
emperor_del(ui_current);
}
}
else {
if (byte == 17) {
+5 -2
View File
@@ -172,6 +172,7 @@ int event_queue_init() {
int epfd;
epfd = epoll_create(256);
if (epfd < 0) {
@@ -403,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;
@@ -443,7 +445,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) {
+101 -78
View File
@@ -2,121 +2,76 @@
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 = uwsgi_fork(name);
if (gw_pid < 0) {
uwsgi_error("fork()");
return NULL;
}
if (!uwsgi.master_process) {
if (gw_pid > 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
if (!uwsgi.sockets) {
// wait for child end
//waitpid(-1, &i, 0);
}
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = orig_pid;
}
else {
if (gw_pid == 0) {
if (uwsgi.master_as_root) uwsgi_as_root();
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = gw_pid;
}
ug->name = name;
ug->loop = loop;
ug->num = num;
uwsgi_log( "spawned %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 = uwsgi_fork(ug->name);
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);
}
@@ -131,3 +86,71 @@ void gateway_respawn(int id) {
}
}
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;
}
+18 -1
View File
@@ -1,6 +1,23 @@
import uwsgi
#uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
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(10)
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>
+2 -2
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;
}
+13 -37
View File
@@ -108,56 +108,37 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct option *aopt, *lopt;
struct uwsgi_option *op = uwsgi.options;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
static int counter = 30000000;
*count = 0;
lopt = uwsgi.long_options;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*uwsgi_count_options(op));
while( (aopt = lopt) ) {
if (!aopt->name)
break;
while( op && op->name ) {
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
uwsgi_name_to_ldap((char *)op->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry) goto next;
if (aopt->flag) {
entry = &ule[*count] ;
entry->num = counter;
strcpy(entry->names, ldap_name);
counter++;
*count = *count+1;
}
else {
entry = get_ldap_by_num(ule, aopt->val, *count);
if (entry) {
strcat(entry->names, ldap_name);
}
else {
entry = &ule[*count] ;
entry->num = aopt->val;
strcpy(entry->names, ldap_name);
*count = *count+1;
}
}
entry = &ule[*count] ;
entry->num = *count;
strcpy(entry->names, ldap_name);
*count = *count+1;
entry->has_arg = aopt->has_arg;
entry->has_arg = op->type;
next:
lopt++;
op++;
}
return ule;
}
void uwsgi_ldap_schema_dump_ldif() {
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
int i;
int items;
@@ -210,7 +191,7 @@ void uwsgi_ldap_schema_dump_ldif() {
exit(0);
}
void uwsgi_ldap_schema_dump() {
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
int i;
int items;
@@ -258,7 +239,7 @@ void uwsgi_ldap_schema_dump() {
exit(0);
}
void uwsgi_ldap_config() {
void uwsgi_ldap_config(char *url) {
LDAP *ldp;
LDAPMessage *results, *entry;
@@ -267,7 +248,6 @@ void uwsgi_ldap_config() {
char *attr;
char *uwsgi_attr;
char *url = "ldap:///";
char *url_slash;
int desired_version = LDAP_VERSION3;
@@ -275,10 +255,6 @@ void uwsgi_ldap_config() {
LDAPURLDesc *ldap_url;
if (uwsgi.ldap) {
url = uwsgi.ldap;
}
if (!ldap_is_ldap_url(url)) {
uwsgi_log("invalid LDAP url.\n");
exit(1);
+3 -34
View File
@@ -27,22 +27,6 @@ struct amqp_frame_method {
static char *amqp_simple_get_frame(int, struct amqp_frame_header *);
static char *amqp_get_method(int, uint16_t, uint16_t, uint32_t *);
/*
static char *amqp_get_longstr(char *ptr, char *watermark) {
uint32_t longstr_size;
if (ptr+4 > watermark) return NULL;
memcpy(&longstr_size, ptr, 4);
longstr_size = ntohl(longstr_size);
if (ptr+4+longstr_size > watermark) return NULL;
return ptr+4+longstr_size;
}
*/
static char *amqp_get_str(char *ptr, char *watermark) {
uint8_t str_size;
@@ -58,23 +42,6 @@ static char *amqp_get_str(char *ptr, char *watermark) {
}
/*
static char *amqp_get_table(char *ptr, char *watermark) {
uint32_t table_size;
if (ptr+4 > watermark) return NULL;
memcpy(&table_size, ptr, 4);
table_size = ntohl(table_size);
if (ptr+4+table_size > watermark) return NULL;
return ptr+4+table_size;
}
*/
static char *amqp_get_short(char *ptr, char *watermark, uint16_t *sv) {
uint16_t tmp_short;
@@ -197,7 +164,9 @@ char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
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;
@@ -501,7 +470,7 @@ static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
len = 0;
char *frame = malloc(fh->size+1);
char *frame = uwsgi_malloc(fh->size+1);
ptr = frame;
while(len < fh->size+1) {
+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);
}
}
}
}
}
+16
View File
@@ -33,6 +33,22 @@ void linux_namespace_start(void *argv) {
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) {
+428 -96
View File
@@ -1,217 +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)
#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_mutexattr_t) + sizeof(pthread_mutex_t)
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutex_t)
#else
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
#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;
}
void uwsgi_rlock(void *lock) {
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
uwsgi_lock(lock);
return uwsgi_lock_fast_check(uli);
#else
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
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_wlock(void *lock) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock(lock);
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_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
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_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_rwunlock(void *lock) {
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_unlock(lock);
uwsgi_lock_fast(uli);
#else
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
pthread_rwlock_wrlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
#endif
}
void uwsgi_lock(void *lock) {
pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_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_unlock(void *lock) {
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
void uwsgi_rwlock_init(void *lock) {
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock_init(lock);
return uwsgi_lock_fast_init(id);
#else
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
pthread_rwlockattr_t attr;
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
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);
void uwsgi_lock_init(void *lock) {
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);
}
FILE *tf = tmpfile();
int fd;
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));
if (!tf) {
uwsgi_error_open("temp lock file");
semu.val = 1;
if (semctl(semid, 0, SETVAL, semu)) {
uwsgi_error("semctl()");
exit(1);
}
fd = fileno(tf);
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;
}
+139 -54
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;
@@ -45,10 +136,12 @@ void log_request(struct wsgi_request *wsgi_req) {
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->do_not_log)
return;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi_apps[wsgi_req->app_id];
@@ -58,7 +151,7 @@ void log_request(struct wsgi_request *wsgi_req) {
}
#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
@@ -67,8 +160,15 @@ void log_request(struct wsgi_request *wsgi_req) {
if (wsgi_req->status == -17) {
via = msg3;
}
else if (wsgi_req->status == -30) {
via = msg4;
}
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
#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;
@@ -93,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;
@@ -107,35 +204,16 @@ 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(uint64_t *rss, uint64_t *vsz) {
void get_memusage(uint64_t * rss, uint64_t * vsz) {
#ifdef UNBIT
*vsz = syscall(356);
@@ -146,7 +224,7 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
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 *) 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);
}
@@ -157,7 +235,7 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
procfd = open("/proc/self/psinfo", O_RDONLY);
if (procfd >= 0) {
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
if (read(procfd, (char *) &info, sizeof(info)) > 0) {
*rss = (uint64_t) info.pr_rssize * 1024;
*vsz = (uint64_t) info.pr_size * 1024;
}
@@ -193,6 +271,13 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
*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;
@@ -215,9 +300,9 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
*vsz = 0;
*rss = 0;
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
while (get_next_area_info(0, &cookie, &ai) == B_OK) {
*vsz += ai.ram_size;
if ( (ai.protection & B_WRITE_AREA) != 0) {
if ((ai.protection & B_WRITE_AREA) != 0) {
*rss += ai.ram_size;
}
}
@@ -225,27 +310,27 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
}
void uwsgi_register_logger(char *name, ssize_t (*func)(struct uwsgi_logger *, char *, size_t)) {
void uwsgi_register_logger(char *name, ssize_t(*func) (struct uwsgi_logger *, char *, size_t)) {
struct uwsgi_logger *ul = uwsgi.loggers, *old_ul;
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;
}
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 = uwsgi_malloc(sizeof(struct uwsgi_logger));
old_ul->next = ul;
}
ul->name = name;
ul->func = func;
ul->next = NULL;
ul->name = name;
ul->func = func;
ul->next = NULL;
ul->configured = 0;
ul->fd = -1;
ul->data = NULL;
@@ -259,11 +344,11 @@ void uwsgi_register_logger(char *name, ssize_t (*func)(struct uwsgi_logger *, ch
struct uwsgi_logger *uwsgi_get_logger(char *name) {
struct uwsgi_logger *ul = uwsgi.loggers;
while(ul) {
while (ul) {
if (!strcmp(ul->name, name)) {
return ul;
}
ul = ul->next;
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=
+9 -3
View File
@@ -40,9 +40,9 @@ 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;
@@ -55,8 +55,11 @@ void *simple_loop(void *arg1) {
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);
}
@@ -128,8 +131,11 @@ void *zeromq_loop(void *arg1) {
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);
}
+260 -304
View File
@@ -68,7 +68,7 @@ void expire_rb_timeouts(struct rb_root *root) {
}
}
void master_log(void) {
int uwsgi_master_log(void) {
char log_buf[4096];
@@ -81,21 +81,66 @@ void master_log(void) {
rlen = write(uwsgi.original_log_fd, log_buf, rlen);
}
// TODO allow uwsgi.logger = func
return 0;
}
return -1;
}
void *logger_thread_loop(void *noarg) {
struct pollfd logpoll;
// block all signals
sigset_t smask;
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
logpoll.events = POLLIN;
logpoll.fd = uwsgi.shared->worker_log_pipe[0];
for(;;) {
int ret = poll(&logpoll, 1, -1);
if (ret > 0 && logpoll.revents & POLLIN) {
master_log();
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
uwsgi_master_log();
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
}
}
return NULL;
}
void *cache_sweeper_loop(void *noarg) {
int i;
// block all signals
sigset_t smask;
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
if (!uwsgi.cache_expire_freq) uwsgi.cache_expire_freq = 3;
// remove expired cache items TODO use rb_tree timeouts
for(;;) {
sleep(uwsgi.cache_expire_freq);
uint64_t freed_items = 0;
// skip the first slot
for (i = 1; i < (int) uwsgi.cache_max_items; i++) {
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi.cache_items[i].expires) {
if (uwsgi.cache_items[i].expires < (uint64_t) uwsgi.current_time) {
uwsgi_cache_del(NULL, 0, i);
freed_items++;
}
}
uwsgi_rwunlock(uwsgi.cache_lock);
}
if (uwsgi.cache_report_freed_items && freed_items > 0) {
uwsgi_log("freed %llu cache items\n", (unsigned long long) freed_items);
}
};
return NULL;
}
void uwsgi_subscribe(char *subscription, uint8_t cmd) {
@@ -218,6 +263,29 @@ void get_linux_tcp_info(int fd) {
}
}
}
#include <linux/sockios.h>
#ifdef UNBIT
#define SIOBKLGQ 0x8908
#endif
#ifdef SIOBKLGQ
void get_linux_unbit_SIOBKLGQ(int fd) {
int queue = 0;
if (ioctl(fd, SIOBKLGQ, &queue) >= 0) {
uwsgi.shared->load = queue;
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS] = queue;
if (queue >= uwsgi.listen_queue) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%d/%d) ***\n", fd, queue, uwsgi.listen_queue);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
}
}
#endif
#endif
@@ -244,6 +312,7 @@ int master_loop(char **argv, char **environ) {
uint64_t last_request_count = 0;
pthread_t logger_thread;
pthread_t cache_sweeper;
#ifdef UWSGI_UDP
struct sockaddr_in udp_client;
@@ -270,8 +339,6 @@ int master_loop(char **argv, char **environ) {
int rlen;
int check_interval = 1;
uint64_t overload_count = 0;
uint64_t idle_count = 0;
struct uwsgi_rb_timer *min_timeout;
struct rb_root *rb_timers = uwsgi_init_rb_timer();
@@ -315,14 +382,15 @@ int master_loop(char **argv, char **environ) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]);
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("adding %d to signal poll (spooler)\n", uwsgi.shared->spooler_signal_pipe[0]);
#endif
if (uwsgi.spoolers) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
}
#endif
if (uwsgi.mules_cnt > 0) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->mule_signal_pipe[0]);
}
if (uwsgi.log_master) {
if (!uwsgi.threaded_logger) {
#ifdef UWSGI_DEBUG
@@ -340,6 +408,16 @@ int master_loop(char **argv, char **environ) {
}
}
if (uwsgi.cache_max_items > 0 && !uwsgi.cache_no_expire) {
if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, NULL)) {
uwsgi_error("pthread_create()");
uwsgi_log("unable to run the cache sweeper !!!\n");
}
else {
uwsgi_log("cache sweeper thread enabled\n");
}
}
uwsgi.wsgi_req->buffer = uwsgi.async_buf[0];
@@ -492,9 +570,9 @@ int master_loop(char **argv, char **environ) {
uwsgi_mule(i + 1);
}
// spawn fat gateways
for (i = 0; i < uwsgi.gateways_cnt; i++) {
if (uwsgi.gateways[i].pid == 0) {
// spawn gateways
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways[i].pid == 0) {
gateway_respawn(i);
}
}
@@ -530,20 +608,36 @@ int master_loop(char **argv, char **environ) {
}
}
struct uwsgi_string_list *touch_reload = uwsgi.touch_reload;
while (touch_reload) {
struct stat tr_st;
if (stat(touch_reload->value, &tr_st)) {
uwsgi_log("unable to stat() %s, reload will be triggered as soon as the file is created\n", touch_reload->value);
touch_reload->custom = 0;
// update touches timestamps
uwsgi_check_touches(uwsgi.touch_reload);
uwsgi_check_touches(uwsgi.touch_logrotate);
uwsgi_check_touches(uwsgi.touch_logreopen);
// setup cheaper algos
uwsgi_register_cheaper_algo("spare", uwsgi_cheaper_algo_spare);
uwsgi_register_cheaper_algo("backlog", uwsgi_cheaper_algo_backlog);
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
if (uwsgi.requested_cheaper_algo) {
uwsgi.cheaper_algo = NULL;
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
while(uca) {
if (!strcmp(uca->name, uwsgi.requested_cheaper_algo)) {
uwsgi.cheaper_algo = uca->func;
break;
}
uca = uca->next;
}
else {
touch_reload->custom = (uint64_t) tr_st.st_mtime;
if (!uwsgi.cheaper_algo) {
uwsgi_log("unable to find requested cheaper algorithm, falling back to spare\n");
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
}
touch_reload = touch_reload->next;
}
// here really starts the master loop
for (;;) {
//uwsgi_log("ready_to_reload %d %d\n", ready_to_reload, uwsgi.numproc);
@@ -552,7 +646,7 @@ int master_loop(char **argv, char **environ) {
uwsgi.gp[i]->master_cycle();
}
}
for (i = 0; i < 0xFF; i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->master_cycle) {
uwsgi.p[i]->master_cycle();
}
@@ -634,76 +728,13 @@ int master_loop(char **argv, char **environ) {
// cheaper management
if (uwsgi.cheaper && !uwsgi.cheap && !uwsgi.to_heaven && !uwsgi.to_hell) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
if (uwsgi.workers[i].busy == 0) {
if (overload_count > 0)
overload_count--;
goto healthy;
}
}
}
overload_count++;
idle_count = 0;
}
healthy:
if (uwsgi.cheaper && !uwsgi.cheap && !uwsgi.to_heaven && !uwsgi.to_hell) {
if (overload_count > 3) {
// activate the first available worker
int decheaped = 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;
overload_count = 0;
decheaped++;
if (decheaped >= uwsgi.cheaper_step)
break;
}
}
}
else if (overload_count == 0) {
// how many active workers ?
idle_count++;
int active_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
active_workers++;
}
}
// find the oldest worker and cheap it
if (active_workers > uwsgi.cheaper_count + 1 || (idle_count > 60 && active_workers > uwsgi.cheaper_count)) {
time_t oldest_worker_spawn = INT_MAX;
int oldest_worker = 0;
idle_count = 0;
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);
overload_count = 0;
}
}
}
if (!uwsgi_calc_cheaper()) return 0;
}
if ((uwsgi.cheap || ready_to_die >= uwsgi.numproc) && uwsgi.to_hell) {
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for (i = 0; i < (uwsgi.gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
@@ -711,80 +742,18 @@ int master_loop(char **argv, char **environ) {
exit(0);
}
if ((uwsgi.cheap || ready_to_reload >= uwsgi.numproc) && uwsgi.to_heaven) {
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for (i = 0; i < (uwsgi.gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
diedpid = 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 (_SC_OPEN_MAX = %ld)...\n", sysconf(_SC_OPEN_MAX));
for (i = 3; i < sysconf(_SC_OPEN_MAX); 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.original_log_fd > -1) {
if (i == uwsgi.original_log_fd) {
dup2(uwsgi.original_log_fd, 1);
dup2(1, 2);
}
}
if (!found) {
#ifdef __APPLE__
fcntl(i, F_SETFD, FD_CLOEXEC);
#else
close(i);
#endif
}
}
#ifdef UWSGI_AS_SHARED_LIBRARY
uwsgi_reload(argv);
// never here (unless in shared library mode)
return -1;
#else
uwsgi_log("running %s\n", uwsgi.binary_path);
argv[0] = uwsgi.binary_path;
//strcpy (argv[0], uwsgi.binary_path);
execvp(uwsgi.binary_path, argv);
uwsgi_error("execvp()");
// never here
exit(1);
#endif
}
if (!uwsgi.cheap) {
if (uwsgi.numproc > 0 || uwsgi.gateways_cnt > 0 || uwsgi.daemons_cnt > 0) {
if (uwsgi.numproc > 0 || ushared->gateways_cnt > 0 || uwsgi.daemons_cnt > 0) {
master_has_children = 1;
}
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
if (uwsgi.spoolers) {
master_has_children = 1;
}
#endif
@@ -903,7 +872,7 @@ int master_loop(char **argv, char **environ) {
if (uwsgi.log_master && !uwsgi.threaded_logger) {
if (interesting_fd == uwsgi.shared->worker_log_pipe[0]) {
master_log();
uwsgi_master_log();
goto health_cycle;
}
}
@@ -917,51 +886,7 @@ int master_loop(char **argv, char **environ) {
if (uwsgi.zerg_server) {
if (interesting_fd == uwsgi.zerg_server_fd) {
struct sockaddr_un zsun;
socklen_t zsun_len = sizeof(struct sockaddr_un);
int zerg_client = accept(uwsgi.zerg_server_fd, (struct sockaddr *) &zsun, &zsun_len);
if (zerg_client < 0) {
uwsgi_error("zerg: accept()");
continue;
}
struct msghdr zerg_msg;
void *zerg_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * uwsgi_count_sockets(uwsgi.sockets)));
struct iovec zerg_iov;
struct cmsghdr *cmsg;
zerg_iov.iov_base = "uwsgi-zerg";
zerg_iov.iov_len = 10;
zerg_msg.msg_name = NULL;
zerg_msg.msg_namelen = 0;
zerg_msg.msg_iov = &zerg_iov;
zerg_msg.msg_iovlen = 1;
zerg_msg.msg_flags = 0;
zerg_msg.msg_control = zerg_msg_control;
zerg_msg.msg_controllen = CMSG_SPACE(sizeof(int) * uwsgi_count_sockets(uwsgi.sockets));
cmsg = CMSG_FIRSTHDR(&zerg_msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * uwsgi_count_sockets(uwsgi.sockets));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
unsigned char *zerg_fd_ptr = CMSG_DATA(cmsg);
while (uwsgi_sock) {
memcpy(zerg_fd_ptr, &uwsgi_sock->fd, sizeof(int));
zerg_fd_ptr += sizeof(int);
uwsgi_sock = uwsgi_sock->next;
}
if (sendmsg(zerg_client, &zerg_msg, 0) < 0) {
uwsgi_error("sendmsg()");
}
close(zerg_client);
free(zerg_msg_control);
uwsgi_manage_zerg(uwsgi.zerg_server_fd, 0, NULL);
goto health_cycle;
}
}
@@ -980,6 +905,8 @@ int master_loop(char **argv, char **environ) {
}
// reload me
else if (byte == 1) {
// un-lazy the stack to trigger a real reload
uwsgi.lazy = 0;
grace_them_all(0);
}
}
@@ -1058,7 +985,7 @@ int master_loop(char **argv, char **environ) {
// loop the various udp manager until one returns true
udp_managed = 0;
for (i = 0; i < 0xFF; i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->manage_udp) {
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, uwsgi.wsgi_req->buffer, rlen)) {
udp_managed = 1;
@@ -1186,14 +1113,13 @@ int master_loop(char **argv, char **environ) {
else {
uwsgi_log_verbose("lost connection with worker %d\n", i);
close(interesting_fd);
//uwsgi.workers[i].pipe[0] = -1;
}
goto health_cycle;
}
#ifdef UWSGI_SPOOLER
// check for spooler signal
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
if (uwsgi.spoolers) {
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[0]) {
rlen = read(interesting_fd, &uwsgi_signal, 1);
if (rlen < 0) {
@@ -1201,7 +1127,7 @@ int master_loop(char **argv, char **environ) {
}
else if (rlen > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("received uwsgi signal %d from the spooler\n", uwsgi_signal);
uwsgi_log_verbose("received uwsgi signal %d from a spooler\n", uwsgi_signal);
#endif
uwsgi_route_signal(uwsgi_signal);
}
@@ -1211,9 +1137,32 @@ int master_loop(char **argv, char **environ) {
}
goto health_cycle;
}
}
#endif
// check for mules signal
if (uwsgi.mules_cnt > 0) {
if (interesting_fd == uwsgi.shared->mule_signal_pipe[0]) {
rlen = read(interesting_fd, &uwsgi_signal, 1);
if (rlen < 0) {
uwsgi_error("read()");
}
else if (rlen > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("received uwsgi signal %d from a mule\n", uwsgi_signal);
#endif
uwsgi_route_signal(uwsgi_signal);
}
else {
uwsgi_log_verbose("lost connection with a mule\n");
close(interesting_fd);
}
goto health_cycle;
}
}
}
@@ -1223,51 +1172,12 @@ int master_loop(char **argv, char **environ) {
continue;
}
uwsgi.current_time = now;
// checking logsize
if (uwsgi.logfile) {
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) {
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;
}
char message[1024];
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) {
rlen = write(uwsgi.original_log_fd, message, ret);
}
if (rename(uwsgi.logfile, rot_name) == 0) {
// close 2, reopen logfile dup'it and 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);
}
}
else {
uwsgi_error("unable to rotate log: rename()");
}
if (need_free)
free(rot_name);
}
uwsgi_check_logrotate();
}
// this will be incremented at (more or less) regular intervals
uwsgi.master_cycles++;
@@ -1323,30 +1233,23 @@ int master_loop(char **argv, char **environ) {
}
}
// remove expired cache items TODO use rb_tree timeouts
if (uwsgi.cache_max_items > 0) {
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi.cache_items[i].expires) {
if (uwsgi.cache_items[i].expires < (uint64_t) uwsgi.current_time) {
uwsgi_cache_del(uwsgi.cache_items[i].key, uwsgi.cache_items[i].keysize);
}
}
uwsgi_rwunlock(uwsgi.cache_lock);
}
}
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!check_interval)
check_interval = 1;
#ifdef __linux__
// get listen_queue status
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_INET) {
get_linux_tcp_info(uwsgi_sock->fd);
}
#ifdef SIOBKLGQ
else if (uwsgi_sock->family == AF_UNIX) {
get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd);
}
#endif
uwsgi_sock = uwsgi_sock->next;
}
#endif
@@ -1393,10 +1296,13 @@ int master_loop(char **argv, char **environ) {
#endif
}
kill(uwsgi.workers[i].pid, SIGUSR2);
// allow SIGUSR2 to be delivered
sleep(1);
kill(uwsgi.workers[i].pid, SIGKILL);
if (uwsgi.workers[i].pid > 0) {
kill(uwsgi.workers[i].pid, SIGUSR2);
// allow SIGUSR2 to be delivered
sleep(1);
kill(uwsgi.workers[i].pid, SIGKILL);
}
// to avoid races
uwsgi.workers[i].harakiri = 0;
}
@@ -1420,6 +1326,18 @@ int master_loop(char **argv, char **environ) {
// need to find a better way
//uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time;
}
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways_harakiri[i] > 0) {
if (ushared->gateways_harakiri[i] < (time_t) uwsgi.current_time) {
if (ushared->gateways[i].pid > 0) {
kill(ushared->gateways[i].pid, SIGKILL);
}
ushared->gateways_harakiri[i] = 0;
}
}
}
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].harakiri > 0) {
if (uwsgi.mules[i].harakiri < (time_t) uwsgi.current_time) {
@@ -1430,12 +1348,14 @@ int master_loop(char **argv, char **environ) {
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.shared->spooler_pid > 0 && uwsgi.shared->spooler_harakiri > 0) {
if (uwsgi.shared->spooler_harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uwsgi.shared->spooler_pid);
kill(uwsgi.shared->spooler_pid, SIGKILL);
uwsgi.shared->spooler_harakiri = 0;
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while(uspool) {
if (uspool->harakiri > 0 && uspool->harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
kill(uspool->pid, SIGKILL);
uspool->harakiri = 0;
}
uspool = uspool->next;
}
#endif
@@ -1457,7 +1377,7 @@ int master_loop(char **argv, char **environ) {
}
// resubscribe every 10 cycles by default
if (uwsgi.subscriptions && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) {
if ((uwsgi.subscriptions && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi.to_heaven && !uwsgi.to_hell) {
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while (subscriptions) {
uwsgi_subscribe(subscriptions->value, 0);
@@ -1480,43 +1400,63 @@ int master_loop(char **argv, char **environ) {
}
// check touch_reload
struct uwsgi_string_list *touch_reload = uwsgi.touch_reload;
while (touch_reload && !uwsgi.to_heaven && !uwsgi.to_hell) {
struct stat tr_st;
if (stat(touch_reload->value, &tr_st)) {
touch_reload->custom = 0;
if (!uwsgi.to_heaven && !uwsgi.to_hell) {
char *touched = uwsgi_check_touches(uwsgi.touch_reload);
if (touched) {
uwsgi_log("*** %s has been touched... grace them all !!! ***\n", touched);
grace_them_all(0);
}
else {
if ((uint64_t) tr_st.st_mtime > touch_reload->custom) {
uwsgi_log("*** %s has been touched... grace them all !!! ***\n", touch_reload->value);
grace_them_all(0);
break;
}
}
touch_reload = touch_reload->next;
}
// now check for lb pool
continue;
}
if (diedpid > 0) {
// check for deadlocks first
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
while(uli) {
if (!uli->can_deadlock) goto nextlock;
pid_t locked_pid = 0;
if (uli->rw) {
locked_pid = uwsgi_rwlock_check(uli);
}
else {
locked_pid = uwsgi_lock_check(uli);
}
if (locked_pid == diedpid) {
uwsgi_log("[deadlock-detector] pid %d was holding lock %s (%p)\n", (int) diedpid, uli->id, uli->lock_ptr);
if (uli->rw) {
uwsgi_rwunlock(uli);
}
else {
uwsgi_unlock(uli);
}
}
nextlock:
uli = uli->next;
}
}
// reload gateways and daemons only on normal workflow
if (!uwsgi.to_heaven && !uwsgi.to_hell) {
#ifdef UWSGI_SPOOLER
/* reload the spooler */
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
if (diedpid == uwsgi.shared->spooler_pid) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
pid_found = 0;
while(uspool) {
if (uspool->pid > 0 && diedpid == uspool->pid) {
uwsgi_log("OOOPS the spooler is no more...trying respawn...\n");
uwsgi.spooler_respawned++;
uwsgi.shared->spooler_pid = spooler_start();
//event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
continue;
uspool->respawned++;
uspool->pid = spooler_start(uspool);
pid_found = 1;
break;
}
uspool = uspool->next;
}
if (pid_found)
continue;
#endif
pid_found = 0;
@@ -1534,10 +1474,9 @@ int master_loop(char **argv, char **environ) {
/* reload the gateways */
// TODO reload_gateway(diedpid);
pid_found = 0;
for (i = 0; i < uwsgi.gateways_cnt; i++) {
if (uwsgi.gateways[i].pid == diedpid) {
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways[i].pid == diedpid) {
gateway_respawn(i);
pid_found = 1;
break;
@@ -1548,7 +1487,7 @@ int master_loop(char **argv, char **environ) {
continue;
/* reload the daemons */
// TODO reload_gateway(diedpid);
// TODO reload_daemons(diedpid);
pid_found = 0;
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
@@ -1579,11 +1518,13 @@ int master_loop(char **argv, char **environ) {
if (uwsgi.mywid <= 0) {
// check spooler, mules, gateways and daemons
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
if (diedpid == uwsgi.shared->spooler_pid) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while(uspool) {
if (uspool->pid > 0 && diedpid == uspool->pid) {
uwsgi_log("spooler (pid: %d) annihilated\n", (int) diedpid);
goto next;
}
uspool = uspool->next;
}
#endif
@@ -1594,9 +1535,9 @@ int master_loop(char **argv, char **environ) {
}
}
for (i = 0; i < uwsgi.gateways_cnt; i++) {
if (uwsgi.gateways[i].pid == diedpid) {
uwsgi_log("gateway %d (pid: %d) annihilated\n", i + 1, (int) diedpid);
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways[i].pid == diedpid) {
uwsgi_log("gateway %d (%s, pid: %d) annihilated\n", i + 1, ushared->gateways[i].fullname, (int) diedpid);
goto next;
}
}
@@ -1647,23 +1588,37 @@ int master_loop(char **argv, char **environ) {
uwsgi.workers[uwsgi.mywid].harakiri = 0;
}
if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) {
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
// noop
}
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
}
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
uwsgi.workers[uwsgi.mywid].pid = 0;
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
uwsgi.workers[uwsgi.mywid].harakiri = 0;
continue;
}
gettimeofday(&last_respawn, NULL);
if (last_respawn.tv_sec == uwsgi.respawn_delta) {
if (last_respawn.tv_sec <= uwsgi.respawn_delta + check_interval) {
last_respawn_rate++;
if (last_respawn_rate > uwsgi.numproc) {
uwsgi_log("worker respawning too fast !!! i have to sleep a bit...\n");
/* TODO, user configurable fork throttler */
sleep(2);
if (uwsgi.forkbomb_delay > 0) {
uwsgi_log("worker respawning too fast !!! i have to sleep a bit (%d seconds)...\n", uwsgi.forkbomb_delay);
/* use --forkbomb-delay 0 to disable sleeping */
sleep(uwsgi.forkbomb_delay);
}
last_respawn_rate = 0;
}
}
@@ -1679,4 +1634,5 @@ int master_loop(char **argv, char **environ) {
}
}
// never here
}
+586 -137
View File
@@ -2,7 +2,332 @@
extern struct uwsgi_server uwsgi;
void worker_wakeup() {}
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() {
@@ -33,7 +358,7 @@ void master_check_cluster_nodes() {
}
}
void uwsgi_fixup_fds(int wid, int muleid) {
void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
int i;
@@ -43,48 +368,82 @@ void uwsgi_fixup_fds(int wid, int muleid) {
}
if (uwsgi.master_process) {
// fix the communication pipe
close(uwsgi.shared->worker_signal_pipe[0]);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].signal_pipe[0] != -1) close(uwsgi.workers[i].signal_pipe[0]);
if (i != wid) {
if (uwsgi.workers[i].signal_pipe[1] != -1) close(uwsgi.workers[i].signal_pipe[1]);
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.shared->spooler_pid != getpid()) {
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
if (uwsgi.shared->spooler_signal_pipe[1] != -1) close (uwsgi.shared->spooler_signal_pipe[1]);
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 (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.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]);
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]);
}
}
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) {
@@ -92,6 +451,10 @@ 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) {
@@ -108,7 +471,7 @@ int uwsgi_respawn_worker(int wid) {
// 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].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;
@@ -121,18 +484,18 @@ int uwsgi_respawn_worker(int wid) {
// reset the apps count with a copy from the master
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
uwsgi_fixup_fds(wid, 0);
uwsgi_fixup_fds(wid, 0, NULL);
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
if (uwsgi.master_process) {
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
}
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;
@@ -149,6 +512,11 @@ int uwsgi_respawn_worker(int wid) {
}
}
if (uwsgi.threaded_logger) {
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
}
return 0;
}
@@ -158,8 +526,7 @@ void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi.current_time = now;
uwsgi_cron_delta = localtime(&uwsgi.current_time);
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
@@ -178,20 +545,36 @@ void uwsgi_manage_signal_cron(time_t now) {
uc_month = ucron->month;
uc_week = ucron->week;
if (ucron->minute == -1)
uc_minute = uwsgi_cron_delta->tm_min;
if (ucron->hour == -1)
uc_hour = uwsgi_cron_delta->tm_hour;
if (ucron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (ucron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
// 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 != -1 && ucron->week != -1) {
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;
}
@@ -205,9 +588,9 @@ void uwsgi_manage_signal_cron(time_t now) {
if (run_task == 1) {
// date match, signal it ?
if (uwsgi.current_time - ucron->last_job > 60) {
if (now - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = uwsgi.current_time;
ucron->last_job = now;
}
}
@@ -227,8 +610,7 @@ void uwsgi_manage_command_cron(time_t now) {
struct uwsgi_cron *current_cron = uwsgi.crons;
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uwsgi.current_time = now;
uwsgi_cron_delta = localtime(&uwsgi.current_time);
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
@@ -236,8 +618,10 @@ void uwsgi_manage_command_cron(time_t now) {
return;
}
while (current_cron) {
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
uc_minute = current_cron->minute;
uc_hour = current_cron->hour;
@@ -245,42 +629,58 @@ void uwsgi_manage_command_cron(time_t now) {
uc_month = current_cron->month;
uc_week = current_cron->week;
if (current_cron->minute == -1)
uc_minute = uwsgi_cron_delta->tm_min;
if (current_cron->hour == -1)
uc_hour = uwsgi_cron_delta->tm_hour;
if (current_cron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (current_cron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (current_cron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
// 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 != -1 && current_cron->week != -1) {
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;
}
}
// 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) {
if (run_task == 1) {
// date match, run command ?
if (uwsgi.current_time - current_cron->last_job > 60) {
if (now - current_cron->last_job > 60) {
//call command
if (current_cron->command) {
if (uwsgi_run_command(current_cron->command) >=0) {
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 = uwsgi.current_time;
current_cron->last_job = now;
}
}
@@ -297,7 +697,7 @@ void uwsgi_manage_command_cron(time_t now) {
void uwsgi_send_stats(int fd) {
int i,j;
int i, j;
struct sockaddr_un client_src;
struct uwsgi_app *ua;
socklen_t client_src_len = 0;
@@ -317,14 +717,15 @@ void uwsgi_send_stats(int fd) {
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
#ifdef __linux__
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
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()));
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);
@@ -333,9 +734,8 @@ void uwsgi_send_stats(int fd) {
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);
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 {
@@ -346,57 +746,76 @@ void uwsgi_send_stats(int fd) {
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, "\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);
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\", ");
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].suspended) {
fprintf(output,"\"status\": \"pause\", ");
}
else {
if (uwsgi.workers[i + 1].sig) {
fprintf(output,"\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
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\", ");
}
}
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("\"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);
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");
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{ ");
for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
ua = &uwsgi.workers[i + 1].apps[j];
fprintf(output, "\t\t{ ");
fprintf(output, "\"id\": %d, ", j);
fprintf(output, "\"modifier1\": %d, ", ua->modifier1);
fprintf(output, "\"mountpoint\": \"%.*s\", ", ua->mountpoint_len, ua->mountpoint);
stats_send_llu( "\"requests\": %llu, ", ua->requests);
stats_send_llu( "\"exceptions\": %llu, ", ua->exceptions);
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);
@@ -404,25 +823,55 @@ void uwsgi_send_stats(int fd) {
else {
fprintf(output, "\"chdir\": \"\" ");
}
if (j == uwsgi.workers[i+1].apps_cnt-1) {
fprintf(output,"}\n");
if (j == uwsgi.workers[i + 1].apps_cnt - 1) {
fprintf(output, "}\n");
}
else {
fprintf(output,"},\n");
fprintf(output, "},\n");
}
}
fprintf(output,"\t\t]");
fprintf(output, "\t\t]");
if (i == uwsgi.numproc-1) {
fprintf(output,"}\n");
if (i == uwsgi.numproc - 1) {
fprintf(output, "}\n");
}
else {
fprintf(output,"},\n");
fprintf(output, "},\n");
}
}
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>
+26 -5
View File
@@ -41,20 +41,20 @@ void uwsgi_mule(int id) {
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = getpid();
uwsgi_fixup_fds(0, id);
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 < 0xFF; i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
for (i = 0; i < 0xFF; i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
@@ -62,7 +62,7 @@ void uwsgi_mule(int id) {
if (uwsgi.mules[id-1].patch) {
for (i = 0; i < 0xFF; i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
// never here
@@ -184,7 +184,7 @@ void uwsgi_mule_handler() {
}
else {
int i,found = 0;
for(i=0;i<0xff;i++) {
for(i=0;i<256;i++) {
if (uwsgi.p[i]->mule_msg) {
if (uwsgi.p[i]->mule_msg(message, len)) {
found = 1;
@@ -356,3 +356,24 @@ clear:
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);
}
+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>
+170 -49
View File
@@ -2,30 +2,16 @@
extern struct uwsgi_server uwsgi;
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option, int absolute) {
void *plugin_handle;
char *plugin_name;
char *plugin_entry_symbol;
struct uwsgi_plugin *up;
char linkpath_buf[1024], linkpath[1024];
int linkpath_size;
static int plugin_already_loaded(const char *plugin) {
int i;
char *colon = strchr(plugin, ':');
if (colon) {
colon[0] = 0;
}
check:
for (i = 0; i < 0xFF; i++) {
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
return NULL;
return 1;
}
}
if (uwsgi.p[i]->alias) {
@@ -33,7 +19,7 @@ check:
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
return 1;
}
}
}
@@ -45,7 +31,7 @@ check:
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
return 1;
}
}
if (uwsgi.gp[i]->alias) {
@@ -53,46 +39,97 @@ check:
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
return 1;
}
}
}
return 0;
}
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;
struct uwsgi_plugin *up;
char linkpath_buf[1024], linkpath[1024];
int linkpath_size;
char *colon = strchr(plugin_name, ':');
if (colon) {
plugin = colon+1;
colon[0] = 0;
modifier = atoi(plugin_name);
plugin_name = colon+1;
colon[0] = ':';
colon = NULL;
goto check;
}
if (absolute == 1) {
plugin_name = uwsgi_concat2(plugin, "");
// need to fix this... postpone until needed
plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0);
}
else if (absolute == 2) {
plugin_name = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin);
plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0);
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
need_free = 1;
}
else {
plugin_name = uwsgi_concat4(UWSGI_PLUGIN_DIR, "/", plugin, "_plugin.so");
plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin");
}
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
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 {
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_name, linkpath_buf, 1023)) > 0) {
if ((linkpath_size = readlink(plugin_abs_path, linkpath_buf, 1023)) > 0) {
do {
linkpath_buf[linkpath_size] = '\0';
strcpy(linkpath, linkpath_buf);
strncpy(linkpath, linkpath_buf, linkpath_size+1);
} while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0);
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", linkpath);
@@ -111,23 +148,47 @@ check:
}
}
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 option *lopt = up->options, *aopt;
struct uwsgi_option *op = up->options;
int found = 0;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(has_option, aopt->name)) {
while (op && op->name) {
if (!strcmp(has_option, op->name)) {
found = 1;
break;
}
lopt++;
op++;
}
if (!found) {
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
free(plugin_name);
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
free(plugin_entry_symbol);
return NULL;
}
@@ -139,17 +200,77 @@ check:
else {
fill_plugin_table(up->modifier1, up);
}
free(plugin_name);
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());
}
free(plugin_name);
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;
}
+1 -1
View File
@@ -63,7 +63,7 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
case 2:
// del
if (wsgi_req->uh.pktsize > 0) {
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize, 0);
}
break;
case 3:
+68 -41
View File
@@ -2,54 +2,25 @@
extern struct uwsgi_server uwsgi;
#define CARBON_OPT_BASE 178000
#define CARBON_OPT_CARBON CARBON_OPT_BASE+1
#define CARBON_OPT_CARBON_ID CARBON_OPT_BASE+2
#define CARBON_OPT_CARBON_FREQ CARBON_OPT_BASE+3
#define CARBON_OPT_CARBON_TIMEOUT CARBON_OPT_BASE+4
struct uwsgi_carbon {
struct uwsgi_string_list *servers;
int freq;
int timeout;
char *id;
int no_workers;
} u_carbon;
struct option carbon_options[] = {
{"carbon", required_argument, 0, CARBON_OPT_CARBON},
{"carbon-timeout", required_argument, 0, CARBON_OPT_CARBON_TIMEOUT},
{"carbon-freq", required_argument, 0, CARBON_OPT_CARBON_FREQ},
{"carbon-id", required_argument, 0, CARBON_OPT_CARBON_ID},
{0, 0, 0, 0},
struct uwsgi_option carbon_options[] = {
{"carbon", required_argument, 0, "push statistics to the specified carbon server", uwsgi_opt_add_string_list, &u_carbon.servers, UWSGI_OPT_MASTER},
{"carbon-timeout", required_argument, 0, "set carbon connection timeout", uwsgi_opt_set_int, &u_carbon.timeout, 0},
{"carbon-freq", required_argument, 0, "set carbon push frequency", uwsgi_opt_set_int, &u_carbon.freq, 0},
{"carbon-id", required_argument, 0, "set carbon id", uwsgi_opt_set_str, &u_carbon.id, 0},
{"carbon-no-workers", no_argument, 0, "disable generation of single worker metrics", uwsgi_opt_true, &u_carbon.no_workers, 0},
{0, 0, 0, 0, 0, 0, 0},
};
int carbon_init() {
return 0;
}
int carbon_opt(int i, char *optarg) {
switch(i) {
case CARBON_OPT_CARBON:
uwsgi.master_process = 1;
uwsgi_string_new_list(&u_carbon.servers, optarg);
return 1;
case CARBON_OPT_CARBON_ID:
u_carbon.id = optarg;
return 1;
case CARBON_OPT_CARBON_FREQ:
u_carbon.freq = atoi(optarg);
return 1;
case CARBON_OPT_CARBON_TIMEOUT:
u_carbon.timeout = atoi(optarg);
return 1;
}
return 0;
}
void carbon_post_init() {
int i;
@@ -94,30 +65,86 @@ void carbon_master_cycle() {
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
unsigned long long total_rss = 0;
unsigned long long total_vsz = 0;
unsigned long long total_tx = 0;
unsigned long long total_avg_rt = 0; // total avg_rt
unsigned long long avg_rt = 0; // per worker avg_rt reported to carbon
unsigned long long avg_rt_workers = 0; // number of workers used to calculate total avg_rt
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.workers[0].requests, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
if (u_carbon.no_workers) goto gmetrics;
for(i=1;i<=uwsgi.numproc;i++) {
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].requests, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
total_rss += uwsgi.workers[i].rss_size;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].rss_size, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
total_vsz += uwsgi.workers[i].vsz_size;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].vsz_size, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
if (uwsgi.workers[i].cheaped) {
// also if worker is cheaped than we report its average response time as zero, sending last value might be confusing
avg_rt = 0;
}
else {
// global average response time is calcucalted from active/idle workers, cheaped workers are excluded, otherwise it is not accurate
avg_rt = uwsgi.workers[i].avg_response_time;
avg_rt_workers++;
total_avg_rt += uwsgi.workers[i].avg_response_time;
}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) avg_rt, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
total_tx += uwsgi.workers[i].tx;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].tx, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
}
gmetrics:
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_rss, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_vsz, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) (avg_rt_workers ? total_avg_rt / avg_rt_workers : 0), (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_tx, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
clear:
close(fd);
nxt:
usl = usl->next;
}
last_update = time(NULL);
}
}
struct uwsgi_plugin carbon_plugin = {
.name = "carbon",
.options = carbon_options,
.manage_opt = carbon_opt,
.master_cycle = carbon_master_cycle,
.post_init = carbon_post_init,
.init = carbon_init,
};
+175 -92
View File
@@ -5,56 +5,77 @@ extern struct uwsgi_server uwsgi;
struct uwsgi_cgi {
struct uwsgi_dyn_dict *mountpoint;
struct uwsgi_dyn_dict *helpers;
int buffer_size;
size_t buffer_size;
int timeout;
struct uwsgi_string_list *index;
struct uwsgi_string_list *allowed_ext;
struct uwsgi_string_list *unset;
struct uwsgi_string_list *loadlib;
int optimize;
int from_docroot;
int has_mountpoints;
struct uwsgi_dyn_dict *default_cgi;
int path_info;
} uc ;
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 1000)
#define LONG_ARGS_CGI LONG_ARGS_CGI_BASE + 1
#define LONG_ARGS_CGI_MAP_HELPER LONG_ARGS_CGI_BASE + 2
#define LONG_ARGS_CGI_BUFFER_SIZE LONG_ARGS_CGI_BASE + 3
#define LONG_ARGS_CGI_TIMEOUT LONG_ARGS_CGI_BASE + 4
#define LONG_ARGS_CGI_INDEX LONG_ARGS_CGI_BASE + 5
#define LONG_ARGS_CGI_ALLOWED_EXT LONG_ARGS_CGI_BASE + 6
#define LONG_ARGS_CGI_UNSET LONG_ARGS_CGI_BASE + 7
#define LONG_ARGS_CGI_LOADLIB LONG_ARGS_CGI_BASE + 8
void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
struct option uwsgi_cgi_options[] = {
char *val = strchr(value, '=');
if (!val) {
uwsgi_dyn_dict_new(&uc.mountpoint, value, strlen(value), NULL, 0);
}
else {
uwsgi_dyn_dict_new(&uc.mountpoint, value, val-value, val+1, strlen(val+1));
}
{"cgi", required_argument, 0, LONG_ARGS_CGI},
{"cgi-map-helper", required_argument, 0, LONG_ARGS_CGI_MAP_HELPER},
{"cgi-helper", required_argument, 0, LONG_ARGS_CGI_MAP_HELPER},
{"cgi-buffer-size", required_argument, 0, LONG_ARGS_CGI_BUFFER_SIZE},
{"cgi-timeout", required_argument, 0, LONG_ARGS_CGI_TIMEOUT},
{"cgi-index", required_argument, 0, LONG_ARGS_CGI_INDEX},
{"cgi-allowed-ext", required_argument, 0, LONG_ARGS_CGI_ALLOWED_EXT},
{"cgi-unset", required_argument, 0, LONG_ARGS_CGI_UNSET},
{"cgi-loadlib", required_argument, 0, LONG_ARGS_CGI_LOADLIB},
{"cgi-optimize", no_argument, &uc.optimize, 1},
{"cgi-optimized", no_argument, &uc.optimize, 1},
{"cgi-path-info", no_argument, &uc.path_info, 1},
{0, 0, 0, 0},
}
void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
char *val = strchr(value, '=');
if (!val) {
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
exit(1);
}
uwsgi_dyn_dict_new(&uc.helpers, value, val-value, val+1, strlen(val+1));
}
struct uwsgi_option uwsgi_cgi_options[] = {
{"cgi", required_argument, 0, "add a cgi mountpoint/directory/script", uwsgi_opt_add_cgi, NULL, 0},
{"cgi-map-helper", required_argument, 0, "add a cgi map-helper", uwsgi_opt_add_cgi_maphelper, NULL, 0},
{"cgi-helper", required_argument, 0, "add a cgi map-helper", uwsgi_opt_add_cgi_maphelper, NULL, 0},
{"cgi-from-docroot", no_argument, 0, "blindly enable cgi in DOCUMENT_ROOT", uwsgi_opt_true, &uc.from_docroot, 0},
{"cgi-buffer-size", required_argument, 0, "set cgi buffer size", uwsgi_opt_set_64bit, &uc.buffer_size, 0},
{"cgi-timeout", required_argument, 0, "set cgi script timeout", uwsgi_opt_set_int, &uc.timeout, 0},
{"cgi-index", required_argument, 0, "add a cgi index file", uwsgi_opt_add_string_list, &uc.index, 0},
{"cgi-allowed-ext", required_argument, 0, "cgi allowed extension", uwsgi_opt_add_string_list, &uc.allowed_ext, 0},
{"cgi-unset", required_argument, 0, "unset specified environment variables", uwsgi_opt_add_string_list, &uc.unset, 0},
{"cgi-loadlib", required_argument, 0, "load a cgi shared library/optimizer", uwsgi_opt_add_string_list, &uc.loadlib, 0},
{"cgi-optimize", no_argument, 0, "enable cgi realpath() optimizer", uwsgi_opt_true, &uc.optimize, 0},
{"cgi-optimized", no_argument, 0, "enable cgi realpath() optimizer", uwsgi_opt_true, &uc.optimize, 0},
{"cgi-path-info", no_argument, 0, "disable PATH_INFO management in cgi scripts", uwsgi_opt_true, &uc.path_info, 0},
{0, 0, 0, 0, 0, 0, 0},
};
void uwsgi_cgi_404(struct wsgi_request *wsgi_req) {
wsgi_req->status = 404;
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\nNot Found", 35);
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nNot Found", 61);
}
void uwsgi_cgi_403(struct wsgi_request *wsgi_req) {
wsgi_req->status = 403;
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\n\r\nForbidden", 35);
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\nContent-Type: text/plain\r\n\r\nForbidden", 61);
}
@@ -223,6 +244,7 @@ int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
if (buf[i] == '\n') {
// end of headers
if (key == NULL) {
i++;
goto send_body;
}
// invalid header
@@ -365,8 +387,9 @@ char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_f
}
if (choosen_udd->status == 0) {
char *tmp_udd = realpath(path, NULL);
if (!tmp_udd) {
char *tmp_udd = uwsgi_malloc(PATH_MAX+1);
if (!realpath(path, tmp_udd)) {
free(tmp_udd);
return NULL;
}
@@ -399,6 +422,8 @@ int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
int part_size = 0;
struct stat st;
if (wsgi_req->path_info_len == 0) return 0;
if (ptr[0] == '/') part_size++;
for(i=0;i<wsgi_req->path_info_len-discard_base;i++) {
@@ -449,10 +474,12 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
int i;
pid_t cgi_pid;
int waitpid_status;
char *argv[3];
char **argv;
int nargs = 0;
char full_path[PATH_MAX];
char tmp_path[PATH_MAX];
int cgi_pipe[2];
int post_pipe[2];
ssize_t len;
struct stat cgi_stat;
int need_free = 0;
@@ -476,16 +503,24 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
return -1;
}
char *docroot = NULL;
// check for file availability (and 'runnability')
if (uc.from_docroot) {
docroot = wsgi_req->document_root;
docroot_len = wsgi_req->document_root_len;
}
else {
docroot = uwsgi_cgi_get_docroot(wsgi_req->path_info, wsgi_req->path_info_len, &need_free, &is_a_file, &discard_base, &script_name);
if (docroot)
docroot_len = strlen(docroot);
}
char *docroot = uwsgi_cgi_get_docroot(wsgi_req->path_info, wsgi_req->path_info_len, &need_free, &is_a_file, &discard_base, &script_name);
if (docroot == NULL) {
if (docroot == NULL || docroot_len == 0) {
uwsgi_cgi_404(wsgi_req);
return UWSGI_OK;
}
docroot_len = strlen(docroot);
memcpy(full_path, docroot, docroot_len);
if (!is_a_file) {
@@ -533,7 +568,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
if (S_ISDIR(cgi_stat.st_mode)) {
// add / to directories
if (wsgi_req->path_info_len == 0 || wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') {
if (wsgi_req->path_info_len == 0 || (wsgi_req->path_info_len > 0 && wsgi_req->path_info[wsgi_req->path_info_len-1] != '/')) {
uwsgi_cgi_redirect_to_slash(wsgi_req);
if (need_free)
free(docroot);
@@ -548,6 +583,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
// add + 1 to ensure null byte
memcpy(full_path+full_path_len, ci->value, ci->len + 1);
if (!access(full_path, R_OK)) {
found = 1;
break;
}
@@ -563,9 +599,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
}
}
else {
full_path_len = strlen(full_path);
}
full_path_len = strlen(full_path);
int cgi_allowed = 1;
struct uwsgi_string_list *allowed = uc.allowed_ext;
@@ -612,13 +647,32 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
int send_post_data = 0;
if (uwsgi.post_buffering > 0 && wsgi_req->post_cl && !wsgi_req->async_post) {
send_post_data = 1;
if (pipe(post_pipe)) {
if (need_free)
free(docroot);
close(cgi_pipe[0]);
close(cgi_pipe[1]);
uwsgi_error("pipe()");
return UWSGI_OK;
}
}
cgi_pid = fork();
if (cgi_pid < 0) {
uwsgi_error("fork()");
if (need_free)
free(docroot);
return -1;
close(cgi_pipe[0]);
close(cgi_pipe[1]);
if (send_post_data) {
close(post_pipe[0]);
close(post_pipe[1]);
}
return UWSGI_OK;
}
if (cgi_pid > 0) {
@@ -627,6 +681,16 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
free(docroot);
close(cgi_pipe[1]);
if (send_post_data) {
close(post_pipe[0]);
if (write(post_pipe[1], wsgi_req->post_buffering_buf, wsgi_req->post_cl) != (ssize_t) wsgi_req->post_cl) {
uwsgi_error("write()");
close(post_pipe[1]);
goto clear2;
}
close(post_pipe[1]);
}
// wait for data
char *headers_buf = uwsgi_malloc(uc.buffer_size);
char *ptr = headers_buf;
@@ -688,6 +752,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
clear:
free(headers_buf);
clear2:
close(cgi_pipe[0]);
// now wait for process exit/death
@@ -701,13 +766,35 @@ clear:
// close all the fd except wsgi_req->poll.fd and 2;
for(i=0;i< (int)uwsgi.max_fd;i++) {
if (send_post_data) {
if (post_pipe[0] == i) {
continue;
}
}
if (wsgi_req->async_post) {
if (fileno((FILE*)wsgi_req->async_post) == i) {
continue;
}
}
if (i != wsgi_req->poll.fd && i != 2 && i != cgi_pipe[1]) {
close(i);
}
}
// now map wsgi_req->poll.fd to 0 & cgi_pipe[1] to 1
if (wsgi_req->poll.fd != 0) {
// now map wsgi_req->poll.fd (or async_post) to 0 & cgi_pipe[1] to 1
if (send_post_data) {
if (post_pipe[0] != 0) {
dup2(post_pipe[0], 0);
close(post_pipe[0]);
}
}
else if (wsgi_req->async_post) {
if (fileno((FILE*)wsgi_req->async_post) != 0) {
dup2(fileno((FILE*)wsgi_req->async_post), 0);
fclose(wsgi_req->async_post);
}
}
else if (wsgi_req->poll.fd != 0) {
dup2(wsgi_req->poll.fd, 0);
close(wsgi_req->poll.fd);
}
@@ -741,14 +828,21 @@ clear:
uwsgi_error("setenv()");
}
if (path_info && wsgi_req->path_info_len-discard_base > 0) {
if (setenv("PATH_INFO", uwsgi_concat2n(path_info, wsgi_req->path_info_len-discard_base, "", 0), 1)) {
if (path_info) {
size_t pi_len = wsgi_req->path_info_len - (path_info - wsgi_req->path_info);
if (setenv("PATH_INFO", uwsgi_concat2n(path_info, pi_len, "", 0), 1)) {
uwsgi_error("setenv()");
}
if (setenv("PATH_TRANSLATED", uwsgi_concat4n(docroot, docroot_len, "/", 1, path_info, wsgi_req->path_info_len-discard_base, "", 0) , 1)) {
if (setenv("PATH_TRANSLATED", uwsgi_concat3n(docroot, docroot_len, path_info, pi_len, "", 0) , 1)) {
uwsgi_error("setenv()");
}
}
else {
unsetenv("PATH_INFO");
@@ -779,7 +873,7 @@ clear:
uwsgi_error("setenv()");
}
if (setenv("SCRIPT_NAME", full_path+(docroot_len-discard_base), 1)) {
if (setenv("SCRIPT_NAME", uwsgi_concat2n(wsgi_req->path_info, discard_base, full_path+docroot_len, strlen(full_path+docroot_len)), 1)) {
uwsgi_error("setenv()");
}
@@ -805,6 +899,41 @@ clear:
drop_env = drop_env->next;
}
argv = uwsgi_malloc(sizeof(char *) * 3);
// check if we need to parse indexed QUERY_STRING
if (wsgi_req->query_string_len > 0) {
if (!memchr(wsgi_req->query_string, '=', wsgi_req->query_string_len)) {
nargs = 1;
for(i=0;i<wsgi_req->query_string_len;i++) {
if (wsgi_req->query_string[i] == '+')
nargs++;
}
// reallocate argv and qs
argv = uwsgi_malloc(sizeof(char *) * (3+nargs));
char *qs = uwsgi_concat2n(wsgi_req->query_string, wsgi_req->query_string_len, "", 0);
// set the start position of args in argv
i = 1;
if (helper) i = 2;
char *p = strtok(qs, "+");
while(p) {
// create a copy for the url_decoded string
char *arg_copy = uwsgi_str(p);
uint16_t arg_copy_len = strlen(p);
http_url_decode(p, &arg_copy_len, arg_copy);
// and a final copy for shell escaped arg
argv[i] = uwsgi_malloc( (arg_copy_len * 2) +1);
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
i++;
p = strtok(NULL, "+");
}
}
else {
}
}
if (helper) {
if (!uwsgi_starts_with(helper, strlen(helper), "sym://", 6)) {
void (*cgi_func)(char *) = dlsym(RTLD_DEFAULT, helper+6);
@@ -818,11 +947,11 @@ clear:
}
argv[0] = helper;
argv[1] = command;
argv[2] = NULL;
argv[nargs+2] = NULL;
}
else {
argv[0] = command;
argv[1] = NULL;
argv[nargs+1] = NULL;
}
if (execvp(argv[0], argv)) {
@@ -840,51 +969,6 @@ void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
int uwsgi_cgi_manage_options(int i, char *optarg) {
char *value;
switch(i) {
case LONG_ARGS_CGI:
value = strchr(optarg, '=');
if (!value) {
uwsgi_dyn_dict_new(&uc.mountpoint, optarg, strlen(optarg), NULL, 0);
}
else {
uwsgi_dyn_dict_new(&uc.mountpoint, optarg, value-optarg, value+1, strlen(value+1));
}
return 1;
case LONG_ARGS_CGI_BUFFER_SIZE:
uc.buffer_size = atoi(optarg);
return 1;
case LONG_ARGS_CGI_TIMEOUT:
uc.timeout = atoi(optarg);
return 1;
case LONG_ARGS_CGI_INDEX:
uwsgi_string_new_list(&uc.index, optarg);
return 1;
case LONG_ARGS_CGI_ALLOWED_EXT:
uwsgi_string_new_list(&uc.allowed_ext, optarg);
return 1;
case LONG_ARGS_CGI_LOADLIB:
uwsgi_string_new_list(&uc.loadlib, uwsgi_str(optarg));
return 1;
case LONG_ARGS_CGI_UNSET:
uwsgi_string_new_list(&uc.unset, optarg);
return 1;
case LONG_ARGS_CGI_MAP_HELPER:
value = strchr(optarg, '=');
if (!value) {
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
exit(1);
}
uwsgi_dyn_dict_new(&uc.helpers, optarg, value-optarg, value+1, strlen(value+1));
return 1;
}
return 0;
}
struct uwsgi_plugin cgi_plugin = {
@@ -893,7 +977,6 @@ struct uwsgi_plugin cgi_plugin = {
.init = uwsgi_cgi_init,
.init_apps = uwsgi_cgi_apps,
.options = uwsgi_cgi_options,
.manage_opt = uwsgi_cgi_manage_options,
.request = uwsgi_cgi_request,
.after_request = uwsgi_cgi_after_request,
@@ -0,0 +1,70 @@
#include "../../uwsgi.h"
/*
This plugins is meant as an example for custom implementations.
-- Copy of 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.
*/
extern struct uwsgi_server uwsgi;
int cheaper_backlog2_algo(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) {
// count active workers
int active_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
active_workers++;
}
}
// cheap a worker if too much are running
if (active_workers > uwsgi.cheaper_count) {
return -1;
}
}
return 0;
}
// registration hook
void uwsgi_cheaper_register_backlog2(void) {
uwsgi_register_cheaper_algo("backlog2", cheaper_backlog2_algo);
}
struct uwsgi_plugin cheaper_backlog2_plugin = {
.name = "cheaper_backlog2",
.on_load = uwsgi_cheaper_register_backlog2,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='cheaper_backlog2'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['cheaper_backlog2']
+16
View File
@@ -0,0 +1,16 @@
#include "../../uwsgi.h"
int dummy_request(struct wsgi_request *wsgi_req) {
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
return UWSGI_OK;
}
struct uwsgi_plugin dummy_plugin = {
.name = "dummy",
.modifier1 = 0,
.request = dummy_request,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='dummy'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['dummy']
+7 -24
View File
@@ -4,10 +4,10 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_erlang uerl;
struct option erlang_options[] = {
{"erlang", required_argument, 0, LONG_ARGS_ERLANG},
{"erlang-cookie", required_argument, 0, LONG_ARGS_ERLANG_COOKIE},
{0, 0, 0, 0},
struct uwsgi_option erlang_options[] = {
{"erlang", required_argument, 0, "spawn an erlang c-node", uwsgi_opt_set_str, &uerl.name, UWSGI_OPT_MASTER},
{"erlang-cookie", required_argument, 0, "set erlang cookie", uwsgi_opt_set_str, &uerl.cookie, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -244,7 +244,7 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
}
void erlang_loop() {
void erlang_loop(int id) {
ErlConnect econn;
//ErlMessage em;
@@ -363,8 +363,7 @@ int erlang_init() {
char *nodename;
struct in_addr addr;
uerl.lock = uwsgi_mmap_shared_lock();
uwsgi_lock_init(uerl.lock);
uerl.lock = uwsgi_lock_init("erlang");
if (uerl.name) {
@@ -423,7 +422,7 @@ int erlang_init() {
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
if (register_fat_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
if (register_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
uwsgi_log("unable to register the erlang gateway\n");
exit(1);
}
@@ -433,26 +432,10 @@ int erlang_init() {
return 0;
}
int erlang_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_ERLANG:
uwsgi.master_process = 1;
uerl.name = optarg;
return 1;
case LONG_ARGS_ERLANG_COOKIE:
uerl.cookie = optarg;
return 1;
}
return 0;
}
struct uwsgi_plugin erlang_plugin = {
.name = "erlang",
.options = erlang_options,
.manage_opt = erlang_opt,
.init = erlang_init,
};
-5
View File
@@ -1,10 +1,5 @@
#include <ei.h>
#define LONG_ARGS_ERLANG 17012
#define LONG_ARGS_ERLANG_COOKIE 17013
struct uwsgi_erlang_process {
char name[0xff];
+10 -2
View File
@@ -1,7 +1,15 @@
import os
NAME='erlang'
CFLAGS = []
LDFLAGS = []
ERLANGPATH = os.environ.get('UWSGICONFIG_ERLANGPATH', 'erl')
includedir = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, include)])\" -s erlang halt").read().rstrip()
libpath = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, lib)])\" -s erlang halt").read().rstrip()
CFLAGS = [ '-I' + includedir ]
LDFLAGS = [ '-L' + libpath ]
LIBS = ['-lei']
GCC_LIST = ['erlang']
File diff suppressed because it is too large Load Diff
+164
View File
@@ -0,0 +1,164 @@
#define FASTROUTER_STATUS_FREE 0
#define FASTROUTER_STATUS_CONNECTING 1
#define FASTROUTER_STATUS_RECV_HDR 2
#define FASTROUTER_STATUS_RECV_VARS 3
#define FASTROUTER_STATUS_RESPONSE 4
#define FASTROUTER_STATUS_BUFFERING 5
#ifdef UWSGI_SCTP
#define FASTROUTER_STATUS_SCTP_NODE_FREE 6
#define FASTROUTER_STATUS_SCTP_RESPONSE 7
#endif
#define add_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+ufr.socket_timeout, x)
#define add_fake_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+1, x)
#define add_check_timeout(x) uwsgi_add_rb_timer(timeouts, time(NULL)+x, NULL)
#define del_check_timeout(x) rb_erase(&x->rbt, timeouts);
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
struct fastrouter_session;
struct uwsgi_fastrouter {
int (*mapper)(struct fastrouter_session *, char **);
int has_sockets;
int has_subscription_sockets;
#ifdef UWSGI_SCTP
int has_sctp_sockets;
#endif
int processes;
int quiet;
struct rb_root *timeouts;
int use_cache;
int nevents;
char *magic_table[0xff];
int queue;
char *pattern;
int pattern_len;
char *base;
int base_len;
size_t post_buffering;
char *pb_base_dir;
struct uwsgi_string_list *static_nodes;
struct uwsgi_string_list *current_static_node;
int static_node_gracetime;
char *stats_server;
int fr_stats_server;
int use_socket;
int socket_num;
struct uwsgi_socket *to_socket;
struct uwsgi_subscribe_slot *subscriptions;
int subscription_regexp;
struct uwsgi_string_list *fallback;
int socket_timeout;
uint8_t code_string_modifier1;
char *code_string_code;
char *code_string_function;
struct uwsgi_rb_timer *subscriptions_check;
int cheap;
int i_am_cheap;
int tolerance;
int harakiri;
struct fastrouter_session **fr_table;
};
#ifdef UWSGI_SCTP
struct uwsgi_fr_sctp_node {
int fd;
char name[64];
uint64_t requests;
struct uwsgi_fr_sctp_node *prev;
struct uwsgi_fr_sctp_node *next;
};
struct uwsgi_fr_sctp_node *uwsgi_fr_sctp_add_node(int);
void uwsgi_fr_sctp_del_node(int);
void uwsgi_opt_fastrouter_sctp(char *, char *, void *);
#endif
struct fastrouter_session {
int fd;
int instance_fd;
int status;
struct uwsgi_header uh;
uint8_t h_pos;
uint16_t pos;
char *hostname;
uint16_t hostname_len;
int has_key;
int retry;
#ifdef UWSGI_SCTP
int persistent;
#endif
char *instance_address;
uint64_t instance_address_len;
struct uwsgi_subscribe_node *un;
struct uwsgi_string_list *static_node;
int pass_fd;
int soopt;
int timed_out;
struct uwsgi_rb_timer *timeout;
int instance_failed;
size_t post_cl;
size_t post_remains;
struct uwsgi_string_list *fallback;
char *buf_file_name;
FILE *buf_file;
uint8_t modifier1;
uint8_t modifier2;
char *tmp_socket_name;
char buffer[0xffff];
};
void uwsgi_fastrouter_switch_events(struct fastrouter_session *, int intersting_fd, char **);
void close_session(struct fastrouter_session *);
void fr_get_hostname(char *, uint16_t, char *, uint16_t, void *);
int uwsgi_fr_map_use_void(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_cache(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_pattern(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_subscription(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_base(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_cs(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_to(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_static_nodes(struct fastrouter_session *, char **);
#ifdef UWSGI_SCTP
int uwsgi_fr_map_use_sctp(struct fastrouter_session *, char **);
#endif
+428
View File
@@ -0,0 +1,428 @@
#include "../../uwsgi.h"
#include "fr.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_fastrouter ufr;
void uwsgi_fastrouter_switch_events(struct fastrouter_session *fr_session, int interesting_fd, char **magic_table) {
socklen_t solen = sizeof(int);
struct iovec iov[2];
struct msghdr msg;
union {
struct cmsghdr cmsg;
char control[CMSG_SPACE(sizeof(int))];
} msg_control;
struct cmsghdr *cmsg;
ssize_t len;
char *post_tmp_buf[0xffff];
switch (fr_session->status) {
case FASTROUTER_STATUS_RECV_HDR:
len = recv(fr_session->fd, (char *) (&fr_session->uh) + fr_session->h_pos, 4 - fr_session->h_pos, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
close_session(fr_session);
break;
}
fr_session->h_pos += len;
if (fr_session->h_pos == 4) {
#ifdef UWSGI_DEBUG
uwsgi_log("modifier1: %d pktsize: %d modifier2: %d\n", fr_session->uh.modifier1, fr_session->uh.pktsize, fr_session->uh.modifier2);
#endif
fr_session->status = FASTROUTER_STATUS_RECV_VARS;
}
break;
case FASTROUTER_STATUS_RECV_VARS:
if (interesting_fd == -1) {
goto choose_node;
}
len = recv(fr_session->fd, fr_session->buffer + fr_session->pos, fr_session->uh.pktsize - fr_session->pos, 0);
if (len <= 0) {
uwsgi_error("recv()");
close_session(fr_session);
break;
}
fr_session->pos += len;
if (fr_session->pos == fr_session->uh.pktsize) {
if (uwsgi_hooked_parse(fr_session->buffer, fr_session->uh.pktsize, fr_get_hostname, (void *) fr_session)) {
close_session(fr_session);
break;
}
if (fr_session->hostname_len == 0) {
close_session(fr_session);
break;
}
#ifdef UWSGI_DEBUG
//uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
#endif
// the mapper hook
choose_node:
if (ufr.mapper(fr_session, magic_table))
break;
// no address found
if (!fr_session->instance_address_len) {
// if fallback nodes are configured, trigger them
if (ufr.fallback) {
fr_session->instance_failed = 1;
}
close_session(fr_session);
break;
}
if (ufr.post_buffering > 0 && fr_session->post_cl > ufr.post_buffering) {
fr_session->status = FASTROUTER_STATUS_BUFFERING;
fr_session->buf_file_name = uwsgi_tmpname(ufr.pb_base_dir, "uwsgiXXXXX");
if (!fr_session->buf_file_name) {
uwsgi_error("tempnam()");
close_session(fr_session);
break;
}
fr_session->post_remains = fr_session->post_cl;
// 2 + UWSGI_POSTFILE + 2 + fr_session->buf_file_name
if (fr_session->uh.pktsize + (2 + 14 + 2 + strlen(fr_session->buf_file_name)) > 0xffff) {
uwsgi_log("unable to buffer request body to file %s: not enough space\n", fr_session->buf_file_name);
close_session(fr_session);
break;
}
char *ptr = fr_session->buffer + fr_session->uh.pktsize;
uint16_t bfn_len = strlen(fr_session->buf_file_name);
*ptr++ = 14;
*ptr++ = 0;
memcpy(ptr, "UWSGI_POSTFILE", 14);
ptr += 14;
*ptr++ = (char) (bfn_len & 0xff);
*ptr++ = (char) ((bfn_len >> 8) & 0xff);
memcpy(ptr, fr_session->buf_file_name, bfn_len);
fr_session->uh.pktsize += 2 + 14 + 2 + bfn_len;
fr_session->buf_file = fopen(fr_session->buf_file_name, "w");
if (!fr_session->buf_file) {
uwsgi_error_open(fr_session->buf_file_name);
close_session(fr_session);
break;
}
}
else {
fr_session->pass_fd = is_unix(fr_session->instance_address, fr_session->instance_address_len);
fr_session->instance_fd = uwsgi_connectn(fr_session->instance_address, fr_session->instance_address_len, 0, 1);
if (fr_session->instance_fd < 0) {
fr_session->instance_failed = 1;
fr_session->soopt = errno;
close_session(fr_session);
break;
}
fr_session->status = FASTROUTER_STATUS_CONNECTING;
ufr.fr_table[fr_session->instance_fd] = fr_session;
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
}
}
break;
case FASTROUTER_STATUS_CONNECTING:
if (interesting_fd == fr_session->instance_fd) {
if (getsockopt(fr_session->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&fr_session->soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
fr_session->instance_failed = 1;
close_session(fr_session);
break;
}
if (fr_session->soopt) {
fr_session->instance_failed = 1;
close_session(fr_session);
break;
}
fr_session->uh.modifier1 = fr_session->modifier1;
iov[0].iov_base = &fr_session->uh;
iov[0].iov_len = 4;
iov[1].iov_base = fr_session->buffer;
iov[1].iov_len = fr_session->uh.pktsize;
// increment node requests counter
if (fr_session->un)
fr_session->un->requests++;
// fd passing: PERFORMANCE EXTREME BOOST !!!
if (fr_session->pass_fd && !uwsgi.no_fd_passing) {
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 2;
msg.msg_flags = 0;
msg.msg_control = &msg_control;
msg.msg_controllen = sizeof(msg_control);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(cmsg), &fr_session->fd, sizeof(int));
if (sendmsg(fr_session->instance_fd, &msg, 0) < 0) {
uwsgi_error("sendmsg()");
}
close_session(fr_session);
break;
}
if (writev(fr_session->instance_fd, iov, 2) < 0) {
uwsgi_error("writev()");
close_session(fr_session);
break;
}
event_queue_fd_write_to_read(ufr.queue, fr_session->instance_fd);
fr_session->status = FASTROUTER_STATUS_RESPONSE;
}
break;
#ifdef UWSGI_SCTP
case FASTROUTER_STATUS_SCTP_NODE_FREE:
{
struct sctp_sndrcvinfo sinfo;
int msg_flags = 0;
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
len = sctp_recvmsg(interesting_fd, fr_session->buffer, 0xffff, NULL, NULL, &sinfo, &msg_flags);
// remove the SCTP node
uwsgi_log("[0] removing SCTP node %d flags = %d len = %d\n", interesting_fd, msg_flags, len);
uwsgi_fr_sctp_del_node(interesting_fd);
if (ufr.fr_table[interesting_fd]->timeout) {
del_timeout(ufr.fr_table[interesting_fd]);
}
free(ufr.fr_table[interesting_fd]);
ufr.fr_table[interesting_fd] = NULL;
close(interesting_fd);
}
break;
case FASTROUTER_STATUS_SCTP_RESPONSE:
// data from instance
if (interesting_fd == fr_session->instance_fd) {
struct sctp_sndrcvinfo sinfo;
struct uwsgi_header *uh;
int msg_flags = 0;
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
len = sctp_recvmsg(fr_session->instance_fd, fr_session->buffer, 0xffff, NULL, NULL, &sinfo, &msg_flags);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
close_session(ufr.fr_table[fr_session->fd]);
// REMOVE THE NODE
uwsgi_log("[1] removing SCTP node %d flags = %d len = %d\n", interesting_fd, msg_flags, len);
uwsgi_fr_sctp_del_node(interesting_fd);
if (ufr.fr_table[interesting_fd]->timeout) {
del_timeout(ufr.fr_table[interesting_fd]);
}
free(ufr.fr_table[interesting_fd]);
ufr.fr_table[interesting_fd] = NULL;
close(interesting_fd);
break;
}
if (fr_session->fd != -1 && sinfo.sinfo_stream != fr_session->fd) {
if (fr_session->fd != -1) {
uwsgi_log("INVALID SCTP STREAM !!!\n");
close_session(ufr.fr_table[fr_session->fd]);
}
break;
}
uh = (struct uwsgi_header *) &sinfo.sinfo_ppid;
// check for close packet
if (uh->modifier1 == 200) {
fr_session->status = FASTROUTER_STATUS_SCTP_NODE_FREE;
if (fr_session->fd != -1) {
close_session(ufr.fr_table[fr_session->fd]);
}
break;
}
if (fr_session->fd == -1) {
break;
}
len = send(fr_session->fd, fr_session->buffer, len, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("send()");
close_session(ufr.fr_table[fr_session->fd]);
break;
}
// update transfer statistics
if (fr_session->un)
fr_session->un->transferred += len;
}
// body from client
else if (interesting_fd == fr_session->fd) {
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
// mark session as broken
ufr.fr_table[fr_session->instance_fd]->fd = -1;
close_session(fr_session);
break;
}
struct sctp_sndrcvinfo sinfo;
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
// map the stream id to the file descriptor
struct uwsgi_header uh;
uh.modifier1 = 199;
uh.pktsize = 0;
uh.modifier2 = 0;
memcpy(&sinfo.sinfo_ppid, &uh, sizeof(uint32_t));
sinfo.sinfo_stream = fr_session->fd;
len = sctp_send(fr_session->instance_fd, fr_session->buffer, len, &sinfo, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("send()");
close_session(fr_session);
break;
}
}
break;
#endif
case FASTROUTER_STATUS_RESPONSE:
// data from instance
if (interesting_fd == fr_session->instance_fd) {
len = recv(fr_session->instance_fd, fr_session->buffer, 0xffff, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
close_session(fr_session);
break;
}
len = send(fr_session->fd, fr_session->buffer, len, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("send()");
close_session(fr_session);
break;
}
// update transfer statistics
if (fr_session->un)
fr_session->un->transferred += len;
}
// body from client
else if (interesting_fd == fr_session->fd) {
//uwsgi_log("receiving body...\n");
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
close_session(fr_session);
break;
}
len = send(fr_session->instance_fd, fr_session->buffer, len, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("send()");
close_session(fr_session);
break;
}
}
break;
case FASTROUTER_STATUS_BUFFERING:
len = recv(fr_session->fd, post_tmp_buf, UMIN(0xffff, fr_session->post_remains), 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
close_session(fr_session);
break;
}
if (fwrite(post_tmp_buf, len, 1, fr_session->buf_file) != 1) {
uwsgi_error("fwrite()");
close_session(fr_session);
break;
}
fr_session->post_remains -= len;
if (fr_session->post_remains == 0) {
// close the buf_file ASAP
fclose(fr_session->buf_file);
fr_session->buf_file = NULL;
fr_session->pass_fd = is_unix(fr_session->instance_address, fr_session->instance_address_len);
fr_session->instance_fd = uwsgi_connectn(fr_session->instance_address, fr_session->instance_address_len, 0, 1);
if (fr_session->instance_fd < 0) {
fr_session->instance_failed = 1;
close_session(fr_session);
break;
}
fr_session->status = FASTROUTER_STATUS_CONNECTING;
ufr.fr_table[fr_session->instance_fd] = fr_session;
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
}
break;
// fallback to destroy !!!
default:
uwsgi_log("unknown event: closing session\n");
close_session(fr_session);
break;
}
}
+190
View File
@@ -0,0 +1,190 @@
#include "../../uwsgi.h"
#include "fr.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_fastrouter ufr;
#ifdef UWSGI_SCTP
extern struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes;
extern struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes_current;
#endif
int uwsgi_fr_map_use_void(struct fastrouter_session *fr_session, char **magic_table) {
return 0;
}
int uwsgi_fr_map_use_cache(struct fastrouter_session *fr_session, char **magic_table) {
fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
if (cs_mod) {
fr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address)) - 1);
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
}
return 0;
}
int uwsgi_fr_map_use_pattern(struct fastrouter_session *fr_session, char **magic_table) {
int tmp_socket_name_len = 0;
magic_table['s'] = uwsgi_concat2n(fr_session->hostname, fr_session->hostname_len, "", 0);
fr_session->tmp_socket_name = magic_sub(ufr.pattern, ufr.pattern_len, &tmp_socket_name_len, magic_table);
free(magic_table['s']);
fr_session->instance_address_len = tmp_socket_name_len;
fr_session->instance_address = fr_session->tmp_socket_name;
return 0;
}
int uwsgi_fr_map_use_subscription(struct fastrouter_session *fr_session, char **magic_table) {
fr_session->un = uwsgi_get_subscribe_node(&ufr.subscriptions, fr_session->hostname, fr_session->hostname_len, ufr.subscription_regexp);
if (fr_session->un && fr_session->un->len) {
fr_session->instance_address = fr_session->un->name;
fr_session->instance_address_len = fr_session->un->len;
fr_session->modifier1 = fr_session->un->modifier1;
}
else if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
uwsgi_gateway_go_cheap("uWSGI fastrouter", ufr.queue, &ufr.i_am_cheap);
}
return 0;
}
int uwsgi_fr_map_use_base(struct fastrouter_session *fr_session, char **magic_table) {
int tmp_socket_name_len = 0;
fr_session->tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
fr_session->instance_address_len = tmp_socket_name_len;
fr_session->instance_address = fr_session->tmp_socket_name;
return 0;
}
int uwsgi_fr_map_use_cs(struct fastrouter_session *fr_session, char **magic_table) {
if (uwsgi.p[ufr.code_string_modifier1]->code_string) {
fr_session->instance_address = uwsgi.p[ufr.code_string_modifier1]->code_string("uwsgi_fastrouter", ufr.code_string_code, ufr.code_string_function, fr_session->hostname, fr_session->hostname_len);
if (fr_session->instance_address) {
fr_session->instance_address_len = strlen(fr_session->instance_address);
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
if (cs_mod) {
fr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address)) - 1);
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
}
}
}
return 0;
}
int uwsgi_fr_map_use_to(struct fastrouter_session *fr_session, char **magic_table) {
fr_session->instance_address = ufr.to_socket->name;
fr_session->instance_address_len = ufr.to_socket->name_len;
return 0;
}
int uwsgi_fr_map_use_static_nodes(struct fastrouter_session *fr_session, char **magic_table) {
if (!ufr.current_static_node) {
ufr.current_static_node = ufr.static_nodes;
}
fr_session->static_node = ufr.current_static_node;
// is it a dead node ?
if (fr_session->static_node->custom > 0) {
// gracetime passed ?
if (fr_session->static_node->custom + ufr.static_node_gracetime <= (uint64_t) uwsgi_now()) {
fr_session->static_node->custom = 0;
}
else {
struct uwsgi_string_list *tmp_node = fr_session->static_node;
struct uwsgi_string_list *next_node = fr_session->static_node->next;
fr_session->static_node = NULL;
// needed for 1-node only setups
if (!next_node)
next_node = ufr.static_nodes;
while (tmp_node != next_node) {
if (!next_node) {
next_node = ufr.static_nodes;
}
if (tmp_node == next_node)
break;
if (next_node->custom == 0) {
fr_session->static_node = next_node;
break;
}
next_node = next_node->next;
}
}
}
if (fr_session->static_node) {
fr_session->instance_address = fr_session->static_node->value;
fr_session->instance_address_len = fr_session->static_node->len;
// set the next one
ufr.current_static_node = fr_session->static_node->next;
}
else {
// set the next one
ufr.current_static_node = ufr.current_static_node->next;
}
return 0;
}
#ifdef UWSGI_SCTP
int uwsgi_fr_map_use_sctp(struct fastrouter_session *fr_session, char **magic_table) {
if (!*uwsgi_fastrouter_sctp_nodes_current)
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes_current;
int choosen_fd = -1;
// find the first available server
while (ufsn) {
if (ufr.fr_table[ufsn->fd]->status == FASTROUTER_STATUS_SCTP_NODE_FREE) {
ufsn->requests++;
choosen_fd = ufsn->fd;
break;
}
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes_current) {
break;
}
ufsn = ufsn->next;
}
// no nodes available
if (choosen_fd == -1) {
fr_session->retry = 1;
del_timeout(fr_session);
fr_session->timeout = add_fake_timeout(fr_session);
return -1;
}
struct sctp_sndrcvinfo sinfo;
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
memcpy(&sinfo.sinfo_ppid, &fr_session->uh, sizeof(uint32_t));
sinfo.sinfo_stream = fr_session->fd;
ssize_t len = sctp_send(choosen_fd, fr_session->buffer, fr_session->uh.pktsize, &sinfo, 0);
if (len < 0)
uwsgi_error("sctp_send()");
fr_session->instance_fd = choosen_fd;
fr_session->status = FASTROUTER_STATUS_SCTP_RESPONSE;
ufr.fr_table[fr_session->instance_fd]->status = FASTROUTER_STATUS_SCTP_RESPONSE;
ufr.fr_table[fr_session->instance_fd]->fd = fr_session->fd;
// round robin
*uwsgi_fastrouter_sctp_nodes_current = (*uwsgi_fastrouter_sctp_nodes_current)->next;
return -1;
}
#endif
+103
View File
@@ -0,0 +1,103 @@
#ifdef UWSGI_SCTP
#include "../../uwsgi.h"
#include "fr.h"
extern struct uwsgi_fastrouter ufr;
struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes;
struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes_current;
struct uwsgi_fr_sctp_node *uwsgi_fr_sctp_add_node(int fd) {
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes;
if (!ufsn) {
*uwsgi_fastrouter_sctp_nodes = uwsgi_malloc(sizeof(struct uwsgi_fr_sctp_node));
(*uwsgi_fastrouter_sctp_nodes)->next = *uwsgi_fastrouter_sctp_nodes;
(*uwsgi_fastrouter_sctp_nodes)->prev = *uwsgi_fastrouter_sctp_nodes;
(*uwsgi_fastrouter_sctp_nodes)->requests = 0;
(*uwsgi_fastrouter_sctp_nodes)->fd = fd;
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
}
else {
while(ufsn) {
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes) {
break;
}
ufsn = ufsn->next;
}
ufsn->next = uwsgi_malloc(sizeof(struct uwsgi_fr_sctp_node));
ufsn->next->next = *uwsgi_fastrouter_sctp_nodes;
ufsn->next->prev = ufsn;
ufsn->next->requests = 0;
ufsn->next->fd = fd;
(*uwsgi_fastrouter_sctp_nodes)->prev = ufsn->next;
*uwsgi_fastrouter_sctp_nodes_current = ufsn->next;
}
return *uwsgi_fastrouter_sctp_nodes_current;
}
void uwsgi_fr_sctp_del_node(int fd) {
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes;
while(ufsn) {
if (ufsn->fd == fd) {
struct uwsgi_fr_sctp_node *prev = ufsn->prev;
struct uwsgi_fr_sctp_node *next = ufsn->next;
// am i the only node ?
if (prev == ufsn) {
free(ufsn);
*uwsgi_fastrouter_sctp_nodes = NULL;
*uwsgi_fastrouter_sctp_nodes_current = NULL;
break;
}
prev->next = next;
next->prev = prev;
// am i the first node ?
if (ufsn == *uwsgi_fastrouter_sctp_nodes) {
*uwsgi_fastrouter_sctp_nodes = next;
*uwsgi_fastrouter_sctp_nodes_current = next;
free(ufsn);
break;
}
if (*uwsgi_fastrouter_sctp_nodes_current == ufsn) {
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
}
free(ufsn);
break;
}
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes) {
break;
}
ufsn = ufsn->next;
}
}
void uwsgi_opt_fastrouter_sctp(char *opt, char *value, void *foobar) {
struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(value, "uWSGI fastrouter");
ugs->sctp = 1;
ufr.has_sctp_sockets++;
}
#endif
+1 -1
View File
@@ -4,4 +4,4 @@ CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['fastrouter']
GCC_LIST = ['fr_sctp', 'fr_map', 'fastrouter', 'fr_events']
-5
View File
@@ -7,10 +7,6 @@ struct ufib {
VALUE *fib;
} ufiber;
struct option fiber_options[] = {
{ 0, 0, 0, 0 }
};
VALUE uwsgi_fiber_request() {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
@@ -80,5 +76,4 @@ struct uwsgi_plugin fiber_plugin = {
.name = "fiber",
.init = fiber_init,
.options = fiber_options,
};
+14 -18
View File
@@ -3,17 +3,13 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
struct option gevent_options[] = {
{ 0, 0, 0, 0 }
};
#define GEVENT_SWITCH PyObject *gswitch = python_call(ugevent.greenlet_switch, ugevent.greenlet_switch_args, 0, NULL); Py_DECREF(gswitch)
#define GET_CURRENT_GREENLET python_call(ugevent.get_current, ugevent.get_current_args, 0, NULL)
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req
#define stop_the_watchers ret = PyObject_CallMethod(timer, "stop", NULL);\
if (ret) Py_DECREF(ret);\
if (ret) { Py_DECREF(ret); }\
ret = PyObject_CallMethod(watcher, "stop", NULL);\
if (ret) Py_DECREF(ret);
if (ret) { Py_DECREF(ret); }
struct uwsgi_gevent {
PyObject *greenlet_switch;
@@ -28,6 +24,14 @@ struct uwsgi_gevent {
} ugevent;
struct wsgi_request *uwsgi_gevent_current_wsgi_req(void) {
PyObject *current_greenlet = GET_CURRENT_GREENLET;
PyObject *py_wsgi_req = PyObject_GetAttrString(current_greenlet, "uwsgi_wsgi_req");
return (struct wsgi_request*) PyLong_AsLong(py_wsgi_req);
}
PyObject *py_uwsgi_gevent_signal_handler(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
@@ -94,7 +98,6 @@ PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {
uwsgi_log("async queue is full !!!\n");
goto clear;
}
uwsgi.wsgi_req = wsgi_req;
// fill wsgi_request structure
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi.sockets );
@@ -111,7 +114,6 @@ PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {
// accept the connection
if (wsgi_req_simple_accept(wsgi_req, uwsgi.sockets->fd)) {
uwsgi_close_request(wsgi_req);
free_req_queue;
goto clear;
}
@@ -154,10 +156,10 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
int status ;
PyObject *current_greenlet = GET_CURRENT_GREENLET;
// another hack to retrieve the current wsgi_req;
PyObject_SetAttrString(current_greenlet, "uwsgi_wsgi_req", py_wsgi_req);
PyObject *greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");
uwsgi.wsgi_req = wsgi_req;
// create a watcher for request socket
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
if (!watcher) goto clear1;
@@ -171,9 +173,6 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
PyObject *ret = uwsgi_gevent_wait(watcher, timer, greenlet_switch);
if (!ret) goto clear_and_stop;
// do not forget to overwrite this pointer each time !!!
uwsgi.wsgi_req = wsgi_req;
// we can safely decref here as watcher and timer has got a +1 for start() method
Py_DECREF(ret);
if (ret == timer) {
@@ -200,7 +199,6 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
}
for(;;) {
uwsgi.wsgi_req = wsgi_req;
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);
if (wsgi_req->async_status <= UWSGI_OK) {
goto clear;
@@ -224,8 +222,6 @@ clear1:
Py_DECREF(current_greenlet);
uwsgi_close_request(wsgi_req);
uwsgi.wsgi_req = wsgi_req;
free_req_queue;
Py_INCREF(Py_None);
@@ -250,6 +246,7 @@ void gevent_loop() {
exit(1);
}
uwsgi.current_wsgi_req = uwsgi_gevent_current_wsgi_req;
PyObject *gevent_dict = get_uwsgi_pydict("gevent");
if (!gevent_dict) uwsgi_pyexit;
@@ -352,5 +349,4 @@ struct uwsgi_plugin gevent_plugin = {
.name = "gevent",
.init = gevent_init,
.options = gevent_options,
};
+3 -3
View File
@@ -10,9 +10,9 @@ struct ugreenlet {
PyGreenlet **gl;
} ugl;
struct option greenlet_options[] = {
{"greenlet", no_argument, &ugl.enabled, 1},
{ 0, 0, 0, 0 }
struct uwsgi_option greenlet_options[] = {
{"greenlet", no_argument, 0, "enable greenlet as suspend engine", uwsgi_opt_true, &ugl.enabled, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
+600 -547
View File
File diff suppressed because it is too large Load Diff
+1 -8
View File
@@ -1,16 +1,9 @@
#include "../../uwsgi.h"
#include <jni.h>
#define MAX_CLASSPATH 64
#define LONG_ARGS_JVM_BASE 17000 + (300 * 100)
#define LONG_ARGS_JVM_CLASS LONG_ARGS_JVM_BASE + 1
#define LONG_ARGS_JVM_CLASSPATH LONG_ARGS_JVM_BASE + 2
struct uwsgi_jvm {
char *classpath[MAX_CLASSPATH];
int classpath_cnt;
struct uwsgi_string_list *classpath;
JNIEnv *env;
char *class;
+10 -30
View File
@@ -5,13 +5,15 @@
with javap -s -p <class>
you can get method signatures
This plugin is the core for all of the JVM-based ones
*/
struct uwsgi_jvm ujvm;
struct option uwsgi_jvm_options[] = {
{"jvm-main-class", required_argument, 0, LONG_ARGS_JVM_CLASS},
{"jvm-classpath", required_argument, 0, LONG_ARGS_JVM_CLASSPATH},
struct uwsgi_option uwsgi_jvm_options[] = {
{"jvm-main-class", required_argument, 0, "load the specified class", uwsgi_opt_set_str, &ujvm.class, 0},
{"jvm-classpath", required_argument, 0, "add the specified directory to the classpath", uwsgi_opt_add_string_list, &ujvm.classpath, 0},
{0, 0, 0, 0},
};
@@ -87,7 +89,6 @@ int jvm_init(void) {
JavaVMOption options[1];
jmethodID mmid;
int i;
char *old_cp = NULL ;
@@ -97,17 +98,17 @@ int jvm_init(void) {
options[0].optionString = "-Djava.class.path=.";
if (ujvm.classpath_cnt > 0) {
for(i=0;i<ujvm.classpath_cnt;i++) {
struct uwsgi_string_list *cp = ujvm.classpath;
while(cp) {
if (old_cp) {
options[0].optionString = uwsgi_concat3(old_cp, ":", ujvm.classpath[i]);
options[0].optionString = uwsgi_concat3(old_cp, ":", cp->value);
free(old_cp);
}
else {
options[0].optionString = uwsgi_concat3(options[0].optionString, ":", ujvm.classpath[i]);
options[0].optionString = uwsgi_concat3(options[0].optionString, ":", cp->value);
}
old_cp = options[0].optionString ;
}
cp = cp->next;
}
vm_args.options = options;
@@ -199,32 +200,11 @@ int uwsgi_jvm_strlen2c(jobject obj) {
return (*ujvm.env)->GetStringUTFLength(ujvm.env, obj);
}
int uwsgi_jvm_manage_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_JVM_CLASS:
ujvm.class = optarg;
return 1;
case LONG_ARGS_JVM_CLASSPATH:
if (ujvm.classpath_cnt < MAX_CLASSPATH) {
ujvm.classpath[ujvm.classpath_cnt] = optarg;
ujvm.classpath_cnt++;
}
else {
uwsgi_log( "you can specify at most %d --jvm-classpath options\n", MAX_CLASSPATH);
}
return 1;
}
return 0;
}
struct uwsgi_plugin jvm_plugin = {
.name = "jvm",
.init = jvm_init,
.options = uwsgi_jvm_options,
.manage_opt = uwsgi_jvm_manage_opt,
};
+2 -2
View File
@@ -13,8 +13,8 @@ NAME='jvm'
# UWSGICONFIG_JVM_INCPATH="/usr/java/include -I /usr/java/include/solaris" UWSGICONFIG_JVM_LIBPATH="/usr/java/jre/lib/i386/" python uwsgiconfig.py --plugin plugins/jvm
# Ubuntu
JVM_INCPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.15/include/linux"
JVM_LIBPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/i386/server/"
JVM_INCPATH = "/usr/lib/jvm/java-6-openjdk/include/ -I/usr/lib/jvm/java-6-openjdk/include/linux"
JVM_LIBPATH = "/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server/"
try:
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
-5
View File
@@ -64,15 +64,10 @@ void uwsgi_logsocket_register() {
uwsgi_register_logger("socket", uwsgi_socket_logger);
}
int uwsgi_logsocket_init() {
return 0;
}
struct uwsgi_plugin logsocket_plugin = {
.name = "logsocket",
.on_load = uwsgi_logsocket_register,
.init = uwsgi_logsocket_init
};
+2 -17
View File
@@ -12,14 +12,11 @@ struct uwsgi_lua {
char *filename;
} ulua;
#define LONG_ARGS_LUA_BASE 17000 + (6 * 100)
#define LONG_ARGS_LUA LONG_ARGS_LUA_BASE + 1
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
struct option uwsgi_lua_options[] = {
struct uwsgi_option uwsgi_lua_options[] = {
{"lua", required_argument, 0, LONG_ARGS_LUA},
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
{0, 0, 0, 0},
@@ -583,16 +580,6 @@ void uwsgi_lua_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
int uwsgi_lua_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_LUA:
ulua.filename = optarg;
return 1;
}
return 0;
}
int uwsgi_lua_magic(char *mountpoint, char *lazy) {
@@ -643,7 +630,6 @@ char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, uint16_
#endif
if (lua_pcall(L, 1, 1, 0) != 0) {
uwsgi_log("CAZZO\n");
uwsgi_log("error running function `f': %s",
lua_tostring(L, -1));
return NULL;
@@ -726,7 +712,6 @@ struct uwsgi_plugin lua_plugin = {
.modifier1 = 6,
.init = uwsgi_lua_init,
.options = uwsgi_lua_options,
.manage_opt = uwsgi_lua_manage_options,
.request = uwsgi_lua_request,
.after_request = uwsgi_lua_after_request,
.init_apps = uwsgi_lua_app,
+7 -19
View File
@@ -3,12 +3,10 @@
extern struct uwsgi_server uwsgi;
int use_nagios = 0;
#define LONG_ARGS_NAGIOS 40000
struct uwsgi_option nagios_options[] = {
struct option nagios_options[] = {
{"nagios", no_argument, 0, LONG_ARGS_NAGIOS},
{0, 0, 0, 0},
{"nagios", no_argument, 0, "nagios check", uwsgi_opt_true, &use_nagios, UWSGI_OPT_NO_INITIAL},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -30,7 +28,10 @@ int nagios() {
int fd = uwsgi_connect(uwsgi.sockets->name, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) {
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers %s\n", strerror(errno));
if (errno == EPERM || errno == EACCES) {
exit(3);
}
exit(2);
}
@@ -70,21 +71,8 @@ int nagios() {
exit(3);
}
int nagios_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_NAGIOS:
uwsgi.no_initial_output = 1;
use_nagios = 1;
return 1;
}
return 0;
}
struct uwsgi_plugin nagios_plugin = {
.options = nagios_options,
.manage_opt = nagios_opt,
.init = nagios,
};
+35
View File
@@ -0,0 +1,35 @@
#include "../../uwsgi.h"
int uwsgi_request_notfound(struct wsgi_request *wsgi_req) {
struct iovec iov[3];
if (wsgi_req->protocol_len > 0) {
iov[0].iov_base = wsgi_req->protocol;
iov[0].iov_len = wsgi_req->protocol_len;
}
else {
iov[0].iov_base = "HTTP/1.0";
iov[0].iov_len = 8;
}
iov[1].iov_base = " 404 Not Found\r\n";
iov[1].iov_len = 16;
iov[2].iov_base = "Content-Type: text/plain\r\n\r\n";
iov[2].iov_len = 28;
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, iov, 3);
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "Not Found", 9);
wsgi_req->status = 404;
return UWSGI_OK;
}
struct uwsgi_plugin notfound_plugin = {
.name = "notfound",
.request = uwsgi_request_notfound,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='notfound'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['notfound']
-16
View File
@@ -1,16 +0,0 @@
PHP_ARG_WITH(uwsgi,,
[ --with-uwsgi=UWSGISRCDIR Build PHP as a uWSGI plugin (UNIX/POSIX only)], no, no)
AC_MSG_CHECKING([for UWSGI])
if test "$PHP_UWSGI" != "no"; then
INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED $PHP_UWSGI/php_plugin.so"
UWSGI_CFLAGS=`cd $PHP_UWSGI ; python uwsgiconfig.py --cflags`
UWSGI_CFLAGS="$UWSGI_CFLAGS -I$PHP_UWSGI"
PHP_SELECT_SAPI(uwsgi, shared, php_plugin.c, $UWSGI_CFLAGS)
AC_MSG_RESULT([$PHP_UWSGI])
else
AC_MSG_RESULT(no)
fi
+510 -77
View File
@@ -4,58 +4,114 @@
#include "php_variables.h"
#include "ext/standard/php_smart_str.h"
#include "ext/standard/info.h"
#include <uwsgi.h>
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
// http status codes list
extern struct http_status_codes hsc[];
static sapi_module_struct uwsgi_sapi_module;
struct uwsgi_php {
struct uwsgi_string_list *allowed_docroot;
struct uwsgi_string_list *allowed_ext;
struct uwsgi_string_list *index;
struct uwsgi_string_list *set;
struct uwsgi_string_list *append_config;
char *docroot;
char *app;
size_t ini_size;
int dump_config;
char *server_software;
size_t server_software_len;
} uphp;
#define LONG_ARGS_PHP_BASE 17000 + ((14 + 1) * 1000)
#define LONG_ARGS_PHP_INI LONG_ARGS_PHP_BASE + 1
#define LONG_ARGS_PHP_ALLOWED_DOCROOT LONG_ARGS_PHP_BASE + 2
#define LONG_ARGS_PHP_ALLOWED_EXT LONG_ARGS_PHP_BASE + 3
void uwsgi_opt_php_ini(char *opt, char *value, void *foobar) {
uwsgi_sapi_module.php_ini_path_override = uwsgi_str(value);
uwsgi_sapi_module.php_ini_ignore = 1;
}
struct option uwsgi_php_options[] = {
struct uwsgi_option uwsgi_php_options[] = {
{"php-ini", required_argument, 0, LONG_ARGS_PHP_INI},
{"php-config", required_argument, 0, LONG_ARGS_PHP_INI},
{"php-allowed-docroot", required_argument, 0, LONG_ARGS_PHP_ALLOWED_DOCROOT},
{"php-allowed-ext", required_argument, 0, LONG_ARGS_PHP_ALLOWED_EXT},
{0, 0, 0, 0},
{"php-ini", required_argument, 0, "set php.ini path", uwsgi_opt_php_ini, NULL, 0},
{"php-config", required_argument, 0, "set php.ini path", uwsgi_opt_php_ini, NULL, 0},
{"php-ini-append", required_argument, 0, "set php.ini path (append mode)", uwsgi_opt_add_string_list, &uphp.append_config, 0},
{"php-config-append", required_argument, 0, "set php.ini path (append mode)", uwsgi_opt_add_string_list, &uphp.append_config, 0},
{"php-set", required_argument, 0, "set a php config directive", uwsgi_opt_add_string_list, &uphp.set, 0},
{"php-index", required_argument, 0, "list the php index files", uwsgi_opt_add_string_list, &uphp.index, 0},
{"php-docroot", required_argument, 0, "force php DOCUMENT_ROOT", uwsgi_opt_set_str, &uphp.docroot, 0},
{"php-allowed-docroot", required_argument, 0, "list the allowed document roots", uwsgi_opt_add_string_list, &uphp.allowed_docroot, 0},
{"php-allowed-ext", required_argument, 0, "list the allowed php file extensions", uwsgi_opt_add_string_list, &uphp.allowed_ext, 0},
{"php-server-software", required_argument, 0, "force php SERVER_SOFTWARE", uwsgi_opt_set_str, &uphp.server_software, 0},
{"php-app", required_argument, 0, "force the php file to run at each request", uwsgi_opt_set_str, &uphp.app, 0},
{"php-dump-config", no_argument, 0, "dump php config (if modified via --php-set or append options)", uwsgi_opt_true, &uphp.dump_config, 0},
{0, 0, 0, 0, 0, 0, 0},
};
void uwsgi_php_redirect_to_slash(struct wsgi_request *wsgi_req) {
struct iovec iov[6];
wsgi_req->status = 301;
iov[0].iov_base = wsgi_req->protocol;
iov[0].iov_len = wsgi_req->protocol_len;
iov[1].iov_base = " 301 Moved Permanently\r\n";
iov[1].iov_len = 24;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
iov[0].iov_base = "Location: ";
iov[0].iov_len = 10;
iov[1].iov_base = wsgi_req->path_info;
iov[1].iov_len = wsgi_req->path_info_len;
iov[2].iov_base = "/";
iov[2].iov_len = 1;
if (wsgi_req->query_string_len > 0) {
iov[3].iov_base = "?";
iov[3].iov_len = 1;
iov[4].iov_base = wsgi_req->query_string;
iov[4].iov_len = wsgi_req->query_string_len;
iov[5].iov_base = "\r\n\r\n";
iov[5].iov_len = 4;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
wsgi_req->header_cnt++;
}
else {
iov[3].iov_base = "\r\n\r\n";
iov[3].iov_len = 4;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
wsgi_req->header_cnt++;
}
}
static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC)
{
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
ssize_t len = wsgi_req->socket->proto_write(wsgi_req, (char *) str, str_length);
if (len != str_length) {
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) str, str_length);
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance) {
php_handle_aborted_connection();
return -1;
}
wsgi_req->response_size += len;
return str_length;
}
void uwsgi_php_404(struct wsgi_request *wsgi_req) {
wsgi_req->status = 404;
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\nNot Found", 35);
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nNot Found", 61);
}
void uwsgi_php_403(struct wsgi_request *wsgi_req) {
wsgi_req->status = 403;
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\n\r\nForbidden", 35);
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\nContent-Type: text/plain\r\n\r\nForbidden", 61);
}
@@ -68,43 +124,57 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
char status[4];
struct http_status_codes *http_sc;
if (SG(request_info).no_headers == 1) {
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
wsgi_req->status = SG(sapi_headers).http_response_code;
if (!wsgi_req->status) wsgi_req->status = 200;
iov[0].iov_base = wsgi_req->protocol;
iov[0].iov_len = wsgi_req->protocol_len;
if (!SG(sapi_headers).http_status_line) {
iov[0].iov_base = wsgi_req->protocol;
iov[0].iov_len = wsgi_req->protocol_len;
iov[1].iov_base = " ";
iov[1].iov_len = 1;
iov[1].iov_base = " ";
iov[1].iov_len = 1;
uwsgi_num2str2n(wsgi_req->status, status, 4);
uwsgi_num2str2n(wsgi_req->status, status, 4);
iov[2].iov_base = status;
iov[2].iov_len = 3;
iov[2].iov_base = status;
iov[2].iov_len = 3;
iov[3].iov_base = " ";
iov[3].iov_len = 1;
iov[3].iov_base = " ";
iov[3].iov_len = 1;
// get the status code
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
if (!strncmp(http_sc->key, status, 3)) {
iov[4].iov_base = (char *) http_sc->message;
iov[4].iov_len = http_sc->message_size;
break;
}
}
// get the status code
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
if (!strncmp(http_sc->key, status, 3)) {
iov[4].iov_base = (char *) http_sc->message;
iov[4].iov_len = http_sc->message_size;
break;
}
}
if (iov[4].iov_len == 0) {
iov[4].iov_base = "Unknown";
iov[4].iov_len = 7;
}
if (iov[4].iov_len == 0) {
iov[4].iov_base = "Unknown";
iov[4].iov_len = 7;
}
iov[5].iov_base = "\r\n";
iov[5].iov_len = 2;
iov[5].iov_base = "\r\n";
iov[5].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
}
else {
iov[0].iov_base = SG(sapi_headers).http_status_line;
iov[0].iov_len = strlen(iov[0].iov_base);
iov[1].iov_base = "\r\n";
iov[1].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
}
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
while (h) {
@@ -112,6 +182,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
iov[0].iov_len = h->header_len;
iov[1].iov_base = "\r\n";
iov[1].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
wsgi_req->header_cnt++;
h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
@@ -185,6 +256,14 @@ static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
php_import_environment_variables(track_vars_array TSRMLS_CC);
if (uphp.server_software) {
if (!uphp.server_software_len) uphp.server_software_len = strlen(uphp.server_software);
php_register_variable_safe("SERVER_SOFTWARE", uphp.server_software, uphp.server_software_len, track_vars_array TSRMLS_CC);
}
else {
php_register_variable_safe("SERVER_SOFTWARE", "uWSGI", 5, track_vars_array TSRMLS_CC);
}
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
php_register_variable_safe( estrndup(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len,
@@ -196,6 +275,7 @@ static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
php_register_variable_safe("SCRIPT_NAME", wsgi_req->script_name, wsgi_req->script_name_len, track_vars_array TSRMLS_CC);
php_register_variable_safe("SCRIPT_FILENAME", wsgi_req->file, wsgi_req->file_len, track_vars_array TSRMLS_CC);
php_register_variable_safe("DOCUMENT_ROOT", wsgi_req->document_root, wsgi_req->document_root_len, track_vars_array TSRMLS_CC);
if (wsgi_req->path_info_len) {
char *path_translated = ecalloc(1, (wsgi_req->file_len - wsgi_req->script_name_len) + wsgi_req->path_info_len + 1);
@@ -204,6 +284,9 @@ static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
memcpy(path_translated + (wsgi_req->file_len - wsgi_req->script_name_len), wsgi_req->path_info, wsgi_req->path_info_len);
php_register_variable_safe("PATH_TRANSLATED", path_translated, (wsgi_req->file_len - wsgi_req->script_name_len) + wsgi_req->path_info_len , track_vars_array TSRMLS_CC);
}
else {
php_register_variable_safe("PATH_TRANSLATED", "", 0, track_vars_array TSRMLS_CC);
}
php_register_variable_safe("PHP_SELF", wsgi_req->script_name, wsgi_req->script_name_len, track_vars_array TSRMLS_CC);
@@ -212,9 +295,286 @@ static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
static sapi_module_struct uwsgi_sapi_module;
void uwsgi_php_append_config(char *filename) {
int file_size = 0;
char *file_content = uwsgi_open_and_read(filename, &file_size, 1, NULL);
uwsgi_sapi_module.ini_entries = realloc(uwsgi_sapi_module.ini_entries, uphp.ini_size + file_size);
memcpy(uwsgi_sapi_module.ini_entries + uphp.ini_size, file_content, file_size);
uphp.ini_size += file_size-1;
free(file_content);
}
void uwsgi_php_set(char *opt) {
uwsgi_sapi_module.ini_entries = realloc(uwsgi_sapi_module.ini_entries, uphp.ini_size + strlen(opt)+2);
memcpy(uwsgi_sapi_module.ini_entries + uphp.ini_size, opt, strlen(opt));
uphp.ini_size += strlen(opt)+1;
uwsgi_sapi_module.ini_entries[uphp.ini_size-1] = '\n';
uwsgi_sapi_module.ini_entries[uphp.ini_size] = 0;
}
// future implementation...
PHP_MINIT_FUNCTION(uwsgi_php_minit) {
return SUCCESS;
}
PHP_FUNCTION(uwsgi_version) {
RETURN_STRING(UWSGI_VERSION, 1);
}
PHP_FUNCTION(uwsgi_worker_id) {
RETURN_LONG(uwsgi.mywid);
}
PHP_FUNCTION(uwsgi_masterpid) {
if (uwsgi.master_process) {
RETURN_LONG(uwsgi.workers[0].pid);
}
RETURN_LONG(0);
}
PHP_FUNCTION(uwsgi_cache_del) {
char *key = NULL;
int keylen = 0;
if (!uwsgi.cache_max_items)
RETURN_NULL();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &keylen) == FAILURE) {
RETURN_NULL();
}
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_del(key, keylen, 0)) {
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_TRUE;
}
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_cache_get) {
char *key = NULL;
int keylen = 0;
uint64_t valsize;
if (!uwsgi.cache_max_items)
RETURN_NULL();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &keylen) == FAILURE) {
RETURN_NULL();
}
uwsgi_rlock(uwsgi.cache_lock);
char *value = uwsgi_cache_get(key, keylen, &valsize);
if (value) {
char *ret = estrndup(value, valsize);
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_STRING(ret, 0);
}
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_cache_set) {
char *key = NULL;
int keylen;
char *value = NULL;
int vallen;
uint64_t expires = 0;
if (!uwsgi.cache_max_items)
RETURN_NULL();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &key, &keylen, &value, &vallen, &expires) == FAILURE) {
RETURN_NULL();
}
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
RETURN_NULL();
}
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_set(key, keylen, value, vallen, expires, 0)) {
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_TRUE;
}
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_cache_update) {
char *key = NULL;
int keylen;
char *value = NULL;
int vallen;
uint64_t expires = 0;
if (!uwsgi.cache_max_items)
RETURN_NULL();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &key, &keylen, &value, &vallen, &expires) == FAILURE) {
RETURN_NULL();
}
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
RETURN_NULL();
}
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_TRUE;
}
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_rpc) {
int num_args = 0;
int i;
char *node = NULL;
char *func = NULL;
zval ***varargs = NULL;
zval *z_current_obj;
char *argv[256];
uint16_t argvs[256];
uint16_t size = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &varargs, &num_args) == FAILURE) {
RETURN_NULL();
}
if (num_args < 2)
goto clear;
if (num_args > 256 + 2)
goto clear;
z_current_obj = *varargs[0];
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
goto clear;
}
node = Z_STRVAL_P(z_current_obj);
z_current_obj = *varargs[1];
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
goto clear;
}
func = Z_STRVAL_P(z_current_obj);
for(i=0;i<(num_args-2);i++) {
z_current_obj = *varargs[i+2];
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
goto clear;
}
argv[i] = Z_STRVAL_P(z_current_obj);
argvs[i] = Z_STRLEN_P(z_current_obj);
}
char *response = uwsgi_do_rpc(node, func, num_args - 2, argv, argvs, &size);
if (size > 0) {
// here we do not free varargs for performance reasons
char *ret = estrndup(response, size);
free(response);
RETURN_STRING(ret, 0);
}
clear:
efree(varargs);
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_setprocname) {
char *name;
int name_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
RETURN_NULL();
}
uwsgi_set_processname(estrndup(name, name_len));
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_signal) {
long long_signum;
uint8_t signum = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &long_signum) == FAILURE) {
RETURN_NULL();
}
signum = (uint8_t) long_signum;
uwsgi_signal_send(uwsgi.signal_socket, signum);
RETURN_NULL();
}
zend_function_entry uwsgi_php_functions[] = {
PHP_FE(uwsgi_version, NULL)
PHP_FE(uwsgi_setprocname, NULL)
PHP_FE(uwsgi_worker_id, NULL)
PHP_FE(uwsgi_masterpid, NULL)
PHP_FE(uwsgi_signal, NULL)
PHP_FE(uwsgi_rpc, NULL)
PHP_FE(uwsgi_cache_get, NULL)
PHP_FE(uwsgi_cache_set, NULL)
PHP_FE(uwsgi_cache_update, NULL)
PHP_FE(uwsgi_cache_del, NULL)
{ NULL, NULL, NULL},
};
PHP_MINFO_FUNCTION(uwsgi_php_minfo) {
php_info_print_table_start( );
php_info_print_table_row(2, "uwsgi api", "enabled");
if (uwsgi.cache_max_items > 0) {
php_info_print_table_row(2, "uwsgi cache", "enabled");
}
else {
php_info_print_table_row(2, "uwsgi cache", "disabled");
}
php_info_print_table_end( );
}
static zend_module_entry uwsgi_module_entry = {
STANDARD_MODULE_HEADER,
"uwsgi",
uwsgi_php_functions,
PHP_MINIT(uwsgi_php_minit),
NULL,
NULL,
NULL,
PHP_MINFO(uwsgi_php_minfo),
UWSGI_VERSION,
STANDARD_MODULE_PROPERTIES
};
static int php_uwsgi_startup(sapi_module_struct *sapi_module)
{
if (php_module_startup(&uwsgi_sapi_module, NULL, 0)==FAILURE) {
if (php_module_startup(&uwsgi_sapi_module, &uwsgi_module_entry, 1)==FAILURE) {
return FAILURE;
} else {
return SUCCESS;
@@ -223,7 +583,7 @@ static int php_uwsgi_startup(sapi_module_struct *sapi_module)
static void sapi_uwsgi_log_message(char *message) {
uwsgi_log(message);
uwsgi_log("%s\n", message);
}
static sapi_module_struct uwsgi_sapi_module = {
@@ -261,7 +621,27 @@ int uwsgi_php_init(void) {
struct http_status_codes *http_sc;
struct uwsgi_string_list *pset = uphp.set;
struct uwsgi_string_list *append_config = uphp.append_config;
sapi_startup(&uwsgi_sapi_module);
// applying custom options
while(append_config) {
uwsgi_php_append_config(append_config->value);
append_config = append_config->next;
}
while(pset) {
uwsgi_php_set(pset->value);
pset = pset->next;
}
if (uphp.dump_config) {
uwsgi_log("--- PHP custom config ---\n\n");
uwsgi_log("%s\n", uwsgi_sapi_module.ini_entries);
uwsgi_log("--- end of PHP custom config ---\n");
}
uwsgi_sapi_module.startup(&uwsgi_sapi_module);
// filling http status codes
@@ -269,7 +649,6 @@ int uwsgi_php_init(void) {
http_sc->message_size = strlen(http_sc->message);
}
uwsgi_log("PHP %s initialized\n", PHP_VERSION);
return 0;
@@ -285,6 +664,8 @@ int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
int part_size = 0;
struct stat st;
if (wsgi_req->path_info_len == 0) return 0;
if (ptr[0] == '/') part_size++;
for(i=0;i<wsgi_req->path_info_len;i++) {
@@ -334,9 +715,9 @@ int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
int uwsgi_php_request(struct wsgi_request *wsgi_req) {
char real_filename[PATH_MAX+1];
uint16_t docroot_len = 0;
char *path_info = NULL;
size_t real_filename_len = 0;
struct stat php_stat;
zend_file_handle file_handle;
@@ -346,23 +727,47 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
return -1;
}
char *docroot = uwsgi_get_var(wsgi_req, (char *) "DOCUMENT_ROOT", 13, &docroot_len);
if (!docroot) {
docroot = uwsgi.cwd;
docroot_len = strlen(uwsgi.cwd);
if (uphp.docroot) {
wsgi_req->document_root = uphp.docroot;
}
// fallback to cwd
else if (!wsgi_req->document_root_len) {
wsgi_req->document_root = uwsgi.cwd;
}
else {
// explode DOCUMENT_ROOT (both for security and sanity checks)
// this memory will be cleared on request end
char *sanitized_docroot = ecalloc(1, PATH_MAX+1);
if (!uwsgi_expand_path(wsgi_req->document_root, wsgi_req->document_root_len, sanitized_docroot)) {
efree(sanitized_docroot);
return -1;
}
wsgi_req->document_root = sanitized_docroot;
}
char *filename = uwsgi_concat4n(docroot, docroot_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
// fix document_root_len
wsgi_req->document_root_len = strlen(wsgi_req->document_root);
if (uwsgi_php_walk(wsgi_req, filename, docroot, docroot_len, &path_info)) {
if (uphp.app) {
strcpy(real_filename, uphp.app);
wsgi_req->path_info = "";
wsgi_req->path_info_len = 0;
goto secure2;
}
char *filename = uwsgi_concat4n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
if (uwsgi_php_walk(wsgi_req, filename, wsgi_req->document_root, wsgi_req->document_root_len, &path_info)) {
free(filename);
return -1;
}
char *orig_path_info = wsgi_req->path_info;
uint16_t orig_path_info_len = wsgi_req->path_info_len;
if (path_info) {
wsgi_req->path_info = path_info;
wsgi_req->path_info_len = strlen(wsgi_req->path_info);
wsgi_req->path_info_len = orig_path_info_len - (path_info - orig_path_info);
}
else {
wsgi_req->path_info = "";
@@ -394,6 +799,47 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
secure:
if (stat(real_filename, &php_stat)) {
uwsgi_php_404(wsgi_req);
return UWSGI_OK;
}
if (S_ISDIR(php_stat.st_mode)) {
// add / to directories
if (orig_path_info_len == 0 || (orig_path_info_len > 0 && orig_path_info[orig_path_info_len-1] != '/')) {
wsgi_req->path_info = orig_path_info;
wsgi_req->path_info_len = orig_path_info_len;
uwsgi_php_redirect_to_slash(wsgi_req);
return UWSGI_OK;
}
struct uwsgi_string_list *upi = uphp.index;
real_filename[real_filename_len] = '/';
real_filename_len++;
int found = 0;
while(upi) {
if (real_filename_len + upi->len + 1 < PATH_MAX) {
// add + 1 to ensure null byte
memcpy(real_filename+real_filename_len, upi->value, upi->len + 1);
if (!access(real_filename, R_OK)) {
found = 1;
break;
}
}
upi = upi->next;
}
if (!found) {
uwsgi_php_404(wsgi_req);
return UWSGI_OK;
}
real_filename_len = strlen(real_filename);
}
if (uphp.allowed_ext) {
struct uwsgi_string_list *usl = uphp.allowed_ext;
while(usl) {
@@ -414,19 +860,23 @@ secure2:
wsgi_req->file = real_filename;
wsgi_req->file_len = strlen(wsgi_req->file);
if (docroot[docroot_len-1] == '/') {
wsgi_req->script_name = real_filename + (docroot_len-1);
if (wsgi_req->document_root[wsgi_req->document_root_len-1] == '/') {
wsgi_req->script_name = real_filename + (wsgi_req->document_root_len-1);
}
else {
wsgi_req->script_name = real_filename + docroot_len;
wsgi_req->script_name = real_filename + wsgi_req->document_root_len;
}
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
#ifdef UWSGI_DEBUG
uwsgi_log("php filename = %s\n", real_filename);
uwsgi_log("php filename = %s script_name = %.*s (%d) document_root = %.*s (%d)\n", real_filename, wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->script_name_len,
wsgi_req->document_root_len, wsgi_req->document_root, wsgi_req->document_root_len);
#endif
// now check for allowed paths and extensions
SG(request_info).request_uri = estrndup(wsgi_req->uri, wsgi_req->uri_len);
@@ -437,6 +887,9 @@ secure2:
SG(request_info).content_length = wsgi_req->post_cl;
SG(request_info).content_type = estrndup(wsgi_req->content_type, wsgi_req->content_type_len);
// reinitialize it at every request !!!
SG(sapi_headers).http_response_code = 200;
SG(request_info).path_translated = wsgi_req->file;
file_handle.type = ZEND_HANDLE_FILENAME;
@@ -444,7 +897,6 @@ secure2:
file_handle.free_filename = 0;
file_handle.opened_path = NULL;
if (php_request_startup(TSRMLS_C) == FAILURE) {
internal_server_error(wsgi_req, "unable to start php request");
return -1;
@@ -463,32 +915,13 @@ void uwsgi_php_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
int uwsgi_php_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PHP_INI:
uwsgi_sapi_module.php_ini_path_override = uwsgi_str(optarg);
uwsgi_sapi_module.php_ini_ignore = 1;
return 1;
case LONG_ARGS_PHP_ALLOWED_DOCROOT:
uwsgi_string_new_list(&uphp.allowed_docroot, optarg);
return 1;
case LONG_ARGS_PHP_ALLOWED_EXT:
uwsgi_string_new_list(&uphp.allowed_ext, optarg);
return 1;
}
return 0;
}
SAPI_API struct uwsgi_plugin php_plugin = {
.name = "php",
.modifier1 = 14,
.init = uwsgi_php_init,
.request = uwsgi_php_request,
.after_request = uwsgi_php_after_request,
.options = uwsgi_php_options,
.manage_opt = uwsgi_php_manage_options,
};
+29
View File
@@ -0,0 +1,29 @@
import os
NAME='php'
ld_run_path = None
PHPPATH = 'php-config'
try:
phpdir = os.environ['UWSGICONFIG_PHPDIR']
ld_run_path = "%s/lib" % phpdir
PHPPATH = "%s/bin/php-config" % phpdir
except:
pass
try:
PHPPATH = os.environ['UWSGICONFIG_PHPPATH']
except:
pass
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip()]
LDFLAGS = os.popen(PHPPATH + ' --ldflags').read().rstrip().split()
if ld_run_path:
LDFLAGS.append('-L%s' % ld_run_path)
os.environ['LD_RUN_PATH'] = ld_run_path
LIBS = [os.popen(PHPPATH + ' --libs').read().rstrip(), '-lphp5']
GCC_LIST = ['php_plugin']
+4 -21
View File
@@ -7,10 +7,10 @@ struct uwsgi_ping {
int ping_timeout;
} uping;
struct option uwsgi_ping_options[] = {
{"ping", required_argument, 0, LONG_ARGS_PING},
{"ping-timeout", required_argument, 0, LONG_ARGS_PING_TIMEOUT},
{ 0, 0, 0, 0 }
struct uwsgi_option uwsgi_ping_options[] = {
{"ping", required_argument, 0, "ping specified uwsgi host", uwsgi_opt_set_str, &uping.ping, UWSGI_OPT_NO_INITIAL | UWSGI_OPT_NO_SERVER},
{"ping-timeout", required_argument, 0, "set ping timeout", uwsgi_opt_set_int, &uping.ping_timeout, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
static void ping() {
@@ -91,28 +91,11 @@ int uwsgi_request_ping(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
int uwsgi_ping_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PING:
uwsgi.no_initial_output = 1;
uwsgi.no_server = 1;
uping.ping = optarg;
return 1;
case LONG_ARGS_PING_TIMEOUT:
uping.ping_timeout = atoi(optarg);
return 1;
}
return 0;
}
struct uwsgi_plugin ping_plugin = {
.name = "ping",
.modifier1 = 100,
.options = uwsgi_ping_options,
.manage_opt = uwsgi_ping_manage_options,
.request = uwsgi_request_ping,
.init = ping_init,
};
+23 -15
View File
@@ -11,27 +11,33 @@
struct uwsgi_perl {
int fd;
char *psgibuffer;
// path of the statically loaded main app
char *psgi;
// locallib path
char *locallib;
// perl argv for initialization
char *embedding[3];
PerlInterpreter *main;
pthread_key_t u_interpreter;
PerlInterpreter **interp;
SV *psgi_main;
SV **psgi_func;
CV *stream_responder;
HV *streaming_stash;
HV *input_stash;
HV *error_stash;
// check for Devel::StackTrace
int no_die_catch;
int stacktrace_available;
// this is a pointer to the main list of interpreters (required for signals, rpc....);
PerlInterpreter **main;
// a lock for dynamic apps
pthread_mutex_t lock_loader;
// this fields must be heavy protected in threaded modes
int tmp_current_i;
HV **tmp_streaming_stash;
HV **tmp_input_stash;
HV **tmp_error_stash;
CV **tmp_stream_responder;
};
#define LONG_ARGS_PERL_BASE 17000 + ((5 + 1) * 1000)
#define LONG_ARGS_PSGI LONG_ARGS_PERL_BASE + 1
#define LONG_ARGS_PERL_LOCAL_LIB LONG_ARGS_PERL_BASE + 2
void init_perl_embedded_module(void);
void uwsgi_psgi_app(void);
int psgi_response(struct wsgi_request *, AV*);
@@ -41,3 +47,5 @@ int psgi_response(struct wsgi_request *, AV*);
SV *uwsgi_perl_obj_call(SV *, char *);
int uwsgi_perl_obj_can(SV *, char *, size_t);
int init_psgi_app(struct wsgi_request *, char *, uint16_t, PerlInterpreter **);
PerlInterpreter *uwsgi_perl_new_interpreter(void);
+248 -83
View File
@@ -15,19 +15,23 @@ XS(XS_input_seek) {
XS(XS_error) {
dXSARGS;
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
psgi_check_args(0);
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.error_stash);
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[wsgi_req->async_id]);
XSRETURN(1);
}
XS(XS_input) {
dXSARGS;
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
psgi_check_args(0);
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.input_stash);
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[wsgi_req->async_id]);
XSRETURN(1);
}
@@ -35,6 +39,7 @@ XS(XS_stream)
{
dXSARGS;
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
psgi_check_args(1);
@@ -47,7 +52,7 @@ XS(XS_stream)
while (psgi_response(wsgi_req, response) != UWSGI_OK);
SvREFCNT_dec(response);
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.streaming_stash);
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[wsgi_req->async_id]);
XSRETURN(1);
}
else {
@@ -184,6 +189,21 @@ XS(XS_error_print) {
XSRETURN(0);
}
XS(XS_uwsgi_stacktrace) {
dXSARGS;
psgi_check_args(0);
uwsgi_log("*** uWSGI perl stacktrace ***\n");
SV *ret = perl_eval_pv("Devel::StackTrace->new->as_string;", 0);
uwsgi_log("%s", SvPV_nolen(ret));
uwsgi_log("*** end of perl stacktrace ***\n\n");
XSRETURN(0);
}
/* automatically generated */
EXTERN_C void xs_init (pTHX);
@@ -203,18 +223,21 @@ xs_init(pTHX)
newXS("uwsgi::input::read", XS_input_read, "uwsgi::input");
newXS("uwsgi::input::seek", XS_input_seek, "uwsgi::input");
uperl.input_stash = gv_stashpv("uwsgi::input", 0);
uperl.tmp_input_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::input", 0);
newXS("uwsgi::error::new", XS_error, "uwsgi::error");
newXS("uwsgi::error::print", XS_error_print, "uwsgi::print");
uperl.error_stash = gv_stashpv("uwsgi::error", 0);
uperl.tmp_error_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::error", 0);
uperl.stream_responder = newXS("uwsgi::stream", XS_stream, "uwsgi");
uperl.tmp_stream_responder[uperl.tmp_current_i] = newXS("uwsgi::stream", XS_stream, "uwsgi");
newXS("uwsgi::streaming::write", XS_streaming_write, "uwsgi::streaming");
newXS("uwsgi::streaming::close", XS_streaming_close, "uwsgi::streaming");
uperl.streaming_stash = gv_stashpv("uwsgi::streaming", 0);
newXS("uwsgi::stacktrace", XS_uwsgi_stacktrace, "uwsgi");
uperl.tmp_streaming_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::streaming", 0);
#ifdef UWSGI_EMBEDDED
init_perl_embedded_module();
@@ -224,87 +247,229 @@ xs_init(pTHX)
/* end of automagically generated part */
PerlInterpreter *uwsgi_perl_new_interpreter(void) {
PerlInterpreter *pi = perl_alloc();
if (!pi) {
uwsgi_log("unable to allocate perl interpreter\n");
return NULL;
}
PERL_SET_CONTEXT(pi);
PL_perl_destruct_level = 2;
PL_origalen = 1;
perl_construct(pi);
// over-engeneering
PL_origalen = 1;
return pi;
}
static void uwsgi_perl_free_stashes(void) {
free(uperl.tmp_streaming_stash);
free(uperl.tmp_input_stash);
free(uperl.tmp_error_stash);
free(uperl.tmp_stream_responder);
}
int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, PerlInterpreter **interpreters) {
struct stat st;
int i;
SV **callables;
time_t now = uwsgi_now();
char *app_name = uwsgi_concat2n(app, app_len, "", 0);
// prepare for $0
uperl.embedding[1] = app_name;
int fd = open(app_name, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(app_name);
goto clear2;
}
if (fstat(fd, &st)) {
uwsgi_error("fstat()");
close(fd);
goto clear2;
}
char *buf = uwsgi_calloc(st.st_size+1);
if (read(fd, buf, st.st_size) != st.st_size) {
uwsgi_error("read()");
close(fd);
free(buf);
goto clear2;
}
close(fd);
// the first (default) app, should always be loaded in the main interpreter
if (interpreters == NULL) {
if (uwsgi_apps_cnt) {
interpreters = uwsgi_calloc(sizeof(PerlInterpreter *) * uwsgi.threads);
interpreters[0] = uwsgi_perl_new_interpreter();
if (!interpreters[0]) {
uwsgi_log("unable to create new perl interpreter\n");
free(interpreters);
goto clear2;
}
}
else {
interpreters = uperl.main;
}
}
if (!interpreters) {
goto clear2;
}
callables = uwsgi_calloc(sizeof(SV *) * uwsgi.threads);
uperl.tmp_streaming_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
uperl.tmp_input_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
uperl.tmp_error_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
uperl.tmp_stream_responder = uwsgi_calloc(sizeof(CV *) * uwsgi.threads);
for(i=0;i<uwsgi.threads;i++) {
if (i > 0 && interpreters != uperl.main) {
interpreters[i] = uwsgi_perl_new_interpreter();
if (!interpreters[i]) {
uwsgi_log("unable to create new perl interpreter\n");
// what to do here ? i hope no-one will use threads with dynamic apps...but clear the whole stuff...
free(callables);
uwsgi_perl_free_stashes();
while(i>=0) {
perl_destruct(interpreters[i]);
perl_free(interpreters[i]);
goto clear2;
}
}
}
PERL_SET_CONTEXT(interpreters[i]);
uperl.tmp_current_i = i;
if (uperl.locallib) {
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
uperl.embedding[2] = app_name;
if (perl_parse(interpreters[i], xs_init, 3, uperl.embedding, NULL)) {
// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
free(uperl.embedding[1]);
uperl.embedding[1] = app_name;
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
free(uperl.embedding[1]);
uperl.embedding[1] = app_name;
}
else {
if (perl_parse(interpreters[i], xs_init, 2, uperl.embedding, NULL)) {
// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
}
perl_eval_pv("use IO::Handle;", 0);
perl_eval_pv("use IO::File;", 0);
if (!uperl.no_die_catch) {
perl_eval_pv("use Devel::StackTrace;", 0);
if (!SvTRUE(ERRSV)) {
uperl.stacktrace_available = 1;
perl_eval_pv("$SIG{__DIE__} = \\&uwsgi::stacktrace;", 0);
}
}
SV *dollar_zero = get_sv("0", GV_ADD);
sv_setsv(dollar_zero, newSVpv(app, app_len));
callables[i] = perl_eval_pv(uwsgi_concat4("#line 1 ", app_name, "\n", buf), 0);
if (!callables[i]) {
uwsgi_log("unable to find PSGI function entry point.\n");
// what to do here ? i hope no-one will use threads with dynamic apps...
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
PERL_SET_CONTEXT(interpreters[0]);
}
free(buf);
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
int id = uwsgi_apps_cnt;
struct uwsgi_app *wi = NULL;
if (wsgi_req) {
// we need a copy of app_id
wi = uwsgi_add_app(id, 5, uwsgi_concat2n(wsgi_req->appid, wsgi_req->appid_len, "", 0), wsgi_req->appid_len, interpreters, callables);
}
else {
wi = uwsgi_add_app(id, 5, "", 0, interpreters, callables);
}
wi->started_at = now;
wi->startup_time = uwsgi_now() - now;
uwsgi_log("PSGI app %d (%s) loaded in %d seconds at %p (interpreter %p)\n", id, app_name, (int) wi->startup_time, callables[0], interpreters[0]);
free(app_name);
// copy global data to app-specific areas
wi->stream = uperl.tmp_streaming_stash;
wi->input = uperl.tmp_input_stash;
wi->error = uperl.tmp_error_stash;
wi->responder0 = uperl.tmp_stream_responder;
uwsgi_emulate_cow_for_apps(id);
// restore context if required
if (interpreters != uperl.main) {
PERL_SET_CONTEXT(uperl.main[0]);
}
return id;
clear:
if (interpreters != uperl.main) {
for(i=0;i<uwsgi.threads;i++) {
perl_destruct(interpreters[i]);
perl_free(interpreters[i]);
}
free(interpreters);
}
PERL_SET_CONTEXT(uperl.main[0]);
clear2:
free(app_name);
return -1;
}
void uwsgi_psgi_app() {
struct stat stat_psgi;
int id = uwsgi_apps_cnt;
if (uperl.psgi) {
// two-pass loading: parse the script -> eval the script
if (uperl.locallib) {
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
uperl.embedding[2] = uperl.psgi;
if (perl_parse(uperl.main, xs_init, 3, uperl.embedding, NULL)) {
exit(1);
}
}
else {
uperl.embedding[1] = uperl.psgi;
if (perl_parse(uperl.main, xs_init, 2, uperl.embedding, NULL)) {
exit(1);
}
}
perl_eval_pv("use IO::Handle;", 0);
perl_eval_pv("use IO::File;", 0);
SV *dollar_zero = get_sv("0", GV_ADD);
sv_setsv(dollar_zero, newSVpv(uperl.psgi, 0));
SV *dollar_slash = get_sv("/", GV_ADD);
sv_setsv(dollar_slash, newRV_inc(newSViv(uwsgi.buffer_size)));
uperl.fd = open(uperl.psgi, O_RDONLY);
if (uperl.fd < 0) {
uwsgi_error_open(uperl.psgi);
exit(1);
}
if (fstat(uperl.fd, &stat_psgi)) {
uwsgi_error("fstat()");
exit(1);
}
uperl.psgibuffer = malloc(stat_psgi.st_size + 1);
if (!uperl.psgibuffer) {
uwsgi_error("malloc()");
exit(1);
}
if (read(uperl.fd, uperl.psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) {
uwsgi_error("read()");
exit(1);
}
uperl.psgibuffer[stat_psgi.st_size] = 0;
uperl.psgi_main = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
if (!uperl.psgi_main) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
if (uwsgi.threads < 2) {
free(uperl.psgibuffer);
close(uperl.fd);
}
uwsgi_add_app(id, 5, "", 0);
uwsgi_log("PSGI app %d (%s) loaded at %p\n", id, uperl.psgi, uperl.psgi_main);
//load app in the main interpreter list
init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main);
}
}
+133 -114
View File
@@ -9,11 +9,12 @@ extern struct uwsgi_perl uperl;
struct uwsgi_perl uperl;
#endif
struct option uwsgi_perl_options[] = {
struct uwsgi_option uwsgi_perl_options[] = {
{"psgi", required_argument, 0, LONG_ARGS_PSGI},
{"perl-local-lib", required_argument, 0, LONG_ARGS_PERL_LOCAL_LIB},
{0, 0, 0, 0},
{"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0},
{"perl-no-die-catch", no_argument, 0, "do not catch $SIG{__DIE__}", uwsgi_opt_true, &uperl.no_die_catch, 0},
{"perl-local-lib", required_argument, 0, "set perl locallib path", uwsgi_opt_set_str, &uperl.locallib, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -22,8 +23,7 @@ extern struct http_status_codes hsc[];
SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
SV *newobj;
// set current context ?
dTHX;
dSP;
ENTER;
@@ -48,21 +48,21 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
SV *uwsgi_perl_call_stream(SV *func) {
SV *ret = NULL;
// set current context ?
dTHX;
dSP;
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( sv_2mortal(newRV((SV*) uperl.stream_responder)));
XPUSHs( sv_2mortal(newRV((SV*) ((SV **)wi->responder0)[wsgi_req->async_id])));
PUTBACK;
call_sv( func, G_SCALAR | G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV));
}
else {
ret = SvREFCNT_inc(POPs);
@@ -78,8 +78,7 @@ SV *uwsgi_perl_call_stream(SV *func) {
int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
int ret;
// set current context ? needed for threading
dTHX;
dSP;
ENTER;
@@ -102,12 +101,10 @@ int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
}
SV *uwsgi_perl_obj_call(SV *obj, char *method) {
SV *ret = NULL;
dTHX;
dSP;
ENTER;
@@ -141,7 +138,6 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
AV *ret = NULL;
dTHX;
dSP;
ENTER;
@@ -156,7 +152,7 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
if(SvTRUE(ERRSV)) {
internal_server_error(wsgi_req, "exception raised");
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV));
}
else {
ret = (AV *) SvREFCNT_inc(SvRV(POPs));
@@ -284,10 +280,19 @@ int uwsgi_perl_init(){
struct http_status_codes *http_sc;
int argc;
int i;
uperl.embedding[0] = "";
uperl.embedding[1] = "-e";
uperl.embedding[2] = "0";
#ifndef USE_ITHREADS
if (uwsgi.threads > 1) {
uwsgi_log("your Perl environment does not support threads\n");
exit(1);
}
#endif
if (setenv("PLACK_ENV", "uwsgi", 0)) {
uwsgi_error("setenv()");
}
@@ -296,92 +301,102 @@ int uwsgi_perl_init(){
uwsgi_error("setenv()");
}
#ifdef PERL_VERSION_STRING
uwsgi_log("initializing Perl %s environment\n", PERL_VERSION_STRING);
#else
uwsgi_log("initializing Perl environment\n");
#endif
argc = 3;
PERL_SYS_INIT3(&argc, (char ***) &uperl.embedding, &environ);
uperl.main = perl_alloc();
if (!uperl.main) {
uwsgi_log("unable to allocate perl interpreter\n");
uperl.main = uwsgi_calloc(sizeof(PerlInterpreter *) * uwsgi.threads);
uperl.main[0] = uwsgi_perl_new_interpreter();
if (!uperl.main[0]) {
return -1;
}
dTHXa(uperl.main);
PERL_SET_CONTEXT(uperl.main);
for(i=1;i<uwsgi.threads;i++) {
uperl.main[i] = uwsgi_perl_new_interpreter();
if (!uperl.main[i]) {
uwsgi_log("unable to create new perl interpreter for thread %d\n", i+1);
exit(1);
}
}
PL_perl_destruct_level = 2;
PL_origalen = 1;
perl_construct(uperl.main);
PERL_SET_CONTEXT(uperl.main[0]);
// filling http status codes
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = strlen(http_sc->message);
}
PL_origalen = 1;
#ifdef PERL_VERSION_STRING
uwsgi_log("initialized Perl %s main interpreter at %p\n", PERL_VERSION_STRING, uperl.main[0]);
#else
uwsgi_log("initialized Perl main interpreter at %p\n", uperl.main[0]);
#endif
return 1;
}
#ifdef USE_ITHREADS
void uwsgi_perl_enable_threads() {
if (pthread_key_create(&uperl.u_interpreter, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
uperl.interp = uwsgi_malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
uperl.interp[0] = uperl.main;
uperl.psgi_func = uwsgi_malloc( sizeof(SV*) * uwsgi.threads );
}
#endif
int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
SV **harakiri;
SV *psgi_func = uperl.psgi_main;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
return psgi_response(wsgi_req, wsgi_req->async_placeholder);
}
#endif
/* Standard PSGI request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log("Invalid PSGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
if (uwsgi.threads > 1) {
psgi_func = uperl.psgi_func[wsgi_req->async_id];
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 5);
// if it is -1, try to load a dynamic app
if (wsgi_req->app_id == -1) {
if (wsgi_req->dynamic) {
if (uwsgi.threads > 1) {
pthread_mutex_lock(&uperl.lock_loader);
}
if (wsgi_req->script_len > 0) {
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->script, wsgi_req->script_len, NULL);
}
else if (wsgi_req->file_len > 0) {
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->file, wsgi_req->file_len, NULL);
}
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&uperl.lock_loader);
}
}
if (wsgi_req->app_id == -1) {
internal_server_error(wsgi_req, "Perl application not found");
// nothing to clear/free
return UWSGI_OK;
}
}
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
wi->requests++;
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
PERL_SET_CONTEXT(((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id]);
}
ENTER;
SAVETMPS;
wsgi_req->async_environ = build_psgi_env(wsgi_req);
if (!wsgi_req->async_environ) goto clear;
wsgi_req->async_result = psgi_call(wsgi_req, psgi_func, wsgi_req->async_environ);
wsgi_req->async_result = psgi_call(wsgi_req, ((SV **)wi->callable)[wsgi_req->async_id], wsgi_req->async_environ);
if (!wsgi_req->async_result) goto clear;
if (SvTYPE((AV *)wsgi_req->async_result) == SVt_PVCV) {
@@ -419,6 +434,11 @@ clear:
FREETMPS;
LEAVE;
// restore main interpreter if needed
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
PERL_SET_CONTEXT(uperl.main[wsgi_req->async_id]);
}
return UWSGI_OK;
}
@@ -435,56 +455,6 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
}
#ifdef USE_ITHREADS
void uwsgi_perl_init_thread(int core_id) {
if (core_id > 0) {
uperl.interp[core_id] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
if (!uperl.interp[core_id]) {
uwsgi_log("unable to create new perl interpreter\n");
exit(1);
}
}
dTHXa(uperl.interp[core_id]);
PERL_SET_CONTEXT(uperl.interp[core_id]);
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
uperl.psgi_func[0] = uperl.psgi_main;
if (core_id > 0) {
uperl.psgi_func[core_id] = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
if (!uperl.psgi_func[core_id]) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
}
}
#endif
int uwsgi_perl_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PSGI:
uperl.psgi = optarg;
return 1;
case LONG_ARGS_PERL_LOCAL_LIB:
uperl.locallib = optarg;
return 1;
}
return 0;
}
int uwsgi_perl_magic(char *mountpoint, char *lazy) {
if (!strcmp(lazy+strlen(lazy)-5, ".psgi")) {
@@ -500,6 +470,55 @@ int uwsgi_perl_magic(char *mountpoint, char *lazy) {
}
// taken from Torsten Foertsch AfterFork.xs
void uwsgi_perl_post_fork() {
GV *tmpgv = gv_fetchpv("$", TRUE, SVt_PV);
if (tmpgv) {
SvREADONLY_off(GvSV(tmpgv));
sv_setiv(GvSV(tmpgv), (IV)getpid());
SvREADONLY_on(GvSV(tmpgv));
}
}
int uwsgi_perl_mount_app(char *mountpoint, char *app, int regexp) {
if (uwsgi_endswith(app, ".pl") || uwsgi_endswith(app, ".psgi")) {
uwsgi.wsgi_req->appid = mountpoint;
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
return init_psgi_app(uwsgi.wsgi_req, app, strlen(app), NULL);
}
return -1;
}
void uwsgi_perl_init_thread(int core_id) {
#ifdef USE_ITHREADS
PERL_SET_CONTEXT(uperl.main[core_id]);
#endif
}
void uwsgi_perl_pthread_prepare(void) {
pthread_mutex_lock(&uperl.lock_loader);
}
void uwsgi_perl_pthread_parent(void) {
pthread_mutex_unlock(&uperl.lock_loader);
}
void uwsgi_perl_pthread_child(void) {
pthread_mutex_init(&uperl.lock_loader, NULL);
}
void uwsgi_perl_enable_threads(void) {
#ifdef USE_ITHREADS
pthread_mutex_init(&uperl.lock_loader, NULL);
pthread_atfork(uwsgi_perl_pthread_prepare, uwsgi_perl_pthread_parent, uwsgi_perl_pthread_child);
#endif
}
struct uwsgi_plugin psgi_plugin = {
@@ -507,16 +526,16 @@ struct uwsgi_plugin psgi_plugin = {
.modifier1 = 5,
.init = uwsgi_perl_init,
.options = uwsgi_perl_options,
.init_apps = uwsgi_psgi_app,
//.magic = uwsgi_perl_magic,
//.help = uwsgi_perl_help,
#ifdef USE_ITHREADS
.enable_threads = uwsgi_perl_enable_threads,
.mount_app = uwsgi_perl_mount_app,
.init_thread = uwsgi_perl_init_thread,
#endif
.manage_opt = uwsgi_perl_manage_options,
.post_fork = uwsgi_perl_post_fork,
.request = uwsgi_perl_request,
.after_request = uwsgi_perl_after_request,
.enable_threads = uwsgi_perl_enable_threads,
.magic = uwsgi_perl_magic,
};
+1 -3
View File
@@ -126,9 +126,7 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
vi = (i*2)+base;
wsgi_req->hvec[vi].iov_base = "\r\n"; wsgi_req->hvec[vi].iov_len = 2;
if ( !(wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, vi+1)) ) {
uwsgi_error("writev()");
}
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, vi+1);
hitem = av_fetch(response, 2, 0);
+22 -2
View File
@@ -76,13 +76,21 @@ XS(XS_wait_fd_write) {
#endif
XS(XS_signal) {
dXSARGS;
psgi_check_args(1);
uwsgi_signal_send(uwsgi.signal_socket, SvIV(ST(0)));
XSRETURN_UNDEF;
}
XS(XS_reload) {
dXSARGS;
psgi_check_args(0);
psgi_check_args(0);
uwsgi_log("SENDING HUP TO %d\n", (int) uwsgi.workers[0].pid);
if (kill(uwsgi.workers[0].pid, SIGHUP)) {
uwsgi_error("kill()");
XSRETURN_NO;
@@ -96,14 +104,19 @@ XS(XS_cache_set) {
char *key, *val;
STRLEN keylen;
STRLEN vallen;
if (uwsgi.cache_max_items == 0) goto clear;
psgi_check_args(2);
key = SvPV(ST(0), keylen);
val = SvPV(ST(1), vallen);
uwsgi_wlock(uwsgi.cache_lock);
uwsgi_cache_set(key, (uint16_t) keylen, val, (uint64_t) vallen, 0, 0);
uwsgi_rwunlock(uwsgi.cache_lock);
clear:
XSRETURN_UNDEF;
}
@@ -113,17 +126,23 @@ XS(XS_cache_get) {
char *key, *val;
STRLEN keylen;
uint64_t vallen;
if (uwsgi.cache_max_items == 0) goto clear;
psgi_check_args(1);
key = SvPV(ST(0), keylen);
uwsgi_rlock(uwsgi.cache_lock);
val = uwsgi_cache_get(key, (uint16_t) keylen, &vallen);
if (!val)
uwsgi_rwunlock(uwsgi.cache_lock);
clear:
XSRETURN_UNDEF;
ST(0) = newSVpv(val, vallen);
uwsgi_rwunlock(uwsgi.cache_lock);
sv_2mortal(ST(0));
XSRETURN(1);
@@ -209,5 +228,6 @@ void init_perl_embedded_module() {
psgi_xs(log);
psgi_xs(async_connect);
psgi_xs(suspend);
psgi_xs(signal);
}
+13
View File
@@ -0,0 +1,13 @@
import os,sys
from distutils import sysconfig
NAME='pypy'
GCC_LIST = ['../python/python_plugin', '../python/pyutils', '../python/pyloader', '../python/wsgi_handlers', '../python/wsgi_headers', '../python/wsgi_subhandler',
'../python/web3_subhandler', '../python/pump_subhandler','../python/gil', '../python/uwsgi_pymodule', '../python/profiler', '../python/symimporter']
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
CFLAGS.append('-DUWSGI_PYPY')
LIBS = ['-lpypy-c']
LDFLAGS = []
+2 -8
View File
@@ -3,14 +3,9 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
#ifdef UWSGI_PYPY
void gil_real_get() {}
void gil_real_release() {}
#else
void gil_real_get() {
//uwsgi_log("LOCK %d\n", uwsgi.mywid);
#ifndef PYTHREE
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
PyEval_AcquireLock();
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_gil_key));
#else
@@ -22,7 +17,7 @@ void gil_real_get() {
void gil_real_release() {
//uwsgi_log("UNLOCK %d\n", uwsgi.mywid);
#ifndef PYTHREE
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
pthread_setspecific(up.upt_gil_key, (void *) PyThreadState_Swap(NULL));
PyEval_ReleaseLock();
#else
@@ -31,7 +26,6 @@ void gil_real_release() {
#endif
}
#endif
void gil_fake_get() {}
void gil_fake_release() {}
+37 -2
View File
@@ -16,15 +16,27 @@ int PyFrame_GetLineNumber(PyFrameObject *frame) {
int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
#ifndef UWSGI_PYPY
static uint64_t last_ts = 0;
uint64_t now = uwsgi_micros();
uint64_t delta = 0;
switch(what) {
case PyTrace_CALL:
uwsgi_log("[uWSGI Python profiler] CALL: %s (line %d) -> %s %d args, stacksize %d\n",
if (last_ts == 0) delta = 0;
else delta = now - last_ts;
last_ts = now;
uwsgi_log("[uWSGI Python profiler %llu] CALL: %s (line %d) -> %s %d args, stacksize %d\n",
(unsigned long long) delta,
PyString_AsString(frame->f_code->co_filename),
PyFrame_GetLineNumber(frame),
PyString_AsString(frame->f_code->co_name), frame->f_code->co_argcount, frame->f_code->co_stacksize);
break;
case PyTrace_C_CALL:
uwsgi_log("[uWSGI Python profiler] C CALL: %s (line %d) -> %s %d args, stacksize %d\n",
if (last_ts == 0) delta = 0;
else delta = now - last_ts;
last_ts = now;
uwsgi_log("[uWSGI Python profiler %llu] C CALL: %s (line %d) -> %s %d args, stacksize %d\n",
(unsigned long long) delta,
PyString_AsString(frame->f_code->co_filename),
PyFrame_GetLineNumber(frame),
PyEval_GetFuncName(arg), frame->f_code->co_argcount, frame->f_code->co_stacksize);
@@ -34,3 +46,26 @@ int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, Py
return 0;
}
int uwsgi_python_tracer(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
#ifndef UWSGI_PYPY
static uint64_t last_ts = 0;
uint64_t now = uwsgi_micros();
uint64_t delta = 0;
if (what == PyTrace_LINE) {
if (last_ts == 0) {
delta = 0;
}
else {
delta = now - last_ts;
}
last_ts = now;
uwsgi_log("[uWSGI Python profiler %llu] file %s line %d: %s argc:%d\n", (unsigned long long)delta, PyString_AsString(frame->f_code->co_filename), PyFrame_GetLineNumber(frame), PyString_AsString(frame->f_code->co_name), frame->f_code->co_argcount);
}
#endif
return 0;
}
-11
View File
@@ -185,8 +185,6 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
struct http_status_codes *http_sc;
char sc[4];
UWSGI_GET_GIL
// ok its a yield
if (!wsgi_req->async_placeholder) {
if (PyDict_Check((PyObject *)wsgi_req->async_result)) {
@@ -339,7 +337,6 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
}
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
#endif
@@ -371,22 +368,14 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
Py_DECREF(pychunk);
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
clear:
if (wsgi_req->async_input) {
Py_DECREF((PyObject *)wsgi_req->async_input);
}
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
UWSGI_RELEASE_GIL
return UWSGI_OK;
}
+46 -32
View File
@@ -86,6 +86,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
struct uwsgi_app *wi;
time_t now = uwsgi_now();
mountpoint = uwsgi_strncopy(wsgi_req->appid, wsgi_req->appid_len);
@@ -375,14 +376,17 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
uwsgi.default_app = id;
}
wi->started_at = now;
wi->startup_time = uwsgi_now() - now;
if (app_type == PYTHON_APP_TYPE_WSGI) {
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
uwsgi_log( "WSGI app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
}
else if (app_type == PYTHON_APP_TYPE_WEB3) {
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
uwsgi_log( "Web3 app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
}
else if (app_type == PYTHON_APP_TYPE_PUMP) {
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
uwsgi_log( "Pump app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
}
@@ -414,19 +418,15 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
}
// check if we need to emulate fork() COW
if (uwsgi.mywid == 0) {
for(i=1;i<=uwsgi.numproc;i++) {
memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
}
}
// emulate COW
uwsgi_emulate_cow_for_apps(id);
return id;
doh:
free(mountpoint);
PyErr_Print();
if (PyErr_Occurred())
PyErr_Print();
#ifdef UWSGI_MINTERPRETERS
if (interpreter == NULL && id) {
Py_EndInterpreter(wi->interpreter);
@@ -482,9 +482,7 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
PyObject *tmp_callable;
PyObject *applications;
#ifndef UWSGI_PYPY
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
#endif
char *module = (char *) arg1;
@@ -507,11 +505,8 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
return NULL;
}
#ifndef UWSGI_PYPY
applications = PyDict_GetItemString(uwsgi_dict, "applications");
if (applications && PyDict_Check(applications)) return applications;
#endif
applications = PyDict_GetItemString(wsgi_dict, "applications");
if (applications && PyDict_Check(applications)) return applications;
@@ -539,7 +534,7 @@ PyObject *uwsgi_mount_loader(void *arg1) {
if ( !strcmp(what+strlen(what)-3, ".py") || !strcmp(what+strlen(what)-5, ".wsgi")) {
callable = uwsgi_file_loader((void *)what);
if (!callable) exit(1);
if (!callable) exit(UWSGI_FAILED_APP_CODE);
}
else if (!strcmp(what+strlen(what)-4, ".ini")) {
callable = uwsgi_paste_loader((void *)what);
@@ -655,39 +650,58 @@ PyObject *uwsgi_paste_loader(void *arg1) {
PyObject *paste_arg, *paste_app;
uwsgi_log( "Loading paste environment: %s\n", paste);
if (up.paste_logger) {
PyObject *paste_logger_dict = get_uwsgi_pydict("paste.script.util.logging_config");
if (paste_logger_dict) {
PyObject *paste_logger_fileConfig = PyDict_GetItemString(paste_logger_dict, "fileConfig");
if (paste_logger_fileConfig) {
PyObject *paste_logger_arg = PyTuple_New(1);
if (!paste_logger_arg) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
PyTuple_SetItem(paste_logger_arg, 0, PyString_FromString(paste+7));
if (python_call(paste_logger_fileConfig, paste_logger_arg, 0, NULL)) {
PyErr_Print();
}
}
}
}
paste_module = PyImport_ImportModule("paste.deploy");
if (!paste_module) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
paste_dict = PyModule_GetDict(paste_module);
if (!paste_dict) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
paste_loadapp = PyDict_GetItemString(paste_dict, "loadapp");
if (!paste_loadapp) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
paste_arg = PyTuple_New(1);
if (!paste_arg) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
if (PyTuple_SetItem(paste_arg, 0, PyString_FromString(paste))) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
paste_app = PyEval_CallObject(paste_loadapp, paste_arg);
if (!paste_app) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
@@ -696,8 +710,10 @@ PyObject *uwsgi_paste_loader(void *arg1) {
PyObject *uwsgi_eval_loader(void *arg1) {
#ifndef UWSGI_PYPY
#ifdef UWSGI_PYPY
uwsgi_log("the eval loader is currently not supported under PyPy !!!\n");
return NULL;
#else
char *code = (char *) arg1;
PyObject *wsgi_eval_module, *wsgi_eval_callable = NULL;
@@ -709,7 +725,7 @@ PyObject *uwsgi_eval_loader(void *arg1) {
if (!wsgi_eval_node) {
PyErr_Print();
uwsgi_log( "failed to parse <eval> code\n");
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
wsgi_compiled_node = (PyObject *) PyNode_Compile(wsgi_eval_node, "uwsgi_eval_config");
@@ -717,14 +733,14 @@ PyObject *uwsgi_eval_loader(void *arg1) {
if (!wsgi_compiled_node) {
PyErr_Print();
uwsgi_log( "failed to compile eval code\n");
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
wsgi_eval_module = PyImport_ExecCodeModule("uwsgi_eval_config", wsgi_compiled_node);
if (!wsgi_eval_module) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
@@ -733,7 +749,7 @@ PyObject *uwsgi_eval_loader(void *arg1) {
up.loader_dict = PyModule_GetDict(wsgi_eval_module);
if (!up.loader_dict) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
@@ -748,13 +764,11 @@ PyObject *uwsgi_eval_loader(void *arg1) {
if (wsgi_eval_callable) {
if (!PyFunction_Check(wsgi_eval_callable) && !PyCallable_Check(wsgi_eval_callable)) {
uwsgi_log( "you must define a callable object in your code\n");
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
}
return wsgi_eval_callable;
#else
return NULL;
#endif
}
File diff suppressed because it is too large Load Diff
+138 -23
View File
@@ -8,20 +8,106 @@ int manage_python_response(struct wsgi_request *wsgi_req) {
return uwsgi_response_subhandler_wsgi(wsgi_req);
}
PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi_request *wsgi_req) {
char *uwsgi_python_get_exception_type(PyObject *exc) {
char *class_name = NULL;
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
if (PyClass_Check(exc)) {
class_name = PyString_AsString( ((PyClassObject*)(exc))->cl_name );
}
else {
#endif
class_name = (char *) ((PyTypeObject*)exc)->tp_name;
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
}
#endif
PyObject *pyret;
if (class_name) {
char *dot = strrchr(class_name, '.');
if (dot) class_name = dot+1;
PyObject *module_name = PyObject_GetAttrString(exc, "__module__");
if (module_name) {
char *mod_name = PyString_AsString(module_name);
if (mod_name && strcmp(mod_name, "exceptions") ) {
char *ret = uwsgi_concat3(mod_name, ".", class_name);
Py_DECREF(module_name);
return ret;
}
Py_DECREF(module_name);
return uwsgi_str(class_name);
}
}
return NULL;
}
char *uwsgi_python_get_exception_value(PyObject *value) {
return PyString_AsString( PyObject_Str(value) );
}
char *uwsgi_python_get_exception_repr(PyObject *exc, PyObject *value) {
char *exc_type = uwsgi_python_get_exception_type(exc);
char *exc_value = uwsgi_python_get_exception_value(value);
if (exc_type && exc_value) {
return uwsgi_concat3(exc_type, ": ", exc_value);
}
return NULL;
}
int uwsgi_python_manage_exceptions(void) {
PyObject *type = NULL;
PyObject *value = NULL;
PyObject *traceback = NULL;
char *exc_type = NULL;
char *exc_value = NULL;
char *exc_repr = NULL;
PyErr_Fetch(&type, &value, &traceback);
PyErr_NormalizeException(&type, &value, &traceback);
if (uwsgi.reload_on_exception_type) {
exc_type = uwsgi_python_get_exception_type(type);
}
if (uwsgi.reload_on_exception_value) {
exc_value = uwsgi_python_get_exception_value(value);
}
if (uwsgi.reload_on_exception_repr) {
exc_repr = uwsgi_python_get_exception_repr(type, value);
}
int ret = uwsgi_manage_exception(exc_type, exc_value, exc_repr);
// free memory allocated for strcmp
if (exc_type) free(exc_type);
if (exc_repr) free(exc_repr);
PyErr_Restore(type, value, traceback);
return ret;
}
PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi_request *wsgi_req) {
//uwsgi_log("ready to call %p %p\n", callable, args);
pyret = PyEval_CallObject(callable, args);
PyObject *pyret = PyEval_CallObject(callable, args);
//uwsgi_log("called\n");
if (PyErr_Occurred()) {
int do_exit = uwsgi_python_manage_exceptions();
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
uwsgi_log("Memory Error detected !!!\n");
}
// this can be in a spooler or in the master
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].exceptions++;
@@ -32,6 +118,10 @@ PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi
if (!catch) {
PyErr_Print();
}
if (do_exit) {
exit(UWSGI_EXCEPTION_CODE);
}
}
#ifdef UWSGI_DEBUG
@@ -64,32 +154,60 @@ void init_pyargv() {
char *ap;
char *argv0 = "uwsgi";
if (up.pyrun) {
argv0 = up.pyrun;
}
#ifdef PYTHREE
wchar_t pname[6];
mbstowcs(pname, "uwsgi", 6);
up.py_argv[0] = pname;
wchar_t *pname = uwsgi_calloc(sizeof(wchar_t) * (strlen(argv0)+1));
mbstowcs(pname, argv0, strlen(argv0)+1);
#else
up.py_argv[0] = "uwsgi";
char *pname = argv0;
#endif
up.argc = 1;
if (up.argv != NULL) {
#ifdef PYTHREE
wchar_t *wcargv = malloc( sizeof( wchar_t ) * (strlen(up.argv)+1));
if (!wcargv) {
uwsgi_error("malloc()");
exit(1);
if (up.argv) {
char *tmp_ptr = uwsgi_str(up.argv);
#ifdef __sun__
// FIX THIS !!!
ap = strtok(tmp_ptr, " ");
while ((ap = strtok(NULL, " ")) != NULL) {
#else
while ((ap = strsep(&tmp_ptr, " \t")) != NULL) {
#endif
if (*ap != '\0') {
up.argc++;
}
}
memset(wcargv, 0, sizeof( wchar_t ) * (strlen(up.argv)+1));
free(tmp_ptr);
}
#ifdef PYTHREE
up.py_argv = uwsgi_calloc(sizeof(wchar_t *) * up.argc+1);
#else
up.py_argv = uwsgi_calloc(sizeof(char *) * up.argc+1);
#endif
up.py_argv[0] = pname;
if (up.argv) {
char *py_argv_copy = uwsgi_str(up.argv);
up.argc = 1;
#ifdef PYTHREE
wchar_t *wcargv = uwsgi_calloc( sizeof( wchar_t ) * (strlen(py_argv_copy)+1));
#endif
#ifdef __sun__
// FIX THIS !!!
ap = strtok(up.argv, " ");
ap = strtok(py_argv_copy, " ");
while ((ap = strtok(NULL, " ")) != NULL) {
#else
while ((ap = strsep(&up.argv, " \t")) != NULL) {
while ((ap = strsep(&py_argv_copy, " \t")) != NULL) {
#endif
if (*ap != '\0') {
#ifdef PYTHREE
@@ -100,14 +218,11 @@ void init_pyargv() {
#endif
up.argc++;
}
if (up.argc + 1 > MAX_PYARGV)
break;
}
}
#ifndef UWSGI_PYPY
PySys_SetArgv(up.argc, up.py_argv);
#endif
}
PySys_SetArgv(up.argc, up.py_argv);
PyObject *sys_dict = get_uwsgi_pydict("sys");
if (!sys_dict) {
+290 -93
View File
@@ -171,7 +171,7 @@ char *uwsgi_encode_pydict(PyObject * pydict, uint16_t * size) {
PyObject *py_uwsgi_listen_queue(PyObject * self, PyObject * args) {
#ifdef __linux__
return PyInt_FromLong(uwsgi.shared->ti.tcpi_unacked);
return PyInt_FromLong(uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]);
#else
return NULL;
#endif
@@ -312,7 +312,9 @@ PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
argvs[i] = PyString_Size(py_str);
}
UWSGI_RELEASE_GIL;
char *response = uwsgi_do_rpc(NULL, func, argc - 1, argv, argvs, &size);
UWSGI_GET_GIL;
if (size > 0) {
PyObject *ret = PyString_FromStringAndSize(response, size);
@@ -381,7 +383,9 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
argvs[i] = PyString_Size(py_str);
}
UWSGI_RELEASE_GIL;
char *response = uwsgi_do_rpc(node, func, argc - 2, argv, argvs, &size);
UWSGI_GET_GIL;
if (size > 0) {
PyObject *ret = PyString_FromStringAndSize(response, size);
@@ -884,7 +888,7 @@ PyObject *py_uwsgi_log(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_i_am_the_spooler(PyObject * self, PyObject * args) {
#ifdef UWSGI_SPOOLER
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
if (uwsgi.i_am_a_spooler) {
Py_INCREF(Py_True);
return Py_True;
}
@@ -894,13 +898,47 @@ PyObject *py_uwsgi_i_am_the_spooler(PyObject * self, PyObject * args) {
return Py_None;
}
PyObject *py_uwsgi_is_locked(PyObject * self, PyObject * args) {
int lock_num = 0;
// the spooler cannot lock resources
#ifdef UWSGI_SPOOLER
if (uwsgi.i_am_a_spooler) {
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
}
#endif
if (!PyArg_ParseTuple(args, "|i:is_locked", &lock_num)) {
return NULL;
}
if (lock_num < 0 || lock_num > uwsgi.locks) {
return PyErr_Format(PyExc_ValueError, "Invalid lock number");
}
UWSGI_RELEASE_GIL
if (uwsgi_lock_check(uwsgi.user_lock[lock_num]) == 0) {
UWSGI_GET_GIL
Py_INCREF(Py_False);
return Py_False;
}
UWSGI_GET_GIL
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_lock(PyObject * self, PyObject * args) {
int lock_num = 0;
// the spooler cannot lock resources
#ifdef UWSGI_SPOOLER
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
if (uwsgi.i_am_a_spooler) {
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
}
#endif
@@ -913,7 +951,9 @@ PyObject *py_uwsgi_lock(PyObject * self, PyObject * args) {
return PyErr_Format(PyExc_ValueError, "Invalid lock number");
}
UWSGI_RELEASE_GIL
uwsgi_lock(uwsgi.user_lock[lock_num]);
UWSGI_GET_GIL
Py_INCREF(Py_None);
return Py_None;
@@ -924,7 +964,7 @@ PyObject *py_uwsgi_unlock(PyObject * self, PyObject * args) {
int lock_num = 0;
#ifdef UWSGI_SPOOLER
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
if (uwsgi.i_am_a_spooler) {
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
}
#endif
@@ -937,7 +977,6 @@ PyObject *py_uwsgi_unlock(PyObject * self, PyObject * args) {
return PyErr_Format(PyExc_ValueError, "Invalid lock number");
}
uwsgi_unlock(uwsgi.user_lock[lock_num]);
Py_INCREF(Py_None);
@@ -1035,7 +1074,9 @@ PyObject *py_uwsgi_farm_msg(PyObject * self, PyObject * args) {
for(i=0;i<uwsgi.farms_cnt;i++) {
if (!strcmp(farm_name, uwsgi.farms[i].name)) {
UWSGI_RELEASE_GIL
len = write(uwsgi.farms[i].queue_pipe[0], message, message_len);
UWSGI_GET_GIL
if (len <= 0) {
uwsgi_error("write()");
}
@@ -1066,7 +1107,9 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
return PyErr_Format(PyExc_ValueError, "no mule configured");
if (mule_obj == NULL) {
UWSGI_RELEASE_GIL
mule_send_msg(uwsgi.shared->mule_queue_pipe[0], message, message_len);
UWSGI_GET_GIL
}
else {
if (PyString_Check(mule_obj)) {
@@ -1093,7 +1136,9 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
}
if (fd > -1) {
UWSGI_RELEASE_GIL
mule_send_msg(fd, message, message_len);
UWSGI_GET_GIL
}
}
@@ -1238,6 +1283,8 @@ PyObject *py_uwsgi_sharedarea_inclong(PyObject * self, PyObject * args) {
Py_INCREF(Py_None);
return Py_None;
}
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.sa_lock);
@@ -1245,11 +1292,10 @@ PyObject *py_uwsgi_sharedarea_inclong(PyObject * self, PyObject * args) {
value = current_value + value;
memcpy(uwsgi.sharedarea + pos, &value, 8);
PyObject *ret = PyInt_FromLong(value);
uwsgi_rwunlock(uwsgi.sa_lock);
UWSGI_GET_GIL
return ret;
return PyInt_FromLong(value);
}
@@ -1271,16 +1317,17 @@ PyObject *py_uwsgi_sharedarea_writelong(PyObject * self, PyObject * args) {
return Py_None;
}
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.sa_lock);
memcpy(uwsgi.sharedarea + pos, &value, 8);
PyObject *ret = PyInt_FromLong(value);
uwsgi_rwunlock(uwsgi.sa_lock);
return ret;
UWSGI_GET_GIL
return PyInt_FromLong(value);
}
@@ -1303,15 +1350,19 @@ PyObject *py_uwsgi_sharedarea_write(PyObject * self, PyObject * args) {
return Py_None;
}
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.sa_lock);
memcpy(uwsgi.sharedarea + pos, value, value_len);
PyObject *ret = PyInt_FromLong(value_len);
uwsgi_rwunlock(uwsgi.sa_lock);
UWSGI_GET_GIL
return PyInt_FromLong(value_len);
return ret;
}
@@ -1334,15 +1385,18 @@ PyObject *py_uwsgi_sharedarea_writebyte(PyObject * self, PyObject * args) {
return Py_None;
}
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.sa_lock);
uwsgi.sharedarea[pos] = value;
PyObject *ret = PyInt_FromLong(uwsgi.sharedarea[pos]);
uwsgi_rwunlock(uwsgi.sa_lock);
return ret;
UWSGI_GET_GIL
return PyInt_FromLong(value);
}
@@ -1364,15 +1418,18 @@ PyObject *py_uwsgi_sharedarea_readlong(PyObject * self, PyObject * args) {
return Py_None;
}
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.sa_lock);
memcpy(&value, uwsgi.sharedarea + pos, 8);
PyObject *ret = PyLong_FromLong(value);
uwsgi_rwunlock(uwsgi.sa_lock);
return ret;
UWSGI_GET_GIL
return PyLong_FromLong(value);
}
@@ -1394,13 +1451,17 @@ PyObject *py_uwsgi_sharedarea_readbyte(PyObject * self, PyObject * args) {
return Py_None;
}
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.sa_lock);
PyObject *ret = PyInt_FromLong(uwsgi.sharedarea[pos]);
char value = uwsgi.sharedarea[pos];
uwsgi_rwunlock(uwsgi.sa_lock);
return ret;
UWSGI_GET_GIL
return PyInt_FromLong(value);
}
@@ -1422,12 +1483,23 @@ PyObject *py_uwsgi_sharedarea_read(PyObject * self, PyObject * args) {
return Py_None;
}
PyObject *ret = PyString_FromStringAndSize(NULL, len);
#ifdef PYTHREE
char *storage = PyBytes_AsString(ret);
#else
char *storage = PyString_AS_STRING(ret);
#endif
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.sa_lock);
PyObject *ret = PyString_FromStringAndSize(uwsgi.sharedarea + pos, len);
memcpy(storage, uwsgi.sharedarea + pos, len);
uwsgi_rwunlock(uwsgi.sa_lock);
UWSGI_GET_GIL
return ret;
}
@@ -1452,23 +1524,25 @@ PyObject *py_uwsgi_spooler_jobs(PyObject * self, PyObject * args) {
PyObject *jobslist = PyList_New(0);
sdir = opendir(uwsgi.spool_dir);
struct uwsgi_spooler *uspool = uwsgi.spoolers;
sdir = opendir(uspool->dir);
if (sdir) {
while ((dp = readdir(sdir)) != NULL) {
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19)) {
abs_path = malloc(strlen(uwsgi.spool_dir) + 1 + strlen(dp->d_name) + 1);
abs_path = malloc(strlen(uspool->dir) + 1 + strlen(dp->d_name) + 1);
if (!abs_path) {
uwsgi_error("malloc()");
closedir(sdir);
goto clear;
}
memset(abs_path, 0, strlen(uwsgi.spool_dir) + 1 + strlen(dp->d_name) + 1);
memset(abs_path, 0, strlen(uspool->dir) + 1 + strlen(dp->d_name) + 1);
memcpy(abs_path, uwsgi.spool_dir, strlen(uwsgi.spool_dir));
memcpy(abs_path + strlen(uwsgi.spool_dir), "/", 1);
memcpy(abs_path + strlen(uwsgi.spool_dir) + 1, dp->d_name, strlen(dp->d_name));
memcpy(abs_path, uspool->dir, strlen(uspool->dir));
memcpy(abs_path + strlen(uspool->dir), "/", 1);
memcpy(abs_path + strlen(uspool->dir) + 1, dp->d_name, strlen(dp->d_name));
if (lstat(abs_path, &sf_lstat)) {
@@ -1510,6 +1584,8 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
char *body = NULL;
size_t body_len= 0;
struct uwsgi_spooler *uspool = uwsgi.spoolers;
spool_dict = PyTuple_GetItem(args, 0);
if (spool_dict) {
@@ -1529,6 +1605,17 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
return PyErr_Format(PyExc_ValueError, "The argument of spooler callable must be a dictionary");
}
// TODO if "spooler" is a num, get the spooler by id, otherwise get it by directory
PyObject *py_spooler = uwsgi_py_dict_get(spool_dict, "spooler");
if (py_spooler) {
if (PyString_Check(py_spooler)) {
uspool = uwsgi_get_spooler_by_name(PyString_AsString(py_spooler));
if (!uspool) {
return PyErr_Format(PyExc_ValueError, "Unknown spooler requested");
}
}
}
PyObject *pyprio = uwsgi_py_dict_get(spool_dict, "priority");
if (pyprio) {
if (PyInt_Check(pyprio)) {
@@ -1628,16 +1715,20 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
}
}
UWSGI_RELEASE_GIL
if (numprio) {
priority = uwsgi_num2str(numprio);
}
i = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, cur_buf - spool_buffer, priority, at, body, body_len);
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, cur_buf - spool_buffer, priority, at, body, body_len);
if (priority) {
free(priority);
}
free(spool_buffer);
UWSGI_GET_GIL
Py_DECREF(spool_vars);
if (i > 0) {
@@ -1651,7 +1742,9 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
}
PyObject *py_uwsgi_spooler_pid(PyObject * self, PyObject * args) {
return PyInt_FromLong(uwsgi.shared->spooler_pid ? uwsgi.shared->spooler_pid : 0);
struct uwsgi_spooler *uspool = uwsgi.spoolers;
if (!uwsgi.spoolers) return PyInt_FromLong(0);
return PyInt_FromLong(uspool->pid);
}
#endif
@@ -1847,24 +1940,6 @@ PyObject *py_uwsgi_set_option(PyObject * self, PyObject * args) {
return PyInt_FromLong(value);
}
PyObject *py_uwsgi_load_plugin(PyObject * self, PyObject * args) {
int modifier;
char *plugin_name = NULL;
char *pargs = NULL;
if (!PyArg_ParseTuple(args, "is|s:load_plugin", &modifier, &plugin_name, &pargs)) {
return NULL;
}
if (uwsgi_load_plugin(modifier, plugin_name, pargs, 1)) {
Py_INCREF(Py_None);
return Py_None;
}
Py_INCREF(Py_True);
return Py_True;
}
#ifdef UWSGI_MULTICAST
PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
@@ -1879,7 +1954,9 @@ PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
uwsgi_message = uwsgi_malloc(message_len+4);
memcpy(uwsgi_message+4, message, message_len);
UWSGI_RELEASE_GIL
ret = send_udp_message(UWSGI_MODIFIER_MULTICAST, 0, host, uwsgi_message, message_len);
UWSGI_GET_GIL
free(uwsgi_message);
if (ret <= 0) {
@@ -2249,9 +2326,12 @@ PyObject *py_uwsgi_route(PyObject * self, PyObject * args) {
return PyErr_Format(PyExc_IOError, "unable to connect to host %s", addr);
}
UWSGI_RELEASE_GIL
if (uwsgi_send_message(uwsgi_fd, wsgi_req->uh.modifier1, wsgi_req->uh.modifier2, wsgi_req->buffer, wsgi_req->uh.pktsize, wsgi_req->poll.fd, wsgi_req->post_cl, 0) < 0) {
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "unable to send uwsgi request to host %s", addr);
}
UWSGI_GET_GIL
// request sent, return the iterator response
uwsgi_Iter *ui = PyObject_New(uwsgi_Iter, &uwsgi_IterType);
@@ -2301,7 +2381,9 @@ PyObject *py_uwsgi_send_message(PyObject * self, PyObject * args) {
uwsgi_fd = PyInt_AsLong(destination);
}
else if (PyString_Check(destination)) {
UWSGI_RELEASE_GIL
uwsgi_fd = uwsgi_connect(PyString_AsString(destination), timeout, 0);
UWSGI_GET_GIL
close_fd = 1;
}
@@ -2438,7 +2520,7 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
if (uwsgi.workers[i + 1].cheaped) {
zero = PyString_FromString("cheap");
}
else if (uwsgi.workers[i + 1].suspended) {
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
zero = PyString_FromString("pause");
}
else {
@@ -2514,6 +2596,8 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
PyDict_SetItemString(apps_dict, "mountpoint", zero);
Py_DECREF(zero);
PyDict_SetItemString(apps_dict, "startup_time", PyInt_FromLong((long) ua->startup_time));
PyDict_SetItemString(apps_dict, "interpreter", PyInt_FromLong((long)ua->interpreter));
PyDict_SetItemString(apps_dict, "callable", PyInt_FromLong((long)ua->interpreter));
@@ -2663,30 +2747,38 @@ PyObject *py_uwsgi_parse_file(PyObject * self, PyObject * args) {
return NULL;
}
UWSGI_RELEASE_GIL
fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(filename);
UWSGI_GET_GIL
goto clear;
}
len = read(fd, &uh, 4);
if (len != 4) {
uwsgi_error("read()");
UWSGI_GET_GIL
goto clear2;
}
buffer = malloc(uh.pktsize);
if (!buffer) {
uwsgi_error("malloc()");
UWSGI_GET_GIL
goto clear2;
}
len = read(fd, buffer, uh.pktsize);
if (len != uh.pktsize) {
uwsgi_error("read()");
free(buffer);
UWSGI_GET_GIL
goto clear2;
}
UWSGI_GET_GIL
ptrbuf = buffer;
bufferend = ptrbuf + uh.pktsize;
@@ -2775,12 +2867,15 @@ PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
uwsgi_error("fork()");
goto clear;
}
// now i am a grunt, avoid it making mess
else if (grunt_pid == 0) {
// it will no more accepts requests
uwsgi_close_all_sockets();
// create a new session
setsid();
// exit on SIGPIPE
signal(SIGPIPE, (void *) &end_me);
// here we create a new worker. Each grunt will race on this datas, so do not rely on them
uwsgi.mywid = uwsgi.numproc + 1;
uwsgi.mypid = getpid();
memset(&uwsgi.workers[uwsgi.mywid], 0, sizeof(struct uwsgi_worker));
@@ -2797,7 +2892,7 @@ PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
return Py_True;
}
// close connection on the worker
// close connection on the original worker
if (PyTuple_Size(args) == 0) {
if (wsgi_req->socket) {
wsgi_req->socket->proto_close(wsgi_req);
@@ -2939,8 +3034,8 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"log_this_request", py_uwsgi_log_this, METH_VARARGS, ""},
{"disconnect", py_uwsgi_disconnect, METH_VARARGS, ""},
{"grunt", py_uwsgi_grunt, METH_VARARGS, ""},
{"load_plugin", py_uwsgi_load_plugin, METH_VARARGS, ""},
{"lock", py_uwsgi_lock, METH_VARARGS, ""},
{"is_locked", py_uwsgi_is_locked, METH_VARARGS, ""},
{"unlock", py_uwsgi_unlock, METH_VARARGS, ""},
{"cl", py_uwsgi_cl, METH_VARARGS, ""},
@@ -3036,16 +3131,21 @@ PyObject *py_uwsgi_cache_del(PyObject * self, PyObject * args) {
}
if (remote && strlen(remote) > 0) {
UWSGI_RELEASE_GIL
uwsgi_simple_send_string(remote, 111, 2, key, keylen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
UWSGI_GET_GIL
}
else if (uwsgi.cache_max_items) {
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_del(key, keylen)) {
if (uwsgi_cache_del(key, keylen, 0)) {
uwsgi_rwunlock(uwsgi.cache_lock);
UWSGI_GET_GIL
Py_INCREF(Py_None);
return Py_None;
}
uwsgi_rwunlock(uwsgi.cache_lock);
UWSGI_GET_GIL
}
Py_INCREF(Py_True);
@@ -3073,16 +3173,21 @@ PyObject *py_uwsgi_cache_set(PyObject * self, PyObject * args) {
}
if (remote && strlen(remote) > 0) {
UWSGI_RELEASE_GIL
uwsgi_simple_send_string2(remote, 111, 1, key, keylen, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
UWSGI_GET_GIL
}
else if (uwsgi.cache_max_items) {
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_set(key, keylen, value, vallen, expires, 0)) {
uwsgi_rwunlock(uwsgi.cache_lock);
UWSGI_GET_GIL
Py_INCREF(Py_None);
return Py_None;
}
uwsgi_rwunlock(uwsgi.cache_lock);
UWSGI_GET_GIL
}
Py_INCREF(Py_True);
@@ -3109,16 +3214,21 @@ PyObject *py_uwsgi_cache_update(PyObject * self, PyObject * args) {
}
if (remote && strlen(remote) > 0) {
UWSGI_RELEASE_GIL
uwsgi_simple_send_string2(remote, 111, 1, key, keylen, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
UWSGI_GET_GIL
}
else if (uwsgi.cache_max_items) {
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
uwsgi_rwunlock(uwsgi.cache_lock);
UWSGI_GET_GIL
Py_INCREF(Py_None);
return Py_None;
}
uwsgi_rwunlock(uwsgi.cache_lock);
UWSGI_GET_GIL
}
Py_INCREF(Py_True);
@@ -3143,15 +3253,25 @@ PyObject *py_uwsgi_cache_exists(PyObject * self, PyObject * args) {
if (remote && strlen(remote) > 0) {
// TODO FIX THIS !!!
UWSGI_RELEASE_GIL
uwsgi_simple_message_string(remote, 111, 0, key, keylen, buffer, &valsize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
UWSGI_GET_GIL
if (valsize > 0) {
Py_INCREF(Py_True);
return Py_True;
}
}
else if (uwsgi_cache_exists(key, keylen)) {
Py_INCREF(Py_True);
return Py_True;
else if (uwsgi.cache_max_items) {
UWSGI_RELEASE_GIL
uwsgi_rlock(uwsgi.cache_lock);
if (uwsgi_cache_exists(key, keylen)) {
uwsgi_rwunlock(uwsgi.cache_lock);
UWSGI_GET_GIL
Py_INCREF(Py_True);
return Py_True;
}
uwsgi_rwunlock(uwsgi.cache_lock);
UWSGI_GET_GIL
}
Py_INCREF(Py_None);
@@ -3170,16 +3290,20 @@ PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {
}
if (uwsgi.queue_size) {
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.queue_lock);
if (uwsgi_queue_push(message, msglen)) {
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
Py_INCREF(Py_True);
res = Py_True;
}
else {
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
Py_INCREF(Py_None);
res = Py_None;
}
uwsgi_rwunlock(uwsgi.queue_lock);
return res;
}
@@ -3200,16 +3324,20 @@ PyObject *py_uwsgi_queue_set(PyObject * self, PyObject * args) {
}
if (uwsgi.queue_size) {
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.queue_lock);
if (uwsgi_queue_set(pos, message, msglen)) {
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
Py_INCREF(Py_True);
res = Py_True;
}
else {
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
Py_INCREF(Py_None);
res = Py_None;
}
uwsgi_rwunlock(uwsgi.queue_lock);
return res;
}
@@ -3235,18 +3363,29 @@ PyObject *py_uwsgi_queue_pull(PyObject * self, PyObject * args) {
char *message;
uint64_t size;
PyObject *res;
char *storage;
if (uwsgi.queue_size) {
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.queue_lock);
message = uwsgi_queue_pull(&size);
if (message && size > 0) {
res = PyString_FromStringAndSize(message, size);
}
else {
if (!message || size == 0) {
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
Py_INCREF(Py_None);
res = Py_None;
return Py_None;
}
storage = uwsgi_malloc(size);
memcpy(storage, message, size);
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
res = PyString_FromStringAndSize(storage, size);
free(storage);
return res;
}
@@ -3260,18 +3399,29 @@ PyObject *py_uwsgi_queue_pop(PyObject * self, PyObject * args) {
char *message;
uint64_t size;
PyObject *res;
char *storage;
if (uwsgi.queue_size) {
UWSGI_RELEASE_GIL
uwsgi_wlock(uwsgi.queue_lock);
message = uwsgi_queue_pop(&size);
if (message && size > 0) {
res = PyString_FromStringAndSize(message, size);
}
else {
if (!message || size == 0) {
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
Py_INCREF(Py_None);
res = Py_None;
}
return Py_None;
}
storage = uwsgi_malloc(size);
memcpy(storage, message, size);
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
res = PyString_FromStringAndSize(storage, size);
free(storage);
return res;
}
@@ -3287,22 +3437,32 @@ PyObject *py_uwsgi_queue_get(PyObject * self, PyObject * args) {
uint64_t size = 0;
char *message;
PyObject *res;
char *storage;
if (!PyArg_ParseTuple(args, "l:queue_get", &index)) {
return NULL;
}
if (uwsgi.queue_size) {
UWSGI_RELEASE_GIL
uwsgi_rlock(uwsgi.queue_lock);
message = uwsgi_queue_get(index, &size);
if (message && size > 0) {
res = PyString_FromStringAndSize(message, size);
}
else {
Py_INCREF(Py_None);
res = Py_None;
if (!message || size == 0) {
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
Py_INCREF(Py_None);
return Py_None;
}
storage = uwsgi_malloc(size);
memcpy(storage, message, size);
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
res = PyString_FromStringAndSize(storage, size);
free(storage);
return res;
}
@@ -3312,11 +3472,12 @@ PyObject *py_uwsgi_queue_get(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
long num = 0;
long i, num = 0;
uint64_t size = 0;
char *message;
PyObject *res = NULL, *zero;
PyObject *res = NULL;
uint64_t base;
char *storage;
if (!PyArg_ParseTuple(args, "|l:queue_last", &num)) {
return NULL;
@@ -3328,6 +3489,7 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
res = PyList_New(0);
}
UWSGI_RELEASE_GIL
uwsgi_rlock(uwsgi.queue_lock);
if (uwsgi.queue_header->pos > 0) {
@@ -3339,31 +3501,41 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
if (num == 0) {
message = uwsgi_queue_get(base, &size);
if (message && size) {
res = PyString_FromStringAndSize(message, size);
}
else {
Py_INCREF(Py_None);
res = Py_None;
}
if (!message || size == 0) {
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
Py_INCREF(Py_None);
return Py_None;
}
storage = uwsgi_malloc(size);
memcpy(storage, message, size);
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
res = PyString_FromStringAndSize(storage, size);
free(storage);
return res;
}
if (num > (long)uwsgi.queue_size) num = uwsgi.queue_size;
char **queue_items = uwsgi_malloc(sizeof(char *) * num);
uint64_t *queue_items_size = uwsgi_malloc(sizeof(uint64_t) * num);
long item_pos = 0;
while(num) {
message = uwsgi_queue_get(base, &size);
if (message && size) {
zero = PyString_FromStringAndSize(message, size);
PyList_Append(res, zero);
Py_DECREF(zero);
}
else {
uwsgi_rwunlock(uwsgi.queue_lock);
return res;
if (!message || size == 0) {
queue_items[item_pos] = NULL;
queue_items_size[item_pos] = 0;
}
else {
queue_items[item_pos] = uwsgi_malloc(size);
memcpy(queue_items[item_pos], message, size);
queue_items_size[item_pos] = size;
}
item_pos++;
if (base > 0) {
base--;
}
@@ -3372,7 +3544,24 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
}
num--;
}
uwsgi_rwunlock(uwsgi.queue_lock);
UWSGI_GET_GIL
for(i=0;i<item_pos;i++) {
if (queue_items[i]) {
PyObject *zero = PyString_FromStringAndSize(queue_items[i], queue_items_size[i]);
PyList_Append(res, zero);
Py_DECREF(zero);
free(queue_items[i]);
}
else {
Py_INCREF(Py_None);
PyList_Append(res, Py_None);
}
}
free(queue_items);
free(queue_items_size);
return res;
}
@@ -3390,7 +3579,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
char *value = NULL;
char *remote = NULL;
char buffer[0xffff];
PyObject *res;
PyObject *ret;
#ifdef UWSGI_DEBUG
struct timeval tv, tv2;
@@ -3401,7 +3590,9 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
}
if (remote && strlen(remote) > 0) {
UWSGI_RELEASE_GIL
uwsgi_simple_message_string(remote, 111, 0, key, keylen, buffer, &valsize16, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
UWSGI_GET_GIL
if (valsize16 > 0) {
value = buffer;
valsize = valsize16;
@@ -3411,22 +3602,28 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
#ifdef UWSGI_DEBUG
gettimeofday(&tv, NULL);
#endif
UWSGI_RELEASE_GIL
uwsgi_rlock(uwsgi.cache_lock);
value = uwsgi_cache_get(key, keylen, &valsize);
if (!value) {
uwsgi_rwunlock(uwsgi.cache_lock);
UWSGI_GET_GIL
Py_INCREF(Py_None);
return Py_None;
}
res = PyString_FromStringAndSize(value, valsize);
char *storage = uwsgi_malloc(valsize);
#ifdef UWSGI_DEBUG
gettimeofday(&tv2, NULL);
if ((tv2.tv_sec* (1000*1000) + tv2.tv_usec) - (tv.tv_sec* (1000*1000) + tv.tv_usec) > 30000) {
uwsgi_log("[slow] cache get done in %d microseconds (%llu bytes value)\n", (tv2.tv_sec* (1000*1000) + tv2.tv_usec) - (tv.tv_sec* (1000*1000) + tv.tv_usec), (unsigned long long) valsize);
}
#endif
memcpy(storage, value, valsize);
uwsgi_rwunlock(uwsgi.cache_lock);
return res;
UWSGI_GET_GIL
ret = PyString_FromStringAndSize(storage, valsize);
free(storage);
return ret;
}
if (value) {
+25 -28
View File
@@ -3,26 +3,6 @@
#include <frameobject.h>
#define MAX_PYMODULE_ALIAS 64
#define MAX_PYARGV 10
#define LONG_ARGS_PYTHON_BASE 17000 + ((0 + 1) * 1000)
#define LONG_ARGS_PYTHONPATH LONG_ARGS_PYTHON_BASE + 1
#define LONG_ARGS_PASTE LONG_ARGS_PYTHON_BASE + 2
#define LONG_ARGS_PYARGV LONG_ARGS_PYTHON_BASE + 3
#define LONG_ARGS_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 4
#define LONG_ARGS_RELOAD_OS_ENV LONG_ARGS_PYTHON_BASE + 5
#define LONG_ARGS_PYIMPORT LONG_ARGS_PYTHON_BASE + 6
#define LONG_ARGS_POST_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 7
#define LONG_ARGS_WEB3 LONG_ARGS_PYTHON_BASE + 8
#define LONG_ARGS_PUMP LONG_ARGS_PYTHON_BASE + 9
#define LONG_ARGS_WSGI_LITE LONG_ARGS_PYTHON_BASE + 10
#define LONG_ARGS_PYSHELL LONG_ARGS_PYTHON_BASE + 11
#define LONG_ARGS_SPOOLER_PYIMPORT LONG_ARGS_PYTHON_BASE + 12
#define LONG_ARGS_PYTHON_RUN LONG_ARGS_PYTHON_BASE + 13
#define LONG_ARGS_SHARED_PYIMPORT LONG_ARGS_PYTHON_BASE + 14
#define PYTHON_APP_TYPE_WSGI 0
#define PYTHON_APP_TYPE_WEB3 1
#define PYTHON_APP_TYPE_WSGI2 2
@@ -58,6 +38,14 @@
#define PyVarObject_HEAD_INIT(x, y) PyObject_HEAD_INIT(x) y,
#endif
#define uwsgi_py_write_set_exception(x) PyErr_SetString(PyExc_IOError, "write error");
#define uwsgi_py_write_exception(x) uwsgi_py_write_set_exception(x); PyErr_Print();
#define uwsgi_py_check_write_errors if (wsgi_req->write_errors > 0 && uwsgi.write_errors_exception_only) {\
uwsgi_py_write_set_exception(wsgi_req);\
}\
else if (wsgi_req->write_errors > uwsgi.write_errors_tolerance)\
PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int);
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
@@ -118,9 +106,9 @@ struct uwsgi_python {
int argc;
#ifdef PYTHREE
wchar_t *py_argv[MAX_PYARGV];
wchar_t **py_argv;
#else
char *py_argv[MAX_PYARGV];
char **py_argv;
#endif
PyObject *wsgi_spitout;
@@ -131,12 +119,15 @@ struct uwsgi_python {
char *test_module;
int pyshell;
int pyshell_oneshot;
struct uwsgi_string_list *python_path;
struct uwsgi_string_list *import_list;
struct uwsgi_string_list *shared_import_list;
struct uwsgi_string_list *spooler_import_list;
struct uwsgi_string_list *post_pymodule_alias;
struct uwsgi_string_list *pymodule_alias;
PyObject *loader_dict;
PyObject* (*loaders[LOADER_MAX]) (void *);
@@ -144,6 +135,7 @@ struct uwsgi_python {
char *wsgi_config;
char *file_config;
char *paste;
int paste_logger;
char *eval;
char *web3;
@@ -152,9 +144,6 @@ struct uwsgi_python {
char *callable;
int ignore_script_name;
int catch_exceptions;
int *current_recursion_depth;
struct _frame **current_frame;
@@ -170,15 +159,14 @@ struct uwsgi_python {
pthread_mutex_t lock_pyloaders;
void (*gil_get) (void);
void (*gil_release) (void);
int auto_reload;
struct uwsgi_string_list *auto_reload_ignore;
#endif
PyObject *workers_tuple;
PyObject *embedded_dict;
PyObject *embedded_args;
PyObject *fastfuncslist;
char *pymodule_alias[MAX_PYMODULE_ALIAS];
int pymodule_alias_cnt;
int pep3333_input;
@@ -186,6 +174,11 @@ struct uwsgi_python {
int reload_os_env;
PyObject *after_req_hook;
PyObject *after_req_hook_args;
char *pyrun;
};
@@ -265,10 +258,14 @@ void simple_reset_ts(struct wsgi_request *, struct uwsgi_app *);
void simple_threaded_reset_ts(struct wsgi_request *, struct uwsgi_app *);
int uwsgi_python_profiler_call(PyObject *, PyFrameObject *, int, PyObject *);
int uwsgi_python_tracer(PyObject *, PyFrameObject *, int, PyObject *);
void uwsgi_python_reset_random_seed(void);
char *uwsgi_pythonize(char *);
void *uwsgi_python_autoreloader_thread(void *);
int uwsgi_python_manage_exceptions(void);
#ifdef UWSGI_PYPY
#undef UWSGI_MINTERPRETERS
+14 -19
View File
@@ -134,9 +134,6 @@ void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_
int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
PyObject *pychunk;
ssize_t wsize;
UWSGI_GET_GIL
// ok its a yield
if (!wsgi_req->async_placeholder) {
@@ -170,11 +167,14 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
Py_DECREF(spit_args);
if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) {
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(wsgi_req->async_placeholder), PyString_Size(wsgi_req->async_placeholder))) < 0) {
uwsgi_error("write()");
goto clear;
char *content = PyString_AsString(wsgi_req->async_placeholder);
size_t content_len = PyString_Size(wsgi_req->async_placeholder);
UWSGI_RELEASE_GIL
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
UWSGI_GET_GIL
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
}
wsgi_req->response_size += wsize;
goto clear;
}
@@ -189,7 +189,6 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
}
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
#endif
@@ -211,32 +210,28 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
if (PyString_Check(pychunk)) {
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
uwsgi_error("write()");
char *content = PyString_AsString(pychunk);
size_t content_len = PyString_Size(pychunk);
UWSGI_RELEASE_GIL
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
UWSGI_GET_GIL
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
Py_DECREF(pychunk);
goto clear;
}
wsgi_req->response_size += wsize;
}
Py_DECREF(pychunk);
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
clear:
if (wsgi_req->async_input) {
Py_DECREF((PyObject *)wsgi_req->async_input);
}
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
UWSGI_RELEASE_GIL
return UWSGI_OK;
}
+37 -5
View File
@@ -229,7 +229,7 @@ static PyMethodDef uwsgi_Input_methods[] = {
PyTypeObject uwsgi_InputType = {
PyVarObject_HEAD_INIT(NULL, 0)
"uwsgi._Input", /*tp_name */
"uwsgi._Input", /*tp_name */
sizeof(uwsgi_Input), /*tp_basicsize */
0, /*tp_itemsize */
(destructor) uwsgi_Input_free, /*tp_dealloc */
@@ -278,6 +278,12 @@ PyObject *py_uwsgi_write(PyObject * self, PyObject * args) {
UWSGI_RELEASE_GIL
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, content, len);
UWSGI_GET_GIL
// this is a special case for the write callable
// no need to honout write-errors-exception-only
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance) {
uwsgi_py_write_set_exception(wsgi_req);
return NULL;
}
}
Py_INCREF(Py_None);
@@ -363,7 +369,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
if (wsgi_req->appid_len == 0) {
if (!up.ignore_script_name) {
if (!uwsgi.ignore_script_name) {
wsgi_req->appid = wsgi_req->script_name;
wsgi_req->appid_len = wsgi_req->script_name_len;
}
@@ -445,8 +451,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
wsgi_req->async_result = wi->request_subhandler(wsgi_req, wi);
UWSGI_RELEASE_GIL
if (wsgi_req->async_result) {
@@ -466,7 +470,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
else if (up.catch_exceptions) {
else if (uwsgi.catch_exceptions) {
// LOCK THIS PART
@@ -501,6 +505,16 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
close(tmp_stderr);
}
// this object must be freed/cleared always
if (wsgi_req->async_input) {
Py_DECREF((PyObject *)wsgi_req->async_input);
}
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
UWSGI_RELEASE_GIL
clear:
up.reset_ts(wsgi_req, wi);
@@ -513,6 +527,24 @@ clear2:
void uwsgi_after_request_wsgi(struct wsgi_request *wsgi_req) {
if (up.after_req_hook) {
if (uwsgi.harakiri_no_arh) {
// leave harakiri mode
if (uwsgi.workers[uwsgi.mywid].harakiri > 0)
set_harakiri(0);
}
UWSGI_GET_GIL
PyObject *arh = python_call(up.after_req_hook, up.after_req_hook_args, 0, NULL);
if (!arh) {
PyErr_Print();
}
else {
Py_DECREF(arh);
}
PyErr_Clear();
UWSGI_RELEASE_GIL
}
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING] || wsgi_req->log_this) {
log_request(wsgi_req);
}
+5
View File
@@ -201,6 +201,11 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
UWSGI_GET_GIL
#endif
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance) {
uwsgi_py_write_set_exception(wsgi_req);
return NULL;
}
//uwsgi_log("%d %p\n", wsgi_req->poll.fd, up.wsgi_writeout);
Py_INCREF(up.wsgi_writeout);
+36 -40
View File
@@ -28,7 +28,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
#endif
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
Py_DECREF(pydictvalue);
}
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
@@ -48,7 +48,6 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
}
#ifndef UWSGI_PYPY
// if async_post is mapped as a file, directly use it as wsgi.input
if (wsgi_req->async_post) {
#ifdef PYTHREE
@@ -69,7 +68,6 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input);
#endif
#ifdef UWSGI_SENDFILE
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->sendfile);
@@ -85,11 +83,9 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", wi->gateway_version);
#ifndef UWSGI_PYPY
zero = PyFile_FromFile(stderr, "wsgi_errors", "w", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.errors", zero);
Py_DECREF(zero);
#endif
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.run_once", Py_False);
@@ -108,6 +104,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_True);
}
if (wsgi_req->scheme_len > 0) {
zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
}
@@ -125,16 +122,12 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
Py_DECREF(zero);
wsgi_req->async_app = wi->callable;
// export .env only in non-threaded mode
#ifndef UWSGI_PYPY
if (uwsgi.threads < 2) {
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
}
#endif
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
@@ -156,39 +149,29 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
#ifdef UWSGI_ROUTING
uwsgi_log("routing %d routes %d\n", uwsgi.routing, uwsgi.nroutes);
if (uwsgi.routing && uwsgi.nroutes > 0) {
check_route(uwsgi, wsgi_req);
}
#endif
// call
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions, wsgi_req);
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
}
int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
PyObject *pychunk;
ssize_t wsize;
#ifdef UWSGI_SENDFILE
ssize_t sf_len = 0;
#endif
UWSGI_GET_GIL
// return or yield ?
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
uwsgi_error("write()");
goto clear;
char *content = PyString_AsString(wsgi_req->async_result);
size_t content_len = PyString_Size(wsgi_req->async_result);
UWSGI_RELEASE_GIL
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
UWSGI_GET_GIL
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
}
wsgi_req->response_size += wsize;
goto clear;
}
@@ -205,7 +188,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
if (wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
}
@@ -223,7 +205,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
}
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
#endif
@@ -234,15 +215,34 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
pychunk = PyIter_Next(wsgi_req->async_placeholder);
if (!pychunk) {
if (PyErr_Occurred()) {
int do_exit = uwsgi_python_manage_exceptions();
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
uwsgi_log("Memory Error detected !!!\n");
}
uwsgi.workers[uwsgi.mywid].exceptions++;
uwsgi_apps[wsgi_req->app_id].exceptions++;
PyErr_Print();
if (do_exit) {
exit(UWSGI_EXCEPTION_CODE);
}
}
if (PyObject_HasAttrString((PyObject *)wsgi_req->async_result, "close")) {
PyObject *close_method = PyObject_GetAttrString((PyObject *)wsgi_req->async_result, "close");
PyObject *close_method_args = PyTuple_New(0);
#ifdef UWSGI_DEBUG
uwsgi_log("calling close() for %.*s %p %p\n", wsgi_req->uri_len, wsgi_req->uri, close_method, close_method_args);
#endif
PyObject *close_method_output = PyEval_CallObject(close_method, close_method_args);
if (PyErr_Occurred()) {
PyErr_Print();
}
Py_DECREF(close_method_args);
Py_XDECREF(close_method_output);
Py_DECREF(close_method);
}
goto clear;
}
@@ -250,12 +250,16 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
if (PyString_Check(pychunk)) {
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
uwsgi_error("write()");
char *content = PyString_AsString(pychunk);
size_t content_len = PyString_Size(pychunk);
UWSGI_RELEASE_GIL
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
UWSGI_GET_GIL
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
Py_DECREF(pychunk);
goto clear;
}
wsgi_req->response_size += wsize;
}
#ifdef UWSGI_SENDFILE
@@ -268,7 +272,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
Py_DECREF(pychunk);
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
clear:
@@ -276,18 +279,11 @@ clear:
if (wsgi_req->sendfile_fd != -1) {
Py_DECREF((PyObject *)wsgi_req->async_sendfile);
}
if (wsgi_req->async_input) {
Py_DECREF((PyObject *)wsgi_req->async_input);
}
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
clear2:
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
UWSGI_RELEASE_GIL
return UWSGI_OK;
}
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python24'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.4-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python24_plugin')
LDFLAGS = os.popen('python2.4-config --ldflags').read().rstrip().split()
LIBS = os.popen('python2.4-config --libs').read().rstrip().split()
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python25'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.5-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python25_plugin')
LDFLAGS = os.popen('python2.5-config --ldflags').read().rstrip().split()
LIBS = os.popen('python2.5-config --libs').read().rstrip().split()
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python26'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.6-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python26_plugin')
LDFLAGS = os.popen('python2.6-config --ldflags').read().rstrip().split()
LIBS = os.popen('python2.6-config --libs').read().rstrip().split()
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python27'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.7-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python27_plugin')
LDFLAGS = os.popen('python2.7-config --ldflags').read().rstrip().split()
LIBS = os.popen('python2.7-config --libs').read().rstrip().split()
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python30'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python3.0-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python30_plugin')
LDFLAGS = os.popen('python3.0-config --ldflags').read().rstrip().split()
LIBS = os.popen('python3.0-config --libs').read().rstrip().split()
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python31'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python3.1-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python31_plugin')
LDFLAGS = os.popen('python3.1-config --ldflags').read().rstrip().split()
LIBS = os.popen('python3.1-config --libs').read().rstrip().split()
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python32'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python3.2-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python32_plugin')
LDFLAGS = os.popen('python3.2-config --ldflags').read().rstrip().split()
LIBS = os.popen('python3.2-config --libs').read().rstrip().split()
+3 -3
View File
@@ -36,7 +36,7 @@ VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
#ifdef UWSGI_SPOOLER
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
if (uwsgi.i_am_a_spooler) {
return Qtrue;
}
#endif
@@ -347,7 +347,7 @@ VALUE rack_uwsgi_cache_del(VALUE *class, VALUE rbkey) {
size_t keylen = RSTRING_LEN(rbkey);
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_del(key, keylen)) {
if (uwsgi_cache_del(key, keylen, 0)) {
uwsgi_rwunlock(uwsgi.cache_lock);
return Qfalse;
}
@@ -838,7 +838,7 @@ VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
priority = uwsgi_num2str(numprio);
}
int ret = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, argv[0] - spool_buffer, priority, at, body, body_len);
int ret = spool_request(uwsgi.spoolers, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, argv[0] - spool_buffer, priority, at, body, body_len);
if (priority) {
free(priority);
+177 -96
View File
@@ -4,20 +4,27 @@ extern struct uwsgi_server uwsgi;
struct uwsgi_rack ur;
struct option uwsgi_rack_options[] = {
struct uwsgi_option uwsgi_rack_options[] = {
{"rails", required_argument, 0, LONG_ARGS_RAILS},
{"rack", required_argument, 0, LONG_ARGS_RACK},
{"ruby-gc-freq", required_argument, 0, LONG_ARGS_RUBY_GC_FREQ},
{"rb-gc-freq", required_argument, 0, LONG_ARGS_RUBY_GC_FREQ},
{"rb-require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
{"ruby-require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
{"rbrequire", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
{"rubyrequire", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
{"require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
{"rbshell", optional_argument, 0, LONG_ARGS_RUBY_SHELL},
{"rails", required_argument, 0, "load a rails <= 2.x app", uwsgi_opt_set_str, &ur.rails, UWSGI_OPT_POST_BUFFERING},
{"rack", required_argument, 0, "load a rack app", uwsgi_opt_set_str, &ur.rack, UWSGI_OPT_POST_BUFFERING},
{"ruby-gc-freq", required_argument, 0, "set ruby GC frequency", uwsgi_opt_set_int, &ur.gc_freq, 0},
{"rb-gc-freq", required_argument, 0, "set ruby GC frequency", uwsgi_opt_set_int, &ur.gc_freq, 0},
{0, 0, 0, 0},
{"rb-require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
{"ruby-require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
{"rbrequire", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
{"rubyrequire", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
{"require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
{"gemset", required_argument, 0, "load the specified gemset (rvm)", uwsgi_opt_set_str, &ur.gemset, 0},
{"rvm", required_argument, 0, "load the specified gemset (rvm)", uwsgi_opt_set_str, &ur.gemset, 0},
{"rvm-path", required_argument, 0, "search for rvm in the specifiied directory", uwsgi_opt_add_string_list, &ur.rvm_path, 0},
{"rbshell", optional_argument, 0, "run a ruby/irb shell", uwsgi_opt_true, &ur.rb_shell, 0},
{0, 0, 0, 0, 0, 0 ,0},
};
@@ -61,12 +68,26 @@ VALUE rb_uwsgi_io_init(int argc, VALUE *argv, VALUE self) {
VALUE rb_uwsgi_io_gets(VALUE obj, VALUE args) {
size_t i;
struct wsgi_request *wsgi_req;
VALUE line;
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
// return the whole body as string
// return a line of body
for(i=wsgi_req->buf_pos;i<wsgi_req->post_cl;i++) {
if (wsgi_req->post_buffering_buf[i] == '\n') {
line = rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, (i+1)-wsgi_req->buf_pos);
wsgi_req->buf_pos = i+1;
return line;
}
}
rb_raise(rb_eRuntimeError, "rack.input::gets is not implemented (req %p)\n", wsgi_req);
if (wsgi_req->buf_pos < wsgi_req->post_cl) {
line = rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, wsgi_req->post_cl-wsgi_req->buf_pos);
wsgi_req->buf_pos = wsgi_req->post_cl;
return line;
}
return Qnil;
}
@@ -89,7 +110,18 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
int chunk_size;
if (!wsgi_req->post_cl || wsgi_req->buf_pos >= wsgi_req->post_cl) {
return Qnil;
/*
When EOF is reached, this method returns nil if length is given and not nil, or "" if length is not given or is nil.
If buffer is given, then the read data will be placed into buffer instead of a newly created String object.
*/
if (RARRAY_LEN(args) > 0) {
if (RARRAY_PTR(args)[0] == Qnil) {
return rb_str_new("", 0);
}
return Qnil;
}
return rb_str_new("", 0);
}
if (RARRAY_LEN(args) == 0) {
@@ -199,6 +231,99 @@ uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[],
}
void uwsgi_ruby_gem_set_apply(char *gemset) {
int in_pipe[2];
int out_pipe[2];
int size;
int waitpid_status;
int i;
if (pipe(in_pipe)) {
uwsgi_error("pipe()");
exit(1);
}
if (pipe(out_pipe)) {
uwsgi_error("pipe()");
exit(1);
}
pid_t pid = uwsgi_run_command("bash", in_pipe, out_pipe[1] );
char *gemset_code = uwsgi_open_and_read(gemset, &size, 0, NULL);
if (write(in_pipe[1], gemset_code, size) != size ) {
uwsgi_error("write()");
}
free(gemset_code);
if (write(in_pipe[1], "printenv\n", 9) != 9 ) {
uwsgi_error("write()");
}
close(in_pipe[1]);
size = 0;
char *buffer = uwsgi_read_fd(out_pipe[0], &size, 0);
close(out_pipe[0]);
char *ptr = buffer;
for(i=0;i<size;i++) {
if (buffer[i] == '\n') {
buffer[i] = 0;
if (putenv(ptr)) {
uwsgi_error("putenv()");
}
ptr = buffer + i + 1;
}
}
free(buffer);
if (waitpid(pid, &waitpid_status, 0) <0) {
uwsgi_error("waitpid()");
}
}
void uwsgi_ruby_gemset(char *gemset) {
char *home = getenv("HOME");
if (home) {
char *filename = uwsgi_concat3(home, "/.rvm/environments/", gemset);
if (uwsgi_file_exists(filename)) {
uwsgi_ruby_gem_set_apply(filename);
free(filename);
return;
}
free(filename);
}
char *filename = uwsgi_concat2("/usr/local/rvm/environments/", gemset);
if (uwsgi_file_exists(filename)) {
uwsgi_ruby_gem_set_apply(filename);
free(filename);
return;
}
free(filename);
struct uwsgi_string_list *rvm_paths = ur.rvm_path;
while(rvm_paths) {
char *filename = uwsgi_concat3(rvm_paths->value, "/environments/", gemset);
if (uwsgi_file_exists(filename)) {
uwsgi_ruby_gem_set_apply(filename);
free(filename);
return;
}
free(filename);
rvm_paths = rvm_paths->next;
}
}
int uwsgi_rack_init(){
@@ -215,6 +340,10 @@ int uwsgi_rack_init(){
http_sc->message_size = (int) strlen(http_sc->message);
}
if (ur.gemset) {
uwsgi_ruby_gemset(ur.gemset);
}
#ifdef RUBY19
ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK
@@ -233,6 +362,7 @@ int uwsgi_rack_init(){
rb_gc_register_address(&ur.signals_protector);
rb_gc_register_address(&ur.rpc_protector);
#ifdef UWSGI_EMBEDDED
uwsgi_rack_init_api();
#endif
@@ -250,6 +380,8 @@ void uwsgi_rack_init_apps(void) {
ur.app_id = uwsgi_apps_cnt;
struct uwsgi_string_list *usl = ur.rbrequire;
time_t now = uwsgi_now();
while(usl) {
error = 0;
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
@@ -364,12 +496,17 @@ ready:
rb_define_method(ur.rb_uwsgi_io_class, "read", rb_uwsgi_io_read, -2);
rb_define_method(ur.rb_uwsgi_io_class, "rewind", rb_uwsgi_io_rewind, 0);
uwsgi_add_app(ur.app_id, 7, (char*)"", 0);
struct uwsgi_app *ua = uwsgi_add_app(ur.app_id, 7, (char*)"", 0, NULL, NULL);
ua->started_at = now;
ua->startup_time = uwsgi_now() - now;
uwsgi_emulate_cow_for_apps(ur.app_id);
if (ur.gc_freq <= 1) {
uwsgi_log("RACK app %d loaded at %p (GC frequency: AGGRESSIVE)\n", ur.app_id, ur.call);
uwsgi_log("RACK app %d loaded in %d seconds at %p (GC frequency: AGGRESSIVE)\n", ur.app_id, (int) ua->startup_time, ur.call);
}
else {
uwsgi_log("RACK app %d loaded at %p (GC frequency: %d)\n", ur.app_id, ur.call, ur.gc_freq);
uwsgi_log("RACK app %d loaded in %d seconds at %p (GC frequency: %d)\n", ur.app_id, (int) ua->startup_time, ur.call, ur.gc_freq);
}
}
@@ -383,18 +520,15 @@ VALUE call_dispatch(VALUE env) {
static VALUE send_body(VALUE obj) {
struct wsgi_request *wsgi_req = current_wsgi_req();
ssize_t len = 0;
//uwsgi_log("sending body\n");
if (TYPE(obj) == T_STRING) {
len = wsgi_req->socket->proto_write( wsgi_req, RSTRING_PTR(obj), RSTRING_LEN(obj));
wsgi_req->response_size += wsgi_req->socket->proto_write( wsgi_req, RSTRING_PTR(obj), RSTRING_LEN(obj));
}
else {
uwsgi_log("UNMANAGED BODY TYPE %d\n", TYPE(obj));
}
wsgi_req->response_size += len;
return Qnil;
}
@@ -420,9 +554,7 @@ VALUE send_header(VALUE obj, VALUE headers) {
struct wsgi_request *wsgi_req = current_wsgi_req();
size_t len;
VALUE hkey, hval;
//uwsgi_log("HEADERS %d\n", TYPE(obj));
if (TYPE(obj) == T_ARRAY) {
@@ -455,18 +587,16 @@ VALUE send_header(VALUE obj, VALUE headers) {
size_t header_value_len = RSTRING_LEN(hval);
size_t i,cnt=0;
char *this_header = header_value;
struct iovec iov[4];
for(i=0;i<header_value_len;i++) {
// multiline header, send it !!!
if (header_value[i] == '\n') {
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, this_header, cnt);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
iov[0].iov_base = RSTRING_PTR(hkey); iov[0].iov_len = RSTRING_LEN(hkey);
iov[1].iov_base = (char *)": "; iov[1].iov_len = 2;
iov[2].iov_base = this_header; iov[2].iov_len = cnt;
iov[3].iov_base = (char *)"\r\n"; iov[3].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header( wsgi_req, iov, 4);
//uwsgi_log("(multi) --%.*s: %.*s--\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), cnt, this_header);
@@ -480,14 +610,11 @@ VALUE send_header(VALUE obj, VALUE headers) {
}
if (cnt > 0) {
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, this_header, cnt);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
iov[0].iov_base = RSTRING_PTR(hkey); iov[0].iov_len = RSTRING_LEN(hkey);
iov[1].iov_base = (char *)": "; iov[1].iov_len = 2;
iov[2].iov_base = this_header; iov[2].iov_len = cnt;
iov[3].iov_base = (char *)"\r\n"; iov[3].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header( wsgi_req, iov, 4);
wsgi_req->header_cnt++;
//uwsgi_log("--%.*s: %.*s--\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), cnt, this_header);
}
@@ -582,7 +709,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
VALUE dws_wr = Data_Wrap_Struct(ur.rb_uwsgi_io_class, 0, 0, wsgi_req);
if (wsgi_req->async_post) {
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(fileno(wsgi_req->async_post)), rb_str_new("r",1) ));
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(fileno((FILE*)wsgi_req->async_post)), rb_str_new("r",1) ));
}
else {
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall(ur.rb_uwsgi_io_class, rb_intern("new"), 1, dws_wr ));
@@ -635,9 +762,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
wsgi_req->hvec[5].iov_base = (char *) "\r\n";
wsgi_req->hvec[5].iov_len = 2 ;
if ( !(wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6)) ) {
uwsgi_error("writev()");
}
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6);
headers = RARRAY_PTR(ret)[1] ;
if (rb_respond_to( headers, rb_intern("each") )) {
@@ -648,9 +773,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
}
}
if (wsgi_req->socket->proto_write(wsgi_req, (char *)"\r\n", 2) != 2) {
uwsgi_error("write()");
}
wsgi_req->socket->proto_write(wsgi_req, (char *)"\r\n", 2);
body = RARRAY_PTR(ret)[2] ;
@@ -719,31 +842,6 @@ void uwsgi_rack_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
int uwsgi_rack_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_RAILS:
// HACK: can be overridden with --post-buffering
if (!uwsgi.post_buffering) uwsgi.post_buffering = 4096;
ur.rails = optarg;
return 1;
case LONG_ARGS_RACK:
// HACK: can be overridden with --post-buffering
if (!uwsgi.post_buffering) uwsgi.post_buffering = 4096;
ur.rack = optarg;
return 1;
case LONG_ARGS_RUBY_GC_FREQ:
ur.gc_freq = atoi(optarg);
return 1;
case LONG_ARGS_RUBY_REQUIRE:
uwsgi_string_new_list(&ur.rbrequire, optarg);
return 1;
}
return 0;
}
void uwsgi_rack_suspend(struct wsgi_request *wsgi_req) {
uwsgi_log("SUSPENDING RUBY\n");
@@ -828,22 +926,6 @@ VALUE init_rack_app( VALUE script ) {
return RARRAY_PTR(rackup)[0] ;
}
int uwsgi_rack_xml(char *node, char *content) {
int error;
if (!strcmp("rack", node)) {
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(content), &error);
if (ur.dispatcher != Qnil) {
rb_gc_register_address(&ur.dispatcher);
uwsgi_log("Rack application ready\n");
return 1;
}
}
return 0;
}
int uwsgi_rack_magic(char *mountpoint, char *lazy) {
if (!strcmp(lazy+strlen(lazy)-3, ".ru")) {
@@ -859,17 +941,17 @@ int uwsgi_rack_magic(char *mountpoint, char *lazy) {
return 0;
}
/*
int uwsgi_rack_mount_app(char *mountpoint, char *app) {
int uwsgi_rack_mount_app(char *mountpoint, char *app, int regexp) {
if ( !strcmp(what+strlen(what)-3, ".ru") || !strcmp(what+strlen(what)-3, ".rb")) {
return = uwsgi_rack_load(mountpoint, what);
if (uwsgi_endswith(app, ".ru") || uwsgi_endswith(app, ".rb")) {
ur.rack = app;
uwsgi_rack_init_apps();
return 0;
}
return -1;
}
*/
void uwsgi_rack_hijack(void) {
}
@@ -1022,7 +1104,7 @@ struct uwsgi_plugin rack_plugin = {
.modifier1 = 7,
.init = uwsgi_rack_init,
.options = uwsgi_rack_options,
.manage_opt = uwsgi_rack_manage_options,
.request = uwsgi_rack_request,
.after_request = uwsgi_rack_after_request,
@@ -1034,8 +1116,7 @@ struct uwsgi_plugin rack_plugin = {
.spooler = uwsgi_rack_spooler,
.init_apps = uwsgi_rack_init_apps,
//.mount_app = uwsgi_rack_mount_app,
.manage_xml = uwsgi_rack_xml,
.mount_app = uwsgi_rack_mount_app,
.magic = uwsgi_rack_magic,
+3 -7
View File
@@ -2,13 +2,6 @@
#include <ruby.h>
#define LONG_ARGS_RACK_BASE 17000 + ((7 + 1) * 100)
#define LONG_ARGS_RAILS LONG_ARGS_RACK_BASE + 1
#define LONG_ARGS_RUBY_GC_FREQ LONG_ARGS_RACK_BASE + 2
#define LONG_ARGS_RACK LONG_ARGS_RACK_BASE + 3
#define LONG_ARGS_RUBY_SHELL LONG_ARGS_RACK_BASE + 4
#define LONG_ARGS_RUBY_REQUIRE LONG_ARGS_RACK_BASE + 5
#ifndef RUBY19
#include <st.h>
#define rb_errinfo() ruby_errinfo
@@ -72,6 +65,9 @@ struct uwsgi_rack {
int unprotected;
struct uwsgi_string_list *rbrequire;
struct uwsgi_string_list *rvm_path;
char *gemset;
};

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