Compare commits

...
317 Commits
Author SHA1 Message Date
roberto@debian32 2d731532be various erlang fixes 2011-11-03 09:09:17 +01:00
roberto@debian32 d545cd5be0 added @erlang decorator 2011-11-02 20:48:11 +01:00
roberto@debian32 261d05d67e added @mulemsg decorator 2011-11-02 19:55:11 +01:00
roberto@debian32 639995785a fixed pyerl 2011-11-02 14:41:32 +01:00
roberto@debian32 817e076cae uwsgidecorators is installed when run under pip/easy_install 2011-11-02 14:20:51 +01:00
roberto@debian32 713370f343 completed regexp support in subscription system 2011-11-01 08:33:52 +01:00
roberto@debian32 5594503a56 pcre support in subscription system 2011-10-31 09:11:02 +01:00
roberto@debian32 d57e5d46fb fixed subscriptions removal in http plugin 2011-10-31 07:56:01 +01:00
roberto@debian32 ee2db5fabd a bunch of subscription optimizations 2011-10-30 13:10:26 +01:00
roberto@debian32 0c4cd6f378 ported http plugin to new subscription system 2011-10-30 11:36:53 +01:00
roberto@debian32 8c32b9665c re-implementation of subscription system 2011-10-30 11:30:53 +01:00
roberto@colossus 7405a01654 ready for next -rc ? 2011-10-28 17:53:16 +02:00
roberto@colossus 5d27691b4b fixed log rotation 2011-10-28 16:49:26 +02:00
roberto@debian32 19bbcfbf4c added @mule decorator 2011-10-28 16:22:39 +02:00
roberto@debian32 fa1064db87 added --umask 2011-10-28 16:10:26 +02:00
roberto@colossus 850ac69ca1 fixed master reloading 2011-10-28 11:35:18 +02:00
roberto@debian32 943edeb30c fixed a typo in subscribe-to and incresed slots to 64 2011-10-28 08:11:51 +02:00
roberto@debian32 01815a354b added a centos init script in contrib 2011-10-27 13:54:29 +02:00
roberto@debian32 2f4412aca1 allows .json as a valid vassal extension 2011-10-27 13:52:11 +02:00
roberto@oneiric64 2782bb7594 fixed 64bit support in rrdtool 2011-10-27 12:44:01 +02:00
roberto@debian32 074c1298d5 procname-prefix-spaced 2011-10-27 10:08:38 +02:00
roberto@debian32 55a7911611 added rrdtool plugin 2011-10-27 09:26:59 +02:00
roberto@debian32 013ad3044d added @mulefuc decorators 2011-10-26 10:51:03 +02:00
roberto@debian32 dcf4217b9d greatly improved uwsgi.mule_msg() 2011-10-26 10:13:20 +02:00
roberto@debian32 876dfc31a9 dynamic buffer_size and timeout for mule_get_msg 2011-10-26 06:43:07 +02:00
roberto@debian32 fd03bdbe00 improved mule and farm signal handling 2011-10-26 06:30:42 +02:00
roberto@debian32 83612649d5 mule_get_msg can manage signals 2011-10-26 06:11:07 +02:00
roberto@debian32 3c4db7e97e timerfd_create workaround 2011-10-26 05:45:06 +02:00
roberto@colossus 088c70efdc fixed locking 2011-10-25 18:05:52 +02:00
roberto@debian32 2b19029dd0 multiple mule_msg() 2011-10-25 17:46:41 +02:00
roberto@debian32 4fb5a84378 improved multi-mule support 2011-10-25 17:35:52 +02:00
roberto@debian32 b3107d9a25 another mule fix 2011-10-25 17:03:13 +02:00
roberto@debian32 bf32988f3e applied riccardo magliocchetti patch for .json support 2011-10-25 16:44:33 +02:00
roberto@debian32 1bf3dd7bf4 fixed mule patch message 2011-10-24 18:52:41 +02:00
roberto@debian32 07fd84f89f ported symimporter/symzipimporter to python3 2011-10-24 16:35:59 +02:00
roberto@debian32 3a8db4a97a fixed unlocking 2011-10-24 15:56:17 +02:00
roberto@debian32 aea30a26f5 added --mules <n> 2011-10-24 10:40:29 +02:00
roberto@gambit 8f5d1cdae7 Added tag 1.0-rc4 for changeset 24f7e260ea34 2011-10-24 10:05:02 +02:00
roberto@gambit 53913357e0 fixed strtok usage 2011-10-24 10:04:25 +02:00
roberto@debian32 098416f444 uWSGI 1.0-rc3 2011-10-24 09:42:41 +02:00
roberto@debian32 c98cb09c7c Added tag 1.0-rc3 for changeset 4e4e781ef89a 2011-10-24 09:42:27 +02:00
roberto@debian32 bb1ef28d69 updated decorators with @farm([name]) 2011-10-23 19:59:53 +02:00
roberto@debian32 1d5b05265d initial farm implementation 2011-10-23 19:18:31 +02:00
roberto@debian32 d9fef3c30e a little hack for psgi loader waiting for a truly agnostic init_uwsgi_app 2011-10-23 12:14:53 +02:00
roberto@debian32 e5dfb9efc3 improved get_memusage 2011-10-23 12:04:02 +02:00
roberto@debian32 02bab15e86 perl threading improvements 2011-10-23 11:49:25 +02:00
roberto@debian32 6f4ddead09 Added tag 1.0-rc2 for changeset 7a4e021ea7ba 2011-10-23 08:37:03 +02:00
roberto@gambit b361248ff6 fixed add_exported_opts 2011-10-23 08:35:15 +02:00
roberto@debian32 e9c42ceaa5 support for multiple values in options 2011-10-22 18:32:32 +02:00
roberto@debian32 5d7029744a PATH_INFO is correctly escaped in http modes 2011-10-22 09:35:01 +02:00
roberto@gambit 1084a3afa8 fixed mule patch loading 2011-10-20 10:38:59 +02:00
roberto@gambit ed254bffee fixed mule process name 2011-10-20 10:20:44 +02:00
roberto@djangocloud 733784d7dd another procname fix... 2011-10-19 16:13:10 +10:00
roberto@djangocloud cb5b26bcb4 another bunch of procname fixes 2011-10-19 14:26:07 +10:00
roberto@djangocloud 0065152bb1 daemons throttling subsystem 2011-10-18 18:53:22 +10:00
roberto@djangocloud 03266203fd another fix for environ 2011-10-18 18:30:13 +10:00
roberto@djangocloud 4a5f68f9d8 fixed environ 2011-10-18 18:12:39 +10:00
roberto@djangocloud 83e31a1c27 another setprocname fix 2011-10-18 16:20:33 +10:00
roberto@djangocloud 0efed5ef9c various emperor procname fixes 2011-10-18 16:15:06 +10:00
roberto@djangocloud cdfef1281d fixed another spooler compilation bug 2011-10-18 15:12:59 +10:00
roberto@debian32 e00907e142 --spooler-harakiri 2011-10-17 19:07:12 +02:00
roberto@app1 6dcbcf39e3 fixed compilation when spooler is disabled 2011-10-17 03:16:55 -05:00
roberto@debian32 044579a8e0 more verbose annihilation report 2011-10-16 11:16:13 +02:00
roberto@debian32 d2b52b4663 added uwsgi.setprocname() 2011-10-16 10:37:26 +02:00
roberto@debian32 7f75b2c02c added --procname and --procname-master 2011-10-16 10:18:45 +02:00
roberto@freebsd64 24a3f671e5 freebsd setproctitle 2011-10-16 10:06:08 +02:00
roberto@debian32 875100e3c8 check for mules before nuke 2011-10-16 09:58:37 +02:00
roberto@mrspurr 34bc7c0cfd check for procname 2011-10-16 09:54:35 +02:00
roberto@debian32 b39a10ff7c procname initial management 2011-10-16 09:45:41 +02:00
roberto@debian32 02331904de uWSGI 1.0-rc1 2011-10-15 08:47:00 +02:00
roberto@debian32 d1a4ae694e --locks 2011-10-15 08:32:32 +02:00
roberto@debian32 7a5ffc1124 --spooler-chdir 2011-10-14 19:20:05 +02:00
roberto@debian32 19c5bfb42c fixed a spooler signal bug spotted by Gabriele Giaccari 2011-10-14 18:32:17 +02:00
roberto@debian32 893bf3686b fixed a wrong typecast 2011-10-14 10:58:02 +02:00
roberto@debian32 e54fa9bcd4 added --emperor-stats 2011-10-13 07:53:32 +02:00
roberto@debian32 c1eb5ab0fe prepare for emperor-stats 2011-10-12 06:51:49 +02:00
roberto@mrspurr 461914dde4 completed --evil-reload options 2011-10-12 06:48:52 +02:00
roberto@debian32 85662578e4 implemented --mule-harakiri 2011-10-12 01:48:30 +02:00
roberto@debian32 a59c0ae795 setlinebuf in syslog mode 2011-10-12 00:54:18 +02:00
roberto@debian32 3a860155ee added --evil-reload-on-as and --evil-reload-on-rss 2011-10-11 20:39:00 +02:00
roberto@debian32 27553c2967 prepare for --evil-reload-... options 2011-10-11 20:18:31 +02:00
roberto@colossus 9a8ac9af3c added uwsgi.mule_id() 2011-10-11 07:31:41 +02:00
roberto@debian32 2f5daffe99 use hggit for better github sync 2011-10-09 09:11:54 +02:00
roberto@debian32 75cd31dce4 better spooler error reporting 2011-10-07 03:30:16 +02:00
roberto@colossus f7150d1b41 fixed mule socketpair 2011-10-06 18:37:24 +02:00
roberto@debian32 d6a6b65338 added --log-x-forwarded-for 2011-10-06 06:42:31 +02:00
roberto@freebsd64 979f6027b4 ignore SIGPIPE by default 2011-10-05 20:45:55 +02:00
roberto@freebsd64 7dc059c75b completed new freebsd64 sendfiel async support 2011-10-05 20:34:25 +02:00
roberto@freebsd64 b639b5974f better freebsd sendfile support 2011-10-05 20:19:12 +02:00
roberto@netbsd64 0de08c553c fixed a potential overflow 2011-10-05 21:16:28 +02:00
roberto@freebsd64 80788ac695 freebsd event fix 2011-10-05 19:01:29 +02:00
roberto@freebsd64 1494c621c1 non-linux fix 2011-10-05 18:43:53 +02:00
roberto@debian32 605e5b5173 export listen_queue size in stats 2011-10-05 17:24:46 +02:00
roberto@debian32 4cf2213051 added --log-truncate --log-reopen --log-maxsize --log-backupname 2011-10-05 11:58:15 +02:00
roberto@debian32 3aa36668e5 better error reporting 2011-10-04 20:28:08 +02:00
roberto@debian32 1c0b5b42e9 support for multiple --touch-reload options 2011-10-04 19:40:09 +02:00
roberto@openindiana64 702dc44fad fixed openindiana build on 64bit 2011-10-03 15:46:04 +02:00
roberto@solrisexpress 2cae07aa52 fixed 64bit compilation 2011-10-03 09:37:32 +00:00
roberto@ebian32 b5616ff25c completed mule signal handling 2011-10-03 08:36:21 +02:00
roberto@debian32 b7b7521975 refactored fds closing and socketpair 2011-10-03 08:29:19 +02:00
roberto@debian32 dce3263ee3 added mule messaging subsystem 2011-10-03 07:45:18 +02:00
roberto@debian32 9796e05ca1 added support for X_FORWARDED_SSL in http parser 2011-10-03 06:38:14 +02:00
roberto@debian32 5cc0d459ec struct uwsgi_server is becoming huge, better to add some comment 2011-10-02 20:45:03 +02:00
roberto@debian32 531a850a71 first almost-working commit for uWSGI mules 2011-10-02 20:05:31 +02:00
roberto@debian32 4c36280287 support --manage-script-name in http socket mode 2011-09-30 12:32:31 +02:00
roberto@debian32 70be8eb55e restored setup.py 2011-09-30 10:55:12 +02:00
roberto@debian32 f8b757b21e print argv in setup.py 2011-09-30 10:39:22 +02:00
roberto@debian32 3a63d352bb print envs in setup.py 2011-09-30 10:36:30 +02:00
roberto@sirius 60467705c5 fixed a stupid bug 2011-09-30 10:31:00 +02:00
roberto@debian32 eada0c09e0 refactored placeholder management 2011-09-30 10:21:26 +02:00
roberto@debian32 8e851aa6a1 fixed egg 2011-09-30 09:56:51 +02:00
roberto@debian32 eaf7bb967d added a check for http (3) 2011-09-30 09:43:42 +02:00
roberto@debian32 7be45c77b1 added a check for http (2) 2011-09-30 09:42:19 +02:00
roberto@debian32 5e2b460dc8 added a check for http (2) 2011-09-30 09:24:33 +02:00
roberto@debian32 16143e698f added a check for http 2011-09-30 09:21:12 +02:00
roberto@debian32 4259946e3b second little typecast fix 2011-09-30 08:51:18 +02:00
roberto@debian32 0a750d76ee little typecast fix 2011-09-30 08:50:00 +02:00
roberto@debian32 e4a9f5f0dd merge 2011-09-28 20:21:11 +02:00
roberto@debian32 d5b7698f89 added --stats 2011-09-28 20:20:40 +02:00
roberto@sirius a481e8508e added .gitignore 2011-09-28 17:23:22 +02:00
roberto@debian32 a53b57497b close bug #47 2011-09-28 07:27:43 +02:00
roberto@debian32 d871357b2d added uwsgi_req_error 2011-09-25 16:16:08 +02:00
roberto@debian32 2d57db55f4 removed a useless error checking 2011-09-25 14:06:06 +02:00
roberto@debian32 bae45ce03a error checking in uwsgi proto writer 2011-09-25 14:01:06 +02:00
roberto@debian32 44cc4336f1 added posix capability support 2011-09-25 13:41:10 +02:00
roberto@debian32 44f6e214fd improved uwsgi.queue_last 2011-09-25 10:44:19 +02:00
roberto@debian32 3e46f81d2b use PyLong_FromUnsignedLongLong 2011-09-25 06:42:23 +02:00
roberto@debian32 e4532b9a50 added memory usage in uwsgicc 2011-09-24 09:07:34 +02:00
roberto@debian32 2694be562c fixed respawn_count 2011-09-24 08:28:19 +02:00
roberto@debian32 fadb9edd7f added running time and avg_rt to uwsgicc 2011-09-24 08:24:51 +02:00
roberto@debian32 d85e0790de added response_time and running_time statistics 2011-09-24 06:40:30 +02:00
roberto@debian32 bc46c4d704 python3 fix 2011-09-23 08:36:28 +02:00
roberto@centos64 a73a010188 fixed build system for older gcc releases 2011-09-23 08:33:15 +02:00
roberto@debian3 4e8c8ef317 improved screen support 2011-09-21 06:09:05 +02:00
roberto@debian32 e402e7805d no need to set pty, screen is much metter 2011-09-21 05:27:58 +02:00
roberto@debian32 302b8f026b --cheaper improvement 2011-09-19 10:15:24 +02:00
roberto@debian32 630054b72a better wakeup of workers 2011-09-19 07:53:51 +02:00
roberto@debian32 a05f459b2b preliminary cheaper implementation 2011-09-19 07:13:45 +02:00
roberto@debian32 207979580a added uwsgi.extract 2011-09-18 07:04:36 +02:00
roberto@debian32 f69526f8bf parse plugin-specific options 2011-09-18 06:57:19 +02:00
roberto@debian32 e249d567a1 --fastrouter-cheap 2011-09-16 15:14:08 +02:00
roberto@debian32 a23ba653da better shared sockets support 2011-09-16 07:46:45 +02:00
roberto@debian32 0644d53572 set pty to raw mode 2011-09-13 08:35:50 +02:00
roberto@debian32 f58f51294d fixed sendfile typecasting 2011-09-11 07:41:42 +02:00
roberto@debian32 86194eb93e GC in symzipimporter is useless 2011-09-11 07:33:23 +02:00
roberto@debian32 0a89f375e6 added charles as contributor 2011-09-11 06:55:27 +02:00
roberto@debian32 6282178b3c fixed python optimize flag 2011-09-11 06:42:45 +02:00
roberto@debian32 8e14d68022 merge 2011-09-10 17:28:40 +02:00
roberto@debian32 e86bd0c070 preliminary support for detachable pyshell 2011-09-10 17:28:01 +02:00
roberto@mrspurr bf991f8892 report gb objects in welcome.py 2011-09-10 11:03:39 +02:00
roberto@mrspurr b341678d20 another symzip fix 2011-09-10 10:58:37 +02:00
roberto@mrspurr 5f59365d88 symzip GC fix 2011-09-10 10:54:27 +02:00
roberto@debian32 5130a7bb33 moved the old 'j' to 'J' option 2011-09-09 20:36:00 +02:00
roberto@dexter cc84a596d6 better iso99 check 2011-09-09 18:44:18 +02:00
roberto@longshot e67bed431a a fix for older gcc 2011-09-09 18:43:08 +02:00
roberto@dexter 72613a9f48 mime type optimization 2011-09-09 18:35:29 +02:00
roberto@sirius c048ea0615 better mimetype file check 2011-09-09 18:14:53 +02:00
roberto@dexter 957ca1b7ed added mime types support in static file serving 2011-09-09 17:06:35 +02:00
roberto@ebian32 d80a6df039 fixed a threading bug 2011-09-09 10:00:09 +02:00
roberto@mrspurr 94f9bd9d91 added Corey as contributor 2011-09-09 08:53:37 +02:00
roberto@mrspurr b480efe672 fixed script_name handling 2011-09-09 08:42:31 +02:00
roberto@mrspurr 4fc306d979 added a new debug entry 2011-09-09 08:32:20 +02:00
roberto@mrspurr 56abccbdeb another fix for urack.rb 2011-09-08 19:59:37 +02:00
roberto@mrspuur f218af0735 clang fixes 2011-09-08 19:45:46 +02:00
roberto@mrspurr 9b69c62780 automagic bundler in urack.rb 2011-09-08 13:44:50 +02:00
roberto@dexter eb5d67e07f 1.0 is better than 1.0.0 2011-09-07 16:09:45 +02:00
roberto@sirius e7391987b1 fixed sandboxviolation on osx 2011-09-07 12:33:12 +02:00
roberto@sirius 02cbe15575 test3 2011-09-07 12:32:02 +02:00
roberto@sirius a5a657f0d4 a second test 2011-09-07 12:29:24 +02:00
roberto@sirius 67567c86e0 a test 2011-09-07 12:27:47 +02:00
roberto@dexter 445d02da45 make easy_install happy 2011-09-06 17:58:02 +02:00
roberto@debian32 4a05df41ce subscription logging 2011-09-05 16:26:25 +02:00
roberto@debian32 5c0c2f6b45 yaml fix 2011-09-05 08:12:12 +02:00
roberto@debian32 0ab55fef46 added support for regexp in UWSGI_APPID 2011-09-04 21:33:30 +02:00
roberto@debian32 dd344bfe38 fixed a bug in multiapp mode 2011-09-04 18:01:04 +02:00
roberto@debian32 e92a889bcc refactored UWSGI_PY_READLINE_BUFSIZE 2011-09-03 07:15:51 +02:00
roberto@debian32 419d656a83 1.0.0-dev cycle started 2011-08-31 14:27:21 +02:00
roberto@debian32 3c3d58bfe9 pypyuwsgi.py 2011-08-31 14:01:46 +02:00
roberto@debian32 1989099cc5 preliminary pypy support 2011-08-31 13:18:32 +02:00
roberto@sirius 1446e3f0a9 allows pyuwsgi in osx 2011-08-31 12:09:56 +02:00
roberto@debian32 00fc31289d a pyuwsgi fix 2011-08-31 12:06:26 +02:00
roberto@sirius 2c463ad6af a test for libless pyuwsgi 2011-08-31 12:02:19 +02:00
roberto@sirius e641ae05c4 pyuwsgi 2011-08-31 11:42:22 +02:00
roberto@debian32 a13e0075ee fixed virtualhosting in fully-dynamic mode 2011-08-31 07:55:34 +02:00
roberto@debian32 e617a7b88e added an example for the new fd-based config 2011-08-30 12:08:22 +02:00
roberto@debian32 cbdeb4caad --stop and --reload, open by fifo and fd 2011-08-30 10:51:50 +02:00
roberto@sirius 59314d692f uWSGI 0.9.9 2011-08-29 17:32:08 +02:00
roberto@sirius 3dfa56b279 Added tag 0.9.9 for changeset 376ffd8f1906 2011-08-29 17:26:31 +02:00
roberto@dexter 920d5d7416 Changelog for 0.9.9 2011-08-29 11:32:27 +02:00
roberto@dexter dcb654d7fb spooler reload fix 2011-08-29 10:50:09 +02:00
roberto@solarisexpress a563da1223 solaris fix for lockf() 2011-08-29 10:34:46 +00:00
roberto@sirius 1e26cda615 fixed a race condition 2011-08-29 10:30:01 +02:00
roberto@dexter 97133b27ce the decoratortest is fully working, ready for release 2011-08-29 09:54:07 +02:00
roberto@sirius b428bd3b87 another bunch of build fixes 2011-08-29 08:02:37 +02:00
roberto@dexter 05136e74b4 fixed build system 2011-08-29 07:55:46 +02:00
roberto@mrspurr 9f28a8bdf1 improved upload progress 2011-08-28 20:53:46 +02:00
roberta@mrspurr d9361f1fee added test for upload progress 2011-08-28 19:13:56 +02:00
roberto@debian32 835230b1a4 emperor-tyrant 2011-08-28 09:15:13 +02:00
roberto@debian32 f88f51c553 added welcome.ini 2011-08-28 08:33:49 +02:00
roberto@debian32 1996305eb1 allows multiple --ini options 2011-08-28 07:55:54 +02:00
roberto@solrisexpress c7ad50e950 do not free getexecname() ret value 2011-08-28 07:37:21 +00:00
roberto@debian32 0ec0c29d67 fixed an indentation 2011-08-28 07:21:49 +02:00
roberto@solarisexpress 75af117e8a better magic plugin loading on binary_path 2011-08-28 07:14:42 +00:00
roberto@debian32 2b04cefe4e added help for a bunch of options 2011-08-27 19:37:34 +02:00
roberto@debian32 0e41c4111a fixed upstart 2011-08-27 18:46:53 +02:00
roberto@debian32 5f5d382c64 signal framework ported to gevent 2011-08-27 07:15:44 +02:00
roberto@dexter 3e867fe401 resolve domain names in socket logging 2011-08-26 16:20:14 +02:00
roberto@dexter 153142b8b0 fixed django uwsgi_admin without spooler 2011-08-26 15:02:02 +02:00
roberto@dexter 5562c0c047 use hub.join() instead of hub.switch() 2011-08-26 14:05:03 +02:00
roberto@debian32 f4a1f800ba timeout handling in gevent plugin 2011-08-26 12:34:12 +02:00
roberto@debian32 bdbc5e5605 another gevent improvement suggested by denis 2011-08-26 11:35:32 +02:00
roberto@debian32 4104f825ff another improvement for sys.executable in python3 2011-08-26 10:28:34 +02:00
roberto@longshot efa01ea404 better sys.executable and sys.argv values 2011-08-26 10:08:01 +02:00
roberto@debian32 982559ae66 snmp fixes 2011-08-26 09:54:11 +02:00
roberto@gambit 60002e8de8 Added tag 0.9.9-rc2 for changeset 6aa667612019 2011-08-26 08:17:20 +02:00
roberto@debian32 25d671e0f6 fixed python snmp api 2011-08-26 08:13:14 +02:00
roberto@debian32 5a58281a3f various gevent fixes 2011-08-26 07:37:26 +02:00
roberto@debian32 c422231806 ops another grunt fix 2011-08-25 18:16:58 +02:00
roberto@debian32 4979883fe5 fixed a grunt bug 2011-08-25 17:51:04 +02:00
roberto@debian32 8158a624d3 check for loop engine 2011-08-25 14:34:18 +02:00
roberto@debian32 06403b5fce fixed stupid bug in setup.py 2011-08-25 14:15:55 +02:00
roberto@debian32 bc482652fc updated setup.py 2011-08-25 14:13:13 +02:00
roberto@debian32 58aa5755e0 fixed a typo 2011-08-25 14:04:57 +02:00
roberto@debian32 bca835c58a added UWSGI_PROFILE unix env 2011-08-25 14:03:43 +02:00
roberto@debian32 4b0f68a57a check gevent version 2011-08-25 13:53:38 +02:00
roberto@debian32 b693d73ebe gevent dedicated plugin 2011-08-25 13:46:42 +02:00
roberto@dexter dfab80447b added a check for Riccardo 2011-08-24 18:24:45 +02:00
roberto@dexter bbde0c866a a couple of fixes, and reintroduction of string-based multiapp 2011-08-24 17:48:27 +02:00
roberto@mrspurr 7b3514f757 --emperor-throttle 2011-08-24 13:03:25 +02:00
roberto@mrspurr 6d5fb3b252 export cache and queue functions only if available 2011-08-20 11:12:32 +02:00
roberto@debian32 87e8f118d3 fix refcnt in async-disabled compilation 2011-08-19 16:35:16 +02:00
roberto@debian32 3ae78cc0a8 another bufsize fix 2011-08-19 16:28:44 +02:00
roberto@debian32 7ef921356f updated sharedarea 2011-08-19 15:22:20 +02:00
roberto@debian32 378185d997 added a build profile for uwsgi_pypy integration 2011-08-19 12:24:38 +02:00
roberto@debian32 c4b15a8509 changed final banner in library mode 2011-08-19 12:15:18 +02:00
roberto@debian32 96ef9d155b uwsgi.magic_table 2011-08-19 11:44:40 +02:00
roberto@debian32 d5e6412b20 uWSGI 0.9.9-rc1 2011-08-19 09:57:58 +02:00
roberto@debian32 eebe757c16 Added tag 0.9.9-rc1 for changeset fb168b0b8616 2011-08-19 08:51:26 +02:00
roberto@debian32 43a21d32cb fixed a stupid bug 2011-08-19 08:49:39 +02:00
roberto@debian32 9f9eb5ef17 improved apache2 SCRIPT_NAME/PATH_INFo handling 2011-08-19 08:48:15 +02:00
roberto@debian32 0116c62980 another refcnt fix 2011-08-19 07:06:29 +02:00
roberto@debian32 fae446e495 fix for 3.0-arch 2011-08-19 06:46:07 +02:00
roberto@debian32 6f7054df18 more tolerant cache and queue size 2011-08-18 14:27:21 +02:00
roberto@debian32 0f31c21f4a completed queue subsystem with test 2011-08-18 09:46:32 +02:00
roberto@debian32 bd3e234703 another xml app tag fix 2011-08-18 07:06:27 +02:00
roberto@gambit 71bfd63623 fixed xml app tag 2011-08-18 07:01:13 +02:00
unbit@localhost 98b89dc83c Added tag 0.9.9-beta1 for changeset 6945ee03c7ea 2011-08-18 06:33:20 +02:00
roberto@gambit 97ec789bbe fixed casting 2011-08-18 06:13:51 +02:00
roberto@debian32 14b403c046 fixed a post-buffering bug 2011-08-17 12:42:12 +02:00
roberto@debian32 bc01d25068 uWSGI can now be built as a shardd library 2011-08-17 11:21:22 +02:00
roberto@fedora64 69808c34a8 fixed callable and start_response refcnt 2011-08-16 17:00:15 +02:00
roberto@debian32 273181daf5 another threading fix 2011-08-16 08:00:09 +02:00
roberto@debian32 8d2394eba1 better name handling in --wsgi-file 2011-08-16 07:33:46 +02:00
roberto@debian32 6f5b468b11 fix threading bug in pyshell 2011-08-16 07:31:20 +02:00
roberta@mrspurr c9e759bc14 allow threads in gateways 2011-08-14 07:46:29 +02:00
roberto@debian32 e6d064f5c1 allows fastrouter cache to set modifier1 2011-08-13 11:25:06 +02:00
roberto@debian32 8f7ed02475 a bunch of lua fixes 2011-08-13 11:12:10 +02:00
roberto@debian32 f7edcebbdc added --fastrouter-use-code-string 2011-08-13 08:39:17 +02:00
roberto@debian32 a19b392ba6 applications list is now shared 2011-08-12 08:08:39 +02:00
roberto@mrspurr 287df9ef86 fixed a stupid bug with thread stacksize 2011-08-11 07:32:02 +02:00
roberto@juggernaut de7be379c4 shut up gcc on ubuntu lucid 2011-08-10 14:43:57 +02:00
roberto@debian32 1e4d41795c allows setting threads stacksize 2011-08-10 12:13:46 +02:00
roberto@debian32 e2e973a20e we are now at 0.9.9-dev 2011-08-09 08:25:09 +02:00
roberto@debian32 5d993fbfc0 implemented UWSGI_APPID var 2011-08-09 08:20:12 +02:00
roberto@debian32 a94a8ea287 added a check on spooler unlink 2011-08-05 06:53:43 +02:00
roberto@debian32 55d8677a46 fixed a spooler thread problem 2011-08-04 18:20:44 +02:00
roberto@debian32 4004aeb54e fileno() for wsgi.input 2011-08-04 16:53:39 +02:00
roberto@debian32 2de2898d86 fix a stupid bug 2011-08-04 16:28:47 +02:00
roberto@debian32 8c1b48a88d a new kick-ass feature for the spooler 2011-08-04 16:25:17 +02:00
roberto@debian32 9bd3022a5e a bunch of threading fixes in the spooler 2011-08-04 14:11:40 +02:00
roberto@debian32 eb0ce609f0 wakeup spooler (if possibile) after each submission 2011-08-04 11:15:24 +02:00
roberto@debian32 5353eba35b improved the pyshell 2011-08-04 07:05:39 +02:00
roberto@debian32 4f94ceed5e fix for solaris 2011-08-03 16:00:35 +02:00
roberto@debian32 cd29998b40 --pyshell and fix for wsgi.url_scheme in pep3333 2011-08-03 15:07:15 +02:00
roberto@debian32 9aad6be26a better realoding in lazy mode 2011-08-03 06:54:48 +02:00
roberto@debian32 19edee88bc fixed --log-master 2011-08-02 21:15:10 +02:00
roberto@debian32 42e6a7d024 wait max 60 seconds for gracefull reload 2011-08-02 20:36:16 +02:00
roberto@debian32 1890290d05 fixed reload-mercy in lazy mode 2011-08-02 20:28:31 +02:00
roberto@debian32 c85231be96 improved picasso test 2011-08-02 16:10:17 +02:00
roberto@debian32 0ca89771d6 fixed pump method 2011-08-02 16:01:06 +02:00
roberto@debian32 d203b12464 fixed --http-var 2011-08-02 15:48:54 +02:00
roberto@debian32 b64690bdd6 allow compilation of pump in python3 2011-08-02 15:38:41 +02:00
roberto@debian32 e76c696678 completed pump support 2011-08-02 15:31:39 +02:00
roberto@debian32 f1ad2090fc remove incompatible LDFLAGS 2011-08-02 15:13:21 +02:00
roberto@debian32 f0be3c3966 fixed rack.scheme 2011-08-02 15:02:26 +02:00
roberto@debian32 8b7abc956f first round for pump support 2011-08-02 13:56:52 +02:00
roberto@debian32 25a8af392b fixed a leak in web3 subhandler 2011-08-02 12:48:15 +02:00
roberto@debian32 ebe1b3497e updated web3 handler 2011-08-02 09:33:49 +02:00
roberto@debian32 6a7246fe5a a little fix 2011-07-31 19:47:54 +02:00
roberto@debian32 1d64e46fcd support for data:// in import/module 2011-07-31 19:42:24 +02:00
roberto@debian32 6d5e089e4e uwsgi.ZipImporter 2011-07-31 19:32:14 +02:00
roberto@debian32 845bc1d41b added data:// facility 2011-07-31 18:51:10 +02:00
roberto@solarixexpress 007cd73ac5 solaris fix 2011-07-31 19:13:01 +00:00
roberto@freebsd64 651a7e4078 added freebsd binary detection 2011-07-31 17:47:15 +02:00
roberto@debian32 c3423370ec added binary detection for sun 2011-07-31 16:07:36 +02:00
roberto@mrspurr 500f1e37f6 better binary detection in osx 2011-07-31 17:25:10 +02:00
roberto@debian32 699a9bfa8e better binary detection on linux 2011-07-31 15:39:36 +02:00
roberto@debian32 90aa7f0d0e fixed --set 2011-07-31 14:44:36 +02:00
roberto@debian32 527819703e added -S/--set option 2011-07-31 14:35:54 +02:00
roberto@debian32 47adc8fe48 added --http-socket and --fastcgi-socket 2011-07-29 14:26:07 +02:00
roberto@debian32 865ad5d631 virtualhosting for http protocol 2011-07-29 13:59:29 +02:00
roberto@debian32 877b99c1d5 extreme optimization for http protocol 2011-07-29 13:49:22 +02:00
roberto@debian32 45bb124200 fixed a typo 2011-07-29 10:04:10 +02:00
roberto@debian32 147af04342 fixed apache2 module, adding uWSGImaxVars directive (bug #31) 2011-07-29 08:06:13 +02:00
roberto@debian32 b30e54bdc1 close bug #35 2011-07-29 07:30:24 +02:00
roberto@debian32 1b7484cf22 closed bug #34 2011-07-29 07:27:03 +02:00
roberto@debian32 c04513f8bd fixed SERVER_PORT in http protocol handler 2011-07-29 06:13:50 +02:00
roberto@debian32 c29db6ee6f cache fixed WSGI values 2011-07-29 05:53:54 +02:00
roberto@debian32 0d60b001fb uwsgi.cache_update 2011-07-28 10:27:37 +02:00
roberto@dexter ea7d428c1b added UWSGI.signal_registered 2011-07-27 11:11:30 +02:00
roberto@dexter 55ac61dbb0 signal framework ported to ruby.rack plugin 2011-07-27 10:58:03 +02:00
roberto@mrspurr 048878b197 added uwsgi.signal to ruby interface 2011-07-27 08:27:24 +02:00
roberto@dexter 1e479de839 auto-set post-buffering in rack plugin 2011-07-26 09:46:11 +02:00
roberto@debian32 5b34f6c515 fixed multiprotocol uwsgi.sendfile 2011-07-26 07:06:46 +02:00
roberto@centos6 8fcf83769c a zombie cannot be avoided... 2011-07-25 08:58:17 +02:00
roberto@centos6 d1ca55da55 get rid of a zombie in http-only mode 2011-07-25 08:23:05 +02:00
roberto@gambit 375328623b Added tag 0.9.8.3 for changeset f4d3c4dcd7a6 2011-07-23 08:27:35 +02:00
148 changed files with 9982 additions and 2478 deletions
+9
View File
@@ -27,3 +27,12 @@ e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
+2
View File
@@ -12,3 +12,5 @@ Marco Beri, Link I.T. S.p.a.
Leonid Borisenko
Cal Leeming, Simplicity Media Ltd
Luigi Scarso
Corey Farwell
Charles Duffy
+34
View File
@@ -1,3 +1,37 @@
*** august 2011 ***
* 0.9.9 [20110829]
- various spooler improvements
- upload progress optimizations and fixes
- new emperor mode: Tyrant
- allows multiple --ini options
- better binary path detection
- gevent loop engine support
- resolve domain names in socket logging
- snmp fixes and reintroduction of the snmp-api
- fixed grunt mode
- you can specify build profile via env var UWSGI_PROFILE
- reintroduction of string-based multiapp
- new option --emperor-throttle
- improved queue and sharedarea subsystems
- uWSGI can now be built as a shared library
- new api attribute: uwsgi.magic_table
- improved apache2 module
- new option --pyshell
- allow threads in gateways
- fastrouter improvements
- the application list is now shared and exported to the api
- allows setting the thread stack size
- UWSGI_APPID for better multiapp hosting
- better reloading in lazy mode
- native pump support
- various rack fixes
- support for attaching binary data in the executable
- new option --set
- extreme-optimized http protocol parser
- WSGI handler optimizations
*** july 2011 ***
* 0.9.8.3 [20110723]
+76 -52
View File
@@ -51,7 +51,6 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
#include <fcntl.h>
#define MAX_VARS 64
#define DEFAULT_SOCK "/tmp/uwsgi.sock"
typedef struct {
@@ -73,6 +72,7 @@ typedef struct {
char script_name[256];
char scheme[9];
int cgi_mode ;
int max_vars;
} uwsgi_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
@@ -83,8 +83,18 @@ static uint16_t uwsgi_swap16(uint16_t x) {
}
#endif
static int uwsgi_add_var(struct iovec *vec, int i, char *key, char *value, uint16_t *pkt_size) {
static int uwsgi_add_var(struct iovec *vec, int i, request_rec *r, char *key, char *value, uint16_t *pkt_size) {
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
#if APR_IS_BIGENDIAN
if (i+6 > c->max_vars) {
#else
if (i+4 > c->max_vars) {
#endif
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: max number of uwsgi variables reached. consider increasing it with uWSGImaxVars directive");
return i;
}
#if APR_IS_BIGENDIAN
char *ptr;
@@ -150,6 +160,8 @@ static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
c->modifier1 = 0 ;
c->modifier2 = 0 ;
c->cgi_mode = 0 ;
c->max_vars = 128;
c->script_name[0] = 0;
return c;
}
@@ -164,6 +176,13 @@ static void *uwsgi_dir_config(apr_pool_t *p, char *dir) {
c->modifier1 = 0 ;
c->modifier2 = 0 ;
c->cgi_mode = 0 ;
c->max_vars = 128;
c->script_name[0] = 0;
if (dir) {
if (strcmp(dir, "/")) {
strncpy(c->script_name, dir, 255);
}
}
return c;
}
@@ -243,11 +262,8 @@ static int uwsgi_handler(request_rec *r) {
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
#if APR_IS_BIGENDIAN
struct iovec uwsgi_vars[(MAX_VARS*6)+1] ;
#else
struct iovec uwsgi_vars[(MAX_VARS*4)+1] ;
#endif
struct iovec *uwsgi_vars;
int vecptr = 1 ;
char pkt_header[4];
uint16_t pkt_size = 0;
@@ -315,68 +331,49 @@ static int uwsgi_handler(request_rec *r) {
}
#if APR_IS_BIGENDIAN
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*6)+1);
#else
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*4)+1);
#endif
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
if (c->scheme[0] != 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
}
if (c->script_name[0] == '/') {
if (c->script_name[1] == 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", c->script_name, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
}
if (c->script_name[0] != 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", c->script_name, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
}
else {
if (r->path_info) {
if (strlen(r->path_info) <= 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri, (strlen(r->uri) - strlen(r->path_info) )) , &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->path_info, &pkt_size) ;
}
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri, &pkt_size) ;
}
headers = apr_table_elts(r->headers_in);
h = (apr_table_entry_t *) headers->elts;
// check for max vars (a bit ugly)
cnt = headers->nelts ;
if (cnt + 11 > MAX_VARS) {
cnt = MAX_VARS -11;
}
for(i=0;i< cnt;i++) {
for(i=0;i< headers->nelts;i++) {
if (h[i].key){
if (!strcasecmp(h[i].key, "Content-Type")) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_TYPE", h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_TYPE", h[i].val, &pkt_size) ;
}
else if (!strcasecmp(h[i].key, "Content-Length")) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
}
else {
penv = apr_pstrcat(r->pool, "HTTP_", h[i].key, NULL);
@@ -388,7 +385,7 @@ static int uwsgi_handler(request_rec *r) {
*cp = toupper(*cp);
}
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, penv, h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, penv, h[i].val, &pkt_size) ;
}
}
}
@@ -397,7 +394,7 @@ static int uwsgi_handler(request_rec *r) {
headers = apr_table_elts(r->subprocess_env);
h = (apr_table_entry_t*) headers->elts;
for (i = 0; i < headers->nelts; ++i) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, h[i].key, h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, h[i].key, h[i].val, &pkt_size) ;
}
@@ -418,11 +415,13 @@ static int uwsgi_handler(request_rec *r) {
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() %s", strerror(errno));
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt != pkt_size+4) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() returned wrong size");
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -434,6 +433,7 @@ static int uwsgi_handler(request_rec *r) {
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: read() client block failed !");
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -458,6 +458,7 @@ static int uwsgi_handler(request_rec *r) {
if (cnt == 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
@@ -467,6 +468,7 @@ static int uwsgi_handler(request_rec *r) {
if (errno != ECONNRESET) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else {
@@ -489,6 +491,7 @@ static int uwsgi_handler(request_rec *r) {
if (r->connection->aborted) {
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
@@ -508,6 +511,7 @@ static int uwsgi_handler(request_rec *r) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -521,6 +525,7 @@ static int uwsgi_handler(request_rec *r) {
if (!c->cgi_mode) {
if (uwsgi_http_status_read == 0) {
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -528,11 +533,13 @@ static int uwsgi_handler(request_rec *r) {
if (hret = ap_scan_script_header_err_brigade(r, bb, NULL)) {
apr_brigade_destroy(bb);
free(uwsgi_vars);
return hret;
}
}
free(uwsgi_vars);
return ap_pass_brigade(r->output_filters, bb) ;
}
@@ -564,6 +571,22 @@ static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const
}
static const char *cmd_uwsgi_max_vars(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
int val ;
if (cfg) {
c = cfg ;
}
else {
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
c->max_vars = atoi(value);
return NULL;
}
static const char * cmd_uwsgi_modifier1(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
@@ -707,6 +730,7 @@ static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
AP_INIT_TAKE1("uWSGImaxVars", cmd_uwsgi_max_vars, NULL, ACCESS_CONF, "Set the maximum allowed number of uwsgi variables (default 128)"),
{NULL}
};
+4
View File
@@ -212,6 +212,10 @@ void *async_loop(void *arg1) {
uwsgi.async_runqueue = NULL;
uwsgi.async_runqueue_cnt = 0;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
}
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
+13
View File
@@ -0,0 +1,13 @@
import struct
import sys
import os
filename = sys.argv[1]
size = os.path.getsize(filename)
f = open(filename, 'r')
print(f.read())
f.close()
print(struct.pack("<Q", size))
+1
View File
@@ -1,4 +1,5 @@
import sys
import uwsgi
print("i am the bootstrap for uwsgi.SymbolsImporter")
sys.meta_path.insert(0, uwsgi.SymbolsImporter())
+4
View File
@@ -0,0 +1,4 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.ZipImporter("data://0"))
+3
View File
@@ -0,0 +1,3 @@
import uwsgi
print uwsgi.extract("data://0")
+2 -1
View File
@@ -27,7 +27,8 @@ plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, ugreen
embedded_plugins = python, ping, cache, nagios, rrdtool, rpc, fastrouter, http, ugreen
as_shared_library = false
locking = auto
event = auto
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, gevent
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = null
as_shared_library = true
-4
View File
@@ -1,7 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,lua
[python]
paste = true
web3 = true
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = symcall
as_shared_library = true
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = pyuwsgi.so
embedded_plugins = pyuwsgi,python,ping,cache,nagios,rpc,ugreen
as_shared_library = true
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = rack, ping, nagios, rpc
embedded_plugins = rack, ping, cache, nagios, rpc, fastrouter, http, ugreen
+11 -294
View File
@@ -8,7 +8,7 @@ void uwsgi_init_cache() {
if (!uwsgi.cache_blocksize)
uwsgi.cache_blocksize = UMAX16;
if (uwsgi.cache_blocksize % uwsgi.page_size != 0) {
if ((uwsgi.cache_blocksize * uwsgi.cache_max_items) % uwsgi.page_size != 0) {
uwsgi_log("invalid cache blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.cache_blocksize, uwsgi.page_size);
exit(1);
}
@@ -94,151 +94,6 @@ void uwsgi_init_cache() {
uwsgi_log("*** Cache subsystem initialized: %dMB preallocated ***\n", ((sizeof(uint64_t) * UMAX16) + (sizeof(uint64_t) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024));
}
struct uwsgi_subscriber_name *uwsgi_get_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint64_t ovl;
struct uwsgi_subscriber *usub;
struct uwsgi_subscriber_name *ret = NULL;
usub = (struct uwsgi_subscriber *) uwsgi_dict_get(udict, key, keylen, &ovl);
if (usub == NULL || !ovl) return NULL;
if (!usub->nodes) return NULL;
if (usub && ovl) {
ret = &usub->names[usub->current];
// dead node
if (ret->len == 0) {
if (usub->current == usub->nodes-1) {
usub->nodes--;
}
// retry with another node (if available)
if (usub->nodes > 0) {
usub->current++;
if (usub->current >= usub->nodes) usub->current = 0;
return uwsgi_get_subscriber(udict, key, keylen);
}
}
if (usub->nodes > 1) {
usub->current++;
if (usub->current >= usub->nodes) usub->current = 0;
}
}
return ret;
}
void uwsgi_add_subscriber(struct uwsgi_dict *udict, struct uwsgi_subscribe_req *usr) {
char *ptr;
uint64_t vallen = 0;
struct uwsgi_subscriber *usub, nusub;
int found = 0;
int i;
ptr = uwsgi_dict_get(udict, usr->key, usr->keylen, &vallen);
if (ptr && vallen) {
usub = (struct uwsgi_subscriber *) ptr;
for(i=0;i<(int)usub->nodes;i++) {
if (!uwsgi_strncmp(usub->names[i].name, usub->names[i].len, usr->address, usr->address_len)) {
found = 1;
break;
}
}
if (!found) {
found = usub->nodes;
// check for unallocated slot
for(i=0;i<(int)usub->nodes;i++) {
if (usub->names[i].len == 0) {
found = i;
break;
}
}
usub->names[found].len = usr->address_len;
usub->names[found].modifier1 = usr->modifier1;
usub->names[found].modifier2 = usr->modifier2;
memcpy(usub->names[found].name, usr->address, usr->address_len);
if (found == (int) usub->nodes) {
usub->nodes++;
}
}
return;
}
else {
nusub.nodes = 1;
nusub.current = 0;
memcpy(nusub.names[0].name, usr->address, usr->address_len);
nusub.names[0].modifier1 = usr->modifier1;
nusub.names[0].modifier2 = usr->modifier2;
uwsgi_dict_set(udict, usr->key, usr->keylen, (char *) &nusub, sizeof(struct uwsgi_subscriber));
}
}
struct uwsgi_dict *uwsgi_dict_create(uint64_t items, uint64_t blocksize) {
int i;
struct uwsgi_dict *udict = (struct uwsgi_dict *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict) {
uwsgi_error("mmap()");
exit(1);
}
if (!blocksize) blocksize = 4096;
if (blocksize % uwsgi.page_size != 0) {
uwsgi_log("invalid shared dictionary blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) udict->blocksize, uwsgi.page_size);
exit(1);
}
udict->blocksize = blocksize;
udict->max_items = items;
udict->hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->hashtable) {
uwsgi_error("mmap()");
exit(1);
}
memset(udict->hashtable, 0, sizeof(uint64_t) * UMAX16);
udict->unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->unused_stack) {
uwsgi_error("mmap()");
exit(1);
}
memset(udict->unused_stack, 0, sizeof(uint64_t) * udict->max_items);
udict->items = (struct uwsgi_dict_item *) mmap(NULL, sizeof(struct uwsgi_dict_item) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->items) {
uwsgi_error("mmap()");
exit(1);
}
udict->data = mmap(NULL, udict->blocksize * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->data) {
uwsgi_error("mmap()");
exit(1);
}
for(i=0;i< (int) udict->max_items;i++) {
memset(&udict->items[i], 0, sizeof(struct uwsgi_dict_item));
}
udict->first_available_item = 1;
udict->unused_stack_ptr = 0;
udict->lock = uwsgi_mmap_shared_lock();
uwsgi_lock_init(udict->lock);
return udict;
}
uint32_t djb33x_hash(char *key, int keylen) {
register uint32_t hash = 5381;
@@ -252,89 +107,6 @@ uint32_t djb33x_hash(char *key, int keylen) {
}
inline uint64_t uwsgi_dict_get_index(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
uint64_t slot = udict->hashtable[hash_key];
struct uwsgi_dict_item *udi;
udi = &udict->items[slot];
// first round
if (udi->djbhash != hash) goto cycle;
if (udi->keysize != keylen) goto cycle;
if (memcmp(udi->key, key, keylen)) goto cycle;
return slot;
cycle:
while(udi->next) {
slot = udi->next;
udi = &udict->items[slot];
if (udi->djbhash != hash) continue;
if (udi->keysize != keylen) continue;
if (!memcmp(udi->key, key, keylen)) return slot;
}
return 0;
}
char *uwsgi_dict_get(struct uwsgi_dict *udict, char *key, uint16_t keylen, uint64_t *valsize) {
uint64_t index = uwsgi_dict_get_index(udict, key, keylen);
if (index) {
*valsize = udict->items[index].valsize;
udict->items[index].hits++;
return udict->data+(index*udict->blocksize);
}
return NULL;
}
int uwsgi_dict_del(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint64_t index = 0;
struct uwsgi_dict_item *udi;
int ret = -1;
index = uwsgi_dict_get_index(udict, key, keylen);
if (index) {
udi = &udict->items[index] ;
udi->keysize = 0;
udi->valsize = 0;
udict->unused_stack_ptr++;
udict->unused_stack[udict->unused_stack_ptr] = index;
// try to return to initial condition...
if (index == udict->first_available_item-1) {
udict->first_available_item--;
}
ret = 0;
// relink collisioned entry
if (udi->prev) {
udict->items[udi->prev].next = udi->next;
}
if (udi->next) {
udict->items[udi->next].prev = udi->prev;
}
if (!udi->prev && !udi->next) {
// reset hashtable entry
udict->hashtable[udi->djbhash % 0xffff] = 0;
}
udi->djbhash = 0;
udi->prev = 0;
udi->next = 0;
}
return ret;
}
inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
@@ -512,77 +284,22 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
uci->prev = last_index;
}
}
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = &uwsgi.cache_items[index] ;
if (expires) {
expires += time(NULL);
uci->expires = expires;
}
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
uci->valsize = vallen;
ret = 0;
}
end:
return ret;
}
int uwsgi_dict_set(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *val, uint64_t vallen) {
uint64_t index = 0, last_index = 0 ;
struct uwsgi_dict_item *udi, *udii;
int ret = -1;
int slot;
if (!keylen || !vallen) return -1;
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
if (udict->first_available_item >= udict->max_items && !udict->unused_stack_ptr) {
uwsgi_log("*** DANGER dictionary %p is FULL !!! ***\n", udict);
goto end;
}
index = uwsgi_dict_get_index(udict, key, keylen);
if (!index) {
if (udict->unused_stack_ptr) {
index = udict->unused_stack[udict->unused_stack_ptr];
udict->unused_stack_ptr--;
}
else {
index = udict->first_available_item;
if (udict->first_available_item < udict->max_items) {
udict->first_available_item++;
}
}
udi = &udict->items[index] ;
udi->djbhash = djb33x_hash(key, keylen);
udi->hits = 0;
memcpy(udi->key, key, keylen);
memcpy(udict->data+(index*udict->blocksize), val, vallen);
// set this as late as possibile (to reduce races risk)
udi->valsize = vallen;
udi->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
slot = udi->djbhash % 0xffff;
if (udict->hashtable[slot] == 0) {
udict->hashtable[slot] = index;
}
else {
// append to first available next
last_index = udict->hashtable[slot];
udii = &udict->items[ last_index ];
while(udii->next) {
last_index = udii->next;
udii = &udict->items[ last_index ];
}
udii->next = index;
udi->prev = last_index;
}
}
end:
return ret;
}
/* THIS PART IS HEAVILY OPTIMIZED: PERFORMANCE NOT ELEGANCE !!! */
void *cache_thread_loop(void *fd_ptr) {
+25
View File
@@ -0,0 +1,25 @@
require 'stringio'
hello = proc do |signum|
puts "Hello i am signal #{signum}"
end
file_changed = proc do |signum|
puts "/tmp has been modified"
end
UWSGI.register_signal(17, '', hello)
UWSGI.register_signal(30, '', file_changed)
UWSGI.add_rb_timer(17 , 2)
UWSGI.add_timer(17 , 1)
UWSGI.add_file_monitor(30 , '/tmp')
puts UWSGI.signal_registered(1)
puts UWSGI.signal_registered(17)
run lambda { |env|
puts env.inspect
UWSGI.signal(17)
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World!\n")]
}
+99
View File
@@ -0,0 +1,99 @@
#!/bin/bash
# uwsgi - Use uwsgi to run python and wsgi web apps.
#
# chkconfig: - 85 15
# description: Use uwsgi to run python and wsgi web apps.
# processname: uwsgi
# author: Roman Vasilyev
# Source function library.
. /etc/rc.d/init.d/functions
PATH=/opt/uwsgi:/sbin:/bin:/usr/sbin:/usr/bin
prog=/usr/sbin/uwsgi
OWNER=nginx
NAME=uwsgi
DESC=uwsgi
#DAEMON_OPTS="-s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 4 -d /var/log/uwsgi.log --pidfile /var/run/$NAME.pid --pythonpath $PYTHONPATH --module $MODULE"
DAEMON_OPTS="-s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 16 -b 32768 -d /var/log/$NAME.log --pidfile /var/run/$NAME.pid --uid $OWNER"
[ -f /etc/sysconfig/uwsgi ] && . /etc/sysconfig/uwsgi
lockfile=/var/lock/subsys/uwsgi
start () {
echo -n "Starting $DESC: "
daemon $prog $DAEMON_OPTS
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop () {
echo -n "Stopping $DESC: "
killproc $prog
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
reload () {
echo "Reloading $NAME"
killproc $prog -HUP
RETVAL=$?
echo
}
force-reload () {
echo "Reloading $NAME"
killproc $prog -TERM
RETVAL=$?
echo
}
restart () {
stop
start
}
rh_status () {
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|force-reload)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
status)
rh_status
;;
*)
echo "Usage: $0 {start|stop|restart|reload|force-reload|status}" >&2
exit 2
;;
esac
exit 0
+11
View File
@@ -0,0 +1,11 @@
from tasksconsumer import enqueue
def application(env, sr):
sr('200 OK', [('Content-Type','text/html')])
enqueue(queue='fast', pippo='pluto')
return "Task enqueued"
+9
View File
@@ -0,0 +1,9 @@
from tasksconsumer import *
@queueconsumer('fast', 4)
def fast_queue(arguments):
print "fast", arguments
@queueconsumer('slow')
def slow_queue(arguments):
print "foobar", arguments
+44
View File
@@ -0,0 +1,44 @@
from uwsgidecorators import *
import Queue
from threading import Thread
queues = {}
class queueconsumer(object):
def __init__(self, name, num=1, **kwargs):
self.name = name
self.num = num
self.queue = Queue.Queue()
self.threads = []
self.func = None
queues[self.name] = self
@staticmethod
def consumer(self):
while True:
req = self.queue.get()
print req
self.func(req)
self.queue.task_done()
def __call__(self, f):
self.func = f
for i in range(self.num):
t = Thread(target=self.consumer,args=(self,))
self.threads.append(t)
t.daemon = True
t.start()
@spool
def spooler_enqueuer(arguments):
if 'queue' in arguments:
queue = arguments['queue']
queues[queue].queue.put(arguments)
else:
raise Exception("You have to specify a queue name")
def enqueue(*args, **kwargs):
return spooler_enqueuer.spool(*args, **kwargs)
+3 -1
View File
@@ -12,4 +12,6 @@ env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --no-orphans avoid workers without master
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -m simple_app --logto $LOGTO -M -p 4
# --die-on-term could be a good idea
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
+4
View File
@@ -1,5 +1,9 @@
require 'rubygems'
require 'socket'
begin
require 'bundler/setup'
rescue LoadError
end
require 'rack'
require 'rack/content_length'
require 'rack/rewindable_input'
+2
View File
@@ -0,0 +1,2 @@
[uwsgi]
show-config = true
+21 -10
View File
@@ -10,8 +10,8 @@ import time
# register rpc function helloworld
@rpc("helloworld")
def hello_world():
return "Hello World"
def hello2():
return "[RPC] Hello World"
# register signal 1
@signal(1)
@@ -45,6 +45,7 @@ def tmpmodified(num):
def a_long_task(args):
for i in xrange(1,10):
print("%s = %d" % ( str(args), i))
print(uwsgi.call('helloworld'))
time.sleep(1)
# continuosly spool a long running task
@@ -52,10 +53,12 @@ def a_long_task(args):
def an_infinite_task(args):
for i in xrange(1,4):
print("infinite: %d %s" % (i, str(args)))
print(uwsgi.call('helloworld'))
uwsgi.signal(100)
time.sleep(1)
# spool a task after 60 seconds
# spool a task after 5 seconds
@spool
def delayed_task(args):
print("*** I am a delayed spool job. It is %s [%s]***" % (time.asctime(), str(args)))
@@ -89,7 +92,10 @@ def a_running_thread_with_args(who):
def a_post_fork_thread():
while True:
time.sleep(3)
print("Hello from a thread in worker %d" % uwsgi.worker_id())
if uwsgi.i_am_the_spooler():
print("Hello from a thread in the spooler")
else:
print("Hello from a thread in worker %d" % uwsgi.worker_id())
@postfork
def fork_happened():
@@ -97,24 +103,29 @@ def fork_happened():
@postfork
def fork_happened2():
print("waiting for a signal...")
uwsgi.signal_wait()
print("signal received: %d" % uwsgi.signal_received())
if uwsgi.i_am_the_spooler():
return
print("worker %d is waiting for signal 100..." % uwsgi.worker_id())
uwsgi.signal_wait(100)
print("worker %d received signal %d" % (uwsgi.worker_id(), uwsgi.signal_received()))
print("fork() has been called [2] wid: %d" % uwsgi.worker_id())
@postfork
@lock
def locked_func():
print("starting locked function on worker %d" % uwsgi.worker_id())
for i in xrange(1, 100):
time.sleep(0.2)
for i in xrange(1, 5):
time.sleep(1)
print("[locked %d] waiting..." % uwsgi.worker_id())
print("done with locked function on worker %d" % uwsgi.worker_id())
print(uwsgi.call('helloworld'))
spool_filename = a_long_task.spool({'foo':'bar'}, hello='world')
print("spool filename = %s" % spool_filename)
an_infinite_task.spool(foo='bar', priority=3)
delayed_task.spool(foo2='bar2', at=time.time()+60)
when = int(time.time())+5
print("scheduling a delayed task at %d" % when)
delayed_task.spool(foo2='bar2', at=when)
a_running_thread()
a_running_thread_with_args("uWSGI")
uwsgi_source_file = open('uwsgi.c','r')
+4 -3
View File
@@ -14,10 +14,11 @@ def index(request):
w['load'] = (100 * (w['running_time']/1000))/total_load
w['last_spawn_str'] = time.ctime(w['last_spawn'])
spooler_jobs = uwsgi.spooler_jobs()
jobs = []
for j in spooler_jobs:
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
if 'spooler' in uwsgi.opt:
spooler_jobs = uwsgi.spooler_jobs()
for j in spooler_jobs:
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
'started_on': time.ctime(uwsgi.started_on),
+167 -22
View File
@@ -8,6 +8,8 @@ extern char **environ;
int emperor_queue;
char *emperor_absolute_dir;
void emperor_send_stats(int);
struct uwsgi_instance {
struct uwsgi_instance *ui_prev;
struct uwsgi_instance *ui_next;
@@ -32,6 +34,9 @@ struct uwsgi_instance {
int loyal;
int zerg;
uid_t uid;
gid_t gid;
};
@@ -169,19 +174,26 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
void emperor_add(char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
struct uwsgi_instance *c_ui = ui;
struct uwsgi_instance *n_ui = NULL;
pid_t pid;
char **argv;
char **vassal_argv;
char *uef;
char **uenvs;
int counter;
char *colon = NULL;
int i;
sleep(1);
usleep(uwsgi.emperor_throttle*1000);
if (uwsgi.emperor_tyrant) {
if (uid == 0 || gid == 0) {
uwsgi_log("[emperor-tyrant] invalid permissions for file %s\n", name);
return;
}
}
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
@@ -209,6 +221,8 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
memcpy(n_ui->name, name, strlen(name));
n_ui->born = born;
n_ui->uid = uid;
n_ui->gid = gid;
n_ui->last_mod = born;
// start without loyalty
n_ui->last_loyal = born;
@@ -253,6 +267,24 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
}
else {
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
if (setgid(gid)) {
uwsgi_error("setgid()");
exit(1);
}
if (setgroups(0, NULL)) {
uwsgi_error("setgroups()");
exit(1);
}
if (setuid(uid)) {
uwsgi_error("setuid()");
exit(1);
}
}
unsetenv("UWSGI_RELOADS");
unsetenv("NOTIFY_SOCKET");
@@ -308,9 +340,9 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
uct = uct->next;
}
argv = uwsgi_malloc(sizeof(char *) * counter);
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
argv[0] = uwsgi.binary_path;
vassal_argv[0] = uwsgi.binary_path;
if (uwsgi.emperor_broodlord) {
colon = strchr(name, ':');
@@ -319,29 +351,31 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
}
}
if (!strcmp(name + (strlen(name) - 4), ".xml"))
argv[1] = "--xml";
vassal_argv[1] = "--xml";
if (!strcmp(name + (strlen(name) - 4), ".ini"))
argv[1] = "--ini";
vassal_argv[1] = "--ini";
if (!strcmp(name + (strlen(name) - 4), ".yml"))
argv[1] = "--yaml";
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
argv[1] = "--yaml";
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 3), ".js"))
argv[1] = "--json";
vassal_argv[1] = "--json";
if (!strcmp(name + (strlen(name) - 5), ".json"))
vassal_argv[1] = "--json";
if (colon) {
colon[0] = ':';
}
argv[2] = name;
vassal_argv[2] = name;
counter = 3;
uct = uwsgi.vassals_templates;
while(uct) {
argv[counter] = "--inherit";
argv[counter+1] = uct->filename;
vassal_argv[counter] = "--inherit";
vassal_argv[counter+1] = uct->filename;
counter+=2;
uct = uct->next;
}
argv[counter] = NULL;
vassal_argv[counter] = NULL;
// close all of the unneded fd
for(i=3;i<sysconf(_SC_OPEN_MAX);i++) {
@@ -360,7 +394,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
}
// start !!!
if (execvp(argv[0], argv)) {
if (execvp(vassal_argv[0], vassal_argv)) {
uwsgi_error("execvp()");
}
uwsgi_log("is the uwsgi binary in your system PATH ?\n");
@@ -400,6 +434,8 @@ void emperor_loop() {
int interesting_fd;
char notification_message[64];
uwsgi.emperor_stats_fd = -1;
signal(SIGPIPE, SIG_IGN);
uwsgi_unix_signal(SIGINT, royal_death);
uwsgi_unix_signal(SIGTERM, royal_death);
@@ -420,6 +456,23 @@ void emperor_loop() {
uwsgi_log("*** starting uWSGI Emperor ***\n");
}
if (uwsgi.emperor_stats) {
char *tcp_port = strchr(uwsgi.emperor_stats, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
uwsgi.emperor_stats_fd = bind_to_tcp(uwsgi.emperor_stats, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
uwsgi.emperor_stats_fd = bind_to_unix(uwsgi.emperor_stats, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
event_queue_add_fd_read(emperor_queue, uwsgi.emperor_stats_fd);
uwsgi_log("*** Emperor stats server enabled on %s fd: %d ***\n", uwsgi.emperor_stats, uwsgi.emperor_stats_fd);
}
amqp_port = strchr(uwsgi.emperor_dir, ':');
if (amqp_port) {
@@ -517,7 +570,7 @@ reconnect:
}
else {
if (msgsize > 0) {
emperor_add(config_file, time(NULL), config, msgsize);
emperor_add(config_file, time(NULL), config, msgsize, 0, 0);
}
}
@@ -554,13 +607,18 @@ reconnect:
emperor_respawn(ui_current, time(NULL));
}
else {
emperor_add(config_file, time(NULL), NULL, 0);
emperor_add(config_file, time(NULL), NULL, 0, 0, 0);
}
free(config_file);
}
}
}
else if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1) {
if (interesting_fd == uwsgi.emperor_stats_fd) {
emperor_send_stats(uwsgi.emperor_stats_fd);
}
}
else {
ui_current = emperor_get_by_fd(interesting_fd);
if (ui_current) {
@@ -583,7 +641,7 @@ reconnect:
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
char *zerg_name = uwsgi_concat3(ui_current->name,":","zerg");
emperor_add(zerg_name, time(NULL), NULL, 0);
emperor_add(zerg_name, time(NULL), NULL, 0, ui_current->uid, ui_current->gid);
free(zerg_name);
}
}
@@ -604,7 +662,8 @@ reconnect:
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".ini") ||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".yml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".yaml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 3), ".js")
!strcmp(de->d_name + (strlen(de->d_name) - 3), ".js") ||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".json")
) {
@@ -620,13 +679,21 @@ reconnect:
ui_current = emperor_get(de->d_name);
if (ui_current) {
// check if uid or gid are changed, in such case, sotp the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
emperor_stop(ui_current);
continue;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(de->d_name, st.st_mtime, NULL, 0);
emperor_add(de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
}
@@ -643,6 +710,7 @@ reconnect:
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".ini") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".yml") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 3), ".js") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".json") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".yaml")
) {
@@ -659,13 +727,21 @@ reconnect:
ui_current = emperor_get(g.gl_pathv[i]);
if (ui_current) {
// check if uid or gid are changed, in such case, sotp the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
emperor_stop(ui_current);
continue;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0);
emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
@@ -729,7 +805,7 @@ reconnect:
}
else {
// UNSAFE
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len);
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
emperor_del(ui_current);
}
break;
@@ -748,3 +824,72 @@ reconnect:
}
}
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
void emperor_send_stats(int fd) {
struct sockaddr_un client_src;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
stats_send("\"emperor\": \"%s\",\n", uwsgi.emperor_dir);
fprintf(output,"\"emperor_tyrant\": %d,\n", uwsgi.emperor_tyrant);
fprintf(output, "\"vassals\": [\n");
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
fprintf(output,"\t{");
stats_send("\"id\": \"%s\", ", c_ui->name);
fprintf(output,"\"pid\": %d, ", (int) c_ui->pid);
stats_send_llu( "\"born\": %llu, ", c_ui->born);
stats_send_llu( "\"last_mod\": %llu, ", c_ui->last_mod);
fprintf(output,"\"loyal\": %d, ", c_ui->loyal);
fprintf(output,"\"zerg\": %d, ", c_ui->zerg);
fprintf(output,"\"uid\": %d, ", (int)c_ui->uid);
fprintf(output,"\"gid\": %d, ", (int)c_ui->gid);
stats_send_llu( "\"respawns\": %llu ", c_ui->respawns);
c_ui = c_ui->ui_next;
if (c_ui) {
fprintf(output,"},\n");
}
else {
fprintf(output,"}\n");
}
}
fprintf(output,"]}\n");
fclose(output);
}
+17 -5
View File
@@ -81,7 +81,7 @@ void *event_queue_alloc(int nevents) {
int event_queue_interesting_fd(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
return (int) pe[id].portev_user;
return (long) pe[id].portev_user;
}
return (int) pe[id].portev_object;
@@ -149,7 +149,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
*interesting_fd = (int) pe.portev_user;
*interesting_fd = (long) pe.portev_user;
}
else {
*interesting_fd = (int) pe.portev_object;
@@ -327,11 +327,13 @@ int event_queue_fd_write_to_read(int eq, int fd) {
struct kevent kev;
#ifndef __FreeBSD__
EV_SET(&kev, fd, EVFILT_WRITE, EV_DISABLE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
#endif
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
@@ -476,7 +478,7 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
fo.fo_ctime = st.st_ctim;
fmon_id++;
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) fmon_id)) {
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) (long) fmon_id)) {
uwsgi_error("port_associate()");
return -1;
}
@@ -506,7 +508,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
fo.fo_atime = st.st_atim;
fo.fo_mtime = st.st_mtim;
fo.fo_ctime = st.st_ctim;
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)id)) {
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)(long)id)) {
uwsgi_error("port_associate()");
return NULL;
}
@@ -687,13 +689,23 @@ enum
static int timerfd_create (clockid_t __clock_id, int __flags) {
#ifdef __amd64__
return syscall(283, __clock_id, __flags);
#elif defined(__i386__)
return syscall(322, __clock_id, __flags);
#else
return -1;
#endif
}
static int timerfd_settime (int __ufd, int __flags,
__const struct itimerspec *__utmr,
struct itimerspec *__otmr) {
#ifdef __amd64__
return syscall(286, __ufd, __flags, __utmr, __otmr);
#elif defined(__i386__)
return syscall(325, __ufd, __flags, __utmr, __otmr);
#endif
}
#endif
@@ -765,7 +777,7 @@ int event_queue_add_timer(int eq, int *id, int sec) {
timer_id++;
pnotif.portnfy_port = eq;
pnotif.portnfy_user = (void *) timer_id;
pnotif.portnfy_user = (void *) (long) timer_id;
sigev.sigev_notify = SIGEV_PORT;
sigev.sigev_value.sival_ptr = &pnotif;
+7
View File
@@ -0,0 +1,7 @@
use POSIX;
open CONFIG,'welcome.ini';
dup2(fileno(CONFIG), 17);
exec './uwsgi','--ini','fd://17';
+15 -4
View File
@@ -47,7 +47,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
}
}
gw_pid = fork();
gw_pid = uwsgi_fork(name);
if (gw_pid < 0) {
uwsgi_error("fork()");
return NULL;
@@ -60,6 +60,11 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
uwsgi_error("prctl()");
}
#endif
if (!uwsgi.sockets) {
// wait for child end
//waitpid(-1, &i, 0);
}
loop();
// never here !!! (i hope)
exit(1);
@@ -85,7 +90,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
ug->loop = loop;
ug->num = num;
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
uwsgi.gateways_cnt++;
@@ -98,7 +103,7 @@ void gateway_respawn(int id) {
pid_t gw_pid;
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
gw_pid = fork();
gw_pid = uwsgi_fork(ug->name);
if (gw_pid < 0) {
uwsgi_error("fork()");
return;
@@ -117,6 +122,12 @@ void gateway_respawn(int id) {
}
ug->pid = gw_pid;
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
ug->respawns++;
if (ug->respawns == 1) {
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
else {
uwsgi_log( "respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
}
+3 -2
View File
@@ -1,5 +1,6 @@
import uwsgi
uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
#uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return "<h1>Hello World</h1>"
yield str(env['wsgi.input'].fileno())
yield "<h1>Hello World</h1>"
+1 -1
View File
@@ -92,7 +92,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
char *section_asked = "uwsgi";
char *colon;
if (!uwsgi_startswith(file, "http://", 7)) {
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
+9 -5
View File
@@ -30,7 +30,7 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
char *colon;
int i;
if (!uwsgi_startswith(file, "http://", 7)) {
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
@@ -49,7 +49,11 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
#ifdef JANSSON_MAJOR_VERSION
root = json_loads(json_data, 0, &error);
#else
root = json_loads(json_data, &error);
#endif
if (!root) {
uwsgi_log("error parsing JSON data: line %d %s\n", error.line, error.text);
@@ -73,10 +77,10 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
add_exported_option((char *)key, (char *) json_string_value(config_value), 0);
}
else if (json_is_true(config_value)) {
add_exported_option((char *)key, (char *) "1", 0);
add_exported_option((char *)key, strdup("1"), 0);
}
else if (json_is_false(config_value) || json_is_null(config_value)) {
add_exported_option((char *)key, (char *) "0", 0);
add_exported_option((char *)key, strdup("0"), 0);
}
else if (json_is_integer(config_value)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_value)), 0);
@@ -88,10 +92,10 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
add_exported_option((char *)key, (char *) json_string_value(config_array_item), 0);
}
else if (json_is_true(config_array_item)) {
add_exported_option((char *)key, (char *) "1", 0);
add_exported_option((char *)key, strdup("1"), 0);
}
else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
add_exported_option((char *)key, (char *) "0", 0);
add_exported_option((char *)key, strdup("0"), 0);
}
else if (json_is_integer(config_array_item)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
+1 -1
View File
@@ -19,7 +19,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+1 -1
View File
@@ -18,7 +18,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+1
View File
@@ -46,6 +46,7 @@ void uwsgi_lock(void *lock) {
void uwsgi_unlock(void *lock) {
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
void uwsgi_rwlock_init(void *lock) {
+19 -18
View File
@@ -50,7 +50,7 @@ void log_request(struct wsgi_request *wsgi_req) {
if (wsgi_req->do_not_log) return ;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi.apps[wsgi_req->app_id];
wi = &uwsgi_apps[wsgi_req->app_id];
if (wi->requests > 0) {
app_req = wi->requests;
}
@@ -129,22 +129,22 @@ void log_request(struct wsgi_request *wsgi_req) {
rlen = writev(2, logvec, logvecpos+1);
}
void get_memusage() {
void get_memusage(uint64_t *rss, uint64_t *vsz) {
#ifdef UNBIT
uwsgi.workers[uwsgi.mywid].vsz_size = syscall(356);
*vsz = syscall(356);
#elif defined(__linux__)
FILE *procfile;
int i;
procfile = fopen("/proc/self/stat", "r");
if (procfile) {
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &uwsgi.workers[uwsgi.mywid].rss_size);
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
if (i != 2) {
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
}
fclose(procfile);
}
uwsgi.workers[uwsgi.mywid].rss_size = uwsgi.workers[uwsgi.mywid].rss_size * uwsgi.page_size;
*rss = *rss * uwsgi.page_size;
#elif defined (__sun__)
psinfo_t info;
int procfd;
@@ -152,8 +152,8 @@ void get_memusage() {
procfd = open("/proc/self/psinfo", O_RDONLY);
if (procfd >= 0) {
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024;
uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024;
*rss = (uint64_t) info.pr_rssize * 1024;
*vsz = (uint64_t) info.pr_size * 1024;
}
close(procfd);
}
@@ -164,8 +164,8 @@ void get_memusage() {
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size;
uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size;
*rss = t_info.resident_size;
*vsz = t_info.virtual_size;
}
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
kvm_t *kv;
@@ -184,8 +184,8 @@ void get_memusage() {
struct kinfo_proc *kproc;
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
if (kproc && cnt > 0) {
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
*vsz = kproc->ki_size;
*rss = kproc->ki_rssize * uwsgi.page_size;
}
#elif defined(__NetBSD__) || defined(__OpenBSD__)
struct kinfo_proc2 *kproc2;
@@ -193,11 +193,11 @@ void get_memusage() {
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
if (kproc2 && cnt > 0) {
#ifdef __OpenBSD__
uwsgi.workers[uwsgi.mywid].vsz_size = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
*vsz = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
#else
uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
*vsz = kproc2->p_vm_msize * uwsgi.page_size;
#endif
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
*rss = kproc2->p_vm_rssize * uwsgi.page_size;
}
#endif
@@ -207,13 +207,14 @@ void get_memusage() {
area_info ai;
int32 cookie;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
*vsz = 0;
*rss = 0;
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
uwsgi.workers[uwsgi.mywid].vsz_size += ai.ram_size;
*vsz += ai.ram_size;
if ( (ai.protection & B_WRITE_AREA) != 0) {
uwsgi.workers[uwsgi.mywid].rss_size += ai.ram_size;
*rss += ai.ram_size;
}
}
#endif
}
+366 -48
View File
@@ -117,7 +117,7 @@ void uwsgi_subscribe(char *subscription) {
if (lines[i] == 0) {
if (keysize > 0) {
if (key[0] != '#' && key[0] != '\n') {
modifier1 = strchr(key, ':');
modifier1 = strchr(key, ',');
if (modifier1) {
modifier1[0] = 0;
modifier1++;
@@ -135,7 +135,7 @@ void uwsgi_subscribe(char *subscription) {
if (keysize > 0) {
if (key[0] != '#' && key[0] != '\n') {
lines[i] = 0;
modifier1 = strchr(key, ':');
modifier1 = strchr(key, ',');
if (modifier1) {
modifier1[0] = 0;
modifier1++;
@@ -159,7 +159,7 @@ void uwsgi_subscribe(char *subscription) {
}
}
else {
modifier1 = strchr(subscription_key+1, ':');
modifier1 = strchr(subscription_key+1, ',');
if (modifier1) {
modifier1[0] = 0;
modifier1++;
@@ -168,7 +168,7 @@ void uwsgi_subscribe(char *subscription) {
uwsgi_send_subscription(udp_address, subscription_key+1, strlen(subscription_key+1), modifier1, modifier1_len);
if (modifier1)
modifier1[-1] = ':';
modifier1[-1] = ',';
}
clear:
@@ -238,7 +238,7 @@ void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t val
}
}
void master_loop(char **argv, char **environ) {
int master_loop(char **argv, char **environ) {
uint64_t tmp_counter;
@@ -284,15 +284,28 @@ void master_loop(char **argv, char **environ) {
#ifdef UWSGI_SNMP
int snmp_fd = -1;
#endif
int i=0;
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();
if (uwsgi.procname_master) {
uwsgi_set_processname(uwsgi.procname_master);
}
else if (uwsgi.procname) {
uwsgi_set_processname(uwsgi.procname);
}
else if (uwsgi.auto_procname) {
uwsgi_set_processname("uWSGI master");
}
uwsgi.current_time = time(NULL);
uwsgi_unix_signal(SIGHUP, grace_them_all);
@@ -318,6 +331,15 @@ void master_loop(char **argv, char **environ) {
#endif
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
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
}
#endif
if (uwsgi.log_master) {
#ifdef UWSGI_DEBUG
uwsgi_log("adding %d to master logging\n", uwsgi.shared->worker_log_pipe[0]);
@@ -337,6 +359,23 @@ void master_loop(char **argv, char **environ) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.zerg_server_fd);
uwsgi_log("*** Zerg server enabled on %s ***\n", uwsgi.zerg_server);
}
if (uwsgi.stats) {
char *tcp_port = strchr(uwsgi.stats, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
uwsgi.stats_fd = bind_to_tcp(uwsgi.stats, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
uwsgi.stats_fd = bind_to_unix(uwsgi.stats, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.stats_fd);
uwsgi_log("*** Stats server enabled on %s fd: %d ***\n", uwsgi.stats, uwsgi.stats_fd);
}
#ifdef UWSGI_UDP
if (uwsgi.udp_socket) {
udp_fd = bind_to_udp(uwsgi.udp_socket, 0, 0);
@@ -351,6 +390,9 @@ void master_loop(char **argv, char **environ) {
if (uwsgi.cheap) {
uwsgi_add_sockets_to_queue(uwsgi.master_queue);
for(i=1;i<=uwsgi.numproc;i++) {
uwsgi.workers[i].cheaped = 1;
}
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
}
@@ -450,10 +492,12 @@ void master_loop(char **argv, char **environ) {
#endif
/*
*/
// spawn mules
for(i=0;i<uwsgi.mules_cnt;i++) {
size_t mule_patch_size = 0;
uwsgi.mules[i].patch = uwsgi_string_get_list(&uwsgi.mules_patches, i, &mule_patch_size);
uwsgi_mule(i+1);
}
// spawn fat gateways
for(i=0;i<uwsgi.gateways_cnt;i++) {
@@ -463,9 +507,10 @@ void master_loop(char **argv, char **environ) {
}
// first subscription
for(i=0;i<uwsgi.subscriptions_cnt;i++) {
uwsgi_log("requested subscription for %s\n", uwsgi.subscriptions[i]);
uwsgi_subscribe(uwsgi.subscriptions[i]);
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while(subscriptions) {
uwsgi_subscribe(subscriptions->value);
subscriptions = subscriptions->next;
}
// sync the cache store if needed
@@ -476,30 +521,53 @@ void master_loop(char **argv, char **environ) {
}
if (uwsgi.queue_store && uwsgi.queue_filesize) {
if (msync(uwsgi.queue, uwsgi.queue_filesize, MS_ASYNC)) {
if (msync(uwsgi.queue_header, uwsgi.queue_filesize, MS_ASYNC)) {
uwsgi_error("msync()");
}
}
if (uwsgi.touch_reload) {
struct uwsgi_string_list *touch_reload = uwsgi.touch_reload;
while(touch_reload) {
struct stat tr_st;
if (stat(uwsgi.touch_reload, &tr_st)) {
uwsgi_error("stat()");
uwsgi_log("unable to stat() %s, touch-reload will be disabled\n", uwsgi.touch_reload);
uwsgi.touch_reload = NULL;
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;
}
else {
uwsgi.last_touch_reload_mtime = tr_st.st_mtime;
touch_reload->custom = (uint64_t) tr_st.st_mtime;
}
touch_reload = touch_reload->next;
}
for (;;) {
//uwsgi_log("ready_to_reload %d %d\n", ready_to_reload, uwsgi.numproc);
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->master_cycle) {
uwsgi.gp[i]->master_cycle();
}
}
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->master_cycle) {
uwsgi.p[i]->master_cycle();
}
}
if (uwsgi.to_outworld) {
//uwsgi_log("%d/%d\n", uwsgi.lazy_respawned, uwsgi.numproc);
if (uwsgi.lazy_respawned >= uwsgi.numproc) {
uwsgi.to_outworld = 0;
uwsgi.master_mercy = 0;
uwsgi.lazy_respawned = 0;
}
}
if (uwsgi.master_mercy) {
if (uwsgi.master_mercy < time(NULL)) {
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0) {
if (uwsgi.lazy && uwsgi.workers[i].destroy == 0) continue;
uwsgi_log("worker %d (pid: %d) is taking too much time to die...NO MERCY !!!\n", i, uwsgi.workers[i].pid);
if (!kill(uwsgi.workers[i].pid, SIGKILL)) {
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
@@ -508,17 +576,22 @@ void master_loop(char **argv, char **environ) {
uwsgi.workers[i].pid = 0;
if (uwsgi.to_hell) { ready_to_die++;}
else if (uwsgi.to_heaven) { ready_to_reload++;}
else if (uwsgi.to_outworld) {
uwsgi.lazy_respawned++;
if (uwsgi_respawn_worker(i)) return 0;
}
}
else {
uwsgi_error("kill()");
}
}
}
uwsgi.master_mercy = 0;
}
}
if (uwsgi.respawn_workers) {
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi_respawn_worker(i)) return;
if (uwsgi_respawn_worker(i)) return 0;
}
uwsgi.respawn_workers = 0;
@@ -546,9 +619,74 @@ void master_loop(char **argv, char **environ) {
uwsgi.restore_snapshot = 0;
continue;
}
// cheaper management
if (uwsgi.cheaper) {
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) {
if (overload_count > 3) {
// activate the first available worker
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;
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.cheap || ready_to_die >= uwsgi.numproc) && uwsgi.to_hell) {
// call a series of waitpid to ensure all processes (gateways and daemons) are dead
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt);i++) {
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt+uwsgi.mules_cnt);i++) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
@@ -556,8 +694,8 @@ void 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 and daemons) are dead
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt);i++) {
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt+uwsgi.mules_cnt);i++) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
@@ -576,6 +714,7 @@ void master_loop(char **argv, char **environ) {
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) {
@@ -593,6 +732,13 @@ void master_loop(char **argv, char **environ) {
}
}
}
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);
@@ -602,6 +748,9 @@ void master_loop(char **argv, char **environ) {
}
}
#ifdef UWSGI_AS_SHARED_LIBRARY
return -1;
#else
uwsgi_log( "running %s\n", uwsgi.binary_path);
argv[0] = uwsgi.binary_path;
//strcpy (argv[0], uwsgi.binary_path);
@@ -609,6 +758,7 @@ void master_loop(char **argv, char **environ) {
uwsgi_error("execvp()");
// never here
exit(1);
#endif
}
if (!uwsgi.cheap) {
@@ -629,6 +779,16 @@ void master_loop(char **argv, char **environ) {
else {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
if (diedpid == -1) {
if (errno == ECHILD && uwsgi.cheaper) {
if (uwsgi.to_heaven) {
ready_to_reload = uwsgi.numproc;
continue;
}
else if (uwsgi.to_hell) {
ready_to_die = uwsgi.numproc;
continue;
}
}
uwsgi_error("waitpid()");
/* here is better to reload all the uWSGI stack */
uwsgi_log( "something horrible happened...\n");
@@ -738,11 +898,20 @@ void master_loop(char **argv, char **environ) {
else if (uwsgi.log_socket) {
sendto(uwsgi.log_socket_fd, log_buf, rlen, 0, &uwsgi.log_socket_addr->sa, uwsgi.log_socket_size);
}
else {
rlen = write(uwsgi.original_log_fd, log_buf, rlen);
}
// TODO allow uwsgi.logger = func
}
}
}
if (uwsgi.stats && uwsgi.stats_fd > -1) {
if (interesting_fd == uwsgi.stats_fd) {
uwsgi_send_stats(uwsgi.stats_fd);
}
}
if (uwsgi.zerg_server) {
if (interesting_fd == uwsgi.zerg_server_fd) {
struct sockaddr_un zsun;
@@ -829,7 +998,7 @@ void master_loop(char **argv, char **environ) {
uwsgi.cheap = 0;
uwsgi_del_sockets_from_queue(uwsgi.master_queue);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi_respawn_worker(i)) return;
if (uwsgi_respawn_worker(i)) return 0;
}
break;
}
@@ -999,23 +1168,75 @@ void master_loop(char **argv, char **environ) {
//uwsgi.workers[i].pipe[0] = -1;
}
}
#ifdef UWSGI_SPOOLER
// check for spooler signal
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
if (interesting_fd == uwsgi.shared->spooler_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 the spooler\n", uwsgi_signal);
#endif
uwsgi_route_signal(uwsgi_signal);
}
else {
uwsgi_log_verbose("lost connection with the spooler\n");
close(interesting_fd);
}
}
}
#endif
}
uwsgi.current_time = time(NULL);
// checking logsize
if (uwsgi.logfile) {
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
/*
if (uwsgi.shared->logsize > 8192) {
//uwsgi_log("logsize: %d\n", uwsgi.shared->logsize);
char *new_logfile = uwsgi_malloc(strlen(uwsgi.logfile) + 14 + 1);
memset(new_logfile, 0, strlen(uwsgi.logfile) + 14 + 1);
if (!rename(uwsgi.logfile, new_logfile)) {
// close 2, reopen logfile dup'it and gracefully reload workers;
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;
}
free(new_logfile);
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);
}
*/
}
@@ -1147,10 +1368,43 @@ void master_loop(char **argv, char **environ) {
uwsgi.workers[i].harakiri = 0;
}
}
// then for evil memory checkers
if (uwsgi.evil_reload_on_as) {
if ((rlim_t) uwsgi.workers[i].vsz_size >= uwsgi.evil_reload_on_as) {
uwsgi_log("*** EVIL RELOAD ON WORKER %d ADDRESS SPACE: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].vsz_size, uwsgi.workers[i].pid );
kill(uwsgi.workers[i].pid, SIGKILL);
uwsgi.workers[i].vsz_size = 0;
}
}
if (uwsgi.evil_reload_on_rss) {
if ((rlim_t) uwsgi.workers[i].rss_size >= uwsgi.evil_reload_on_rss) {
uwsgi_log("*** EVIL RELOAD ON WORKER %d RSS: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].rss_size, uwsgi.workers[i].pid );
kill(uwsgi.workers[i].pid, SIGKILL);
uwsgi.workers[i].rss_size = 0;
}
}
// need to find a better way
//uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time;
}
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].harakiri > 0) {
if (uwsgi.mules[i].harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON MULE %d HANDLING SIGNAL %d (pid: %d) ***\n", i+1, uwsgi.mules[i].signum, uwsgi.mules[i].pid );
kill(uwsgi.mules[i].pid, SIGKILL);
uwsgi.mules[i].harakiri = 0;
}
}
}
#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;
}
}
#endif
#ifdef UWSGI_UDP
// check for cluster nodes
@@ -1162,9 +1416,11 @@ void master_loop(char **argv, char **environ) {
}
// resubscribe every 10 cycles
if (uwsgi.subscriptions_cnt > 0 && ((uwsgi.master_cycles % 10) == 0 || uwsgi.master_cycles == 1)) {
for(i=0;i<uwsgi.subscriptions_cnt;i++) {
uwsgi_subscribe(uwsgi.subscriptions[i]);
if (uwsgi.subscriptions && ((uwsgi.master_cycles % 10) == 0 || uwsgi.master_cycles == 1)) {
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while(subscriptions) {
uwsgi_subscribe(subscriptions->value);
subscriptions = subscriptions->next;
}
}
@@ -1177,25 +1433,26 @@ void master_loop(char **argv, char **environ) {
}
if (uwsgi.queue_store && uwsgi.queue_filesize && uwsgi.queue_store_sync && ((uwsgi.master_cycles % uwsgi.queue_store_sync) == 0)) {
if (msync(uwsgi.queue, uwsgi.queue_filesize, MS_ASYNC)) {
if (msync(uwsgi.queue_header, uwsgi.queue_filesize, MS_ASYNC)) {
uwsgi_error("msync()");
}
}
// check touch_reload
if (uwsgi.touch_reload && !uwsgi.to_heaven && !uwsgi.to_hell) {
struct uwsgi_string_list *touch_reload = uwsgi.touch_reload;
while (touch_reload && !uwsgi.to_heaven && !uwsgi.to_hell) {
struct stat tr_st;
if (stat(uwsgi.touch_reload, &tr_st)) {
uwsgi_error("stat()");
uwsgi_log("unable to stat() %s, touch-reload will be disabled\n", uwsgi.touch_reload);
uwsgi.touch_reload = NULL;
if (stat(touch_reload->value, &tr_st)) {
touch_reload->custom = 0;
}
else {
if (tr_st.st_mtime > uwsgi.last_touch_reload_mtime) {
uwsgi_log("*** %s has been touched... grace them all !!! ***\n", uwsgi.touch_reload);
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;
}
@@ -1213,12 +1470,27 @@ void master_loop(char **argv, char **environ) {
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
if (diedpid == uwsgi.shared->spooler_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;
}
}
#endif
pid_found = 0;
for(i=0;i<uwsgi.mules_cnt;i++) {
if (uwsgi.mules[i].pid == diedpid) {
uwsgi_log("OOOPS mule %d crippled...trying respawn...\n", i+1);
uwsgi_mule(i+1);
pid_found = 1;
break;
}
}
if (pid_found) continue;
/* reload the gateways */
// TODO reload_gateway(diedpid);
pid_found = 0;
@@ -1259,6 +1531,37 @@ void master_loop(char **argv, char **environ) {
uwsgi.mywid = find_worker_id(diedpid);
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) {
uwsgi_log("spooler (pid: %d) annihilated\n", (int) diedpid);
goto next;
}
}
#endif
for(i=0;i<uwsgi.mules_cnt;i++) {
if (uwsgi.mules[i].pid == diedpid) {
uwsgi_log("mule %d (pid: %d) annihilated\n", i+1, (int) diedpid);
goto next;
}
}
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);
goto next;
}
}
for(i=0;i<uwsgi.shared->daemons_cnt;i++) {
if (uwsgi.shared->daemons[i].pid == diedpid) {
uwsgi_log("daemon %d (pid: %d) annihilated\n", i+1, (int) diedpid);
goto next;
}
}
if (WIFEXITED(waitpid_status)) {
uwsgi_log("subprocess %d exited with code %d\n", (int) diedpid, WEXITSTATUS(waitpid_status));
}
@@ -1268,10 +1571,12 @@ void master_loop(char **argv, char **environ) {
else if (WIFSTOPPED(waitpid_status)) {
uwsgi_log("subprocess %d stopped\n", (int) diedpid);
}
next:
continue;
}
else {
if (uwsgi.to_heaven) {
ready_to_reload++;
uwsgi.workers[uwsgi.mywid].pid = 0;
@@ -1286,11 +1591,24 @@ void master_loop(char **argv, char **environ) {
uwsgi.workers[uwsgi.mywid].harakiri = 0;
continue;
}
else if (uwsgi.to_outworld) {
uwsgi.lazy_respawned++;
uwsgi.workers[uwsgi.mywid].destroy = 0;
uwsgi.workers[uwsgi.mywid].pid = 0;
// only to be safe :P
uwsgi.workers[uwsgi.mywid].harakiri = 0;
}
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);
continue;
}
gettimeofday(&last_respawn, NULL);
if (last_respawn.tv_sec == uwsgi.respawn_delta) {
last_respawn_rate++;
@@ -1314,7 +1632,7 @@ void master_loop(char **argv, char **environ) {
continue;
}
*/
if (uwsgi_respawn_worker(uwsgi.mywid)) return;
if (uwsgi_respawn_worker(uwsgi.mywid)) return 0;
}
}
+189 -39
View File
@@ -2,6 +2,8 @@
extern struct uwsgi_server uwsgi;
void worker_wakeup() {}
void master_check_cluster_nodes() {
int i;
@@ -31,71 +33,107 @@ void master_check_cluster_nodes() {
}
}
void uwsgi_fixup_fds(int wid, int muleid) {
int i;
// close the cache server
if (uwsgi.cache_server_fd != -1) {
close(uwsgi.cache_server_fd);
}
if (uwsgi.master_process) {
// fix the communication pipe
close(uwsgi.shared->worker_signal_pipe[0]);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].signal_pipe[0] != -1) close(uwsgi.workers[i].signal_pipe[0]);
if (i != wid) {
if (uwsgi.workers[i].signal_pipe[1] != -1) close(uwsgi.workers[i].signal_pipe[1]);
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.shared->spooler_pid != getpid()) {
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
if (uwsgi.shared->spooler_signal_pipe[1] != -1) close (uwsgi.shared->spooler_signal_pipe[1]);
}
#endif
if (uwsgi.shared->mule_signal_pipe[0] != -1) close(uwsgi.shared->mule_signal_pipe[0]);
if (muleid == 0) {
if (uwsgi.shared->mule_signal_pipe[1] != -1) close(uwsgi.shared->mule_signal_pipe[1]);
if (uwsgi.shared->mule_queue_pipe[1] != -1) close(uwsgi.shared->mule_queue_pipe[1]);
}
for(i=0;i<uwsgi.mules_cnt;i++) {
if (uwsgi.mules[i].signal_pipe[0] != -1) close(uwsgi.mules[i].signal_pipe[0]);
if (muleid != i+1) {
if (uwsgi.mules[i].signal_pipe[1] != -1) close(uwsgi.mules[i].signal_pipe[1]);
if (uwsgi.mules[i].queue_pipe[1] != -1) close(uwsgi.mules[i].queue_pipe[1]);
}
}
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi.farms[i].signal_pipe[0] != -1) close(uwsgi.farms[i].signal_pipe[0]);
if (muleid == 0) {
if (uwsgi.farms[i].signal_pipe[1] != -1) close(uwsgi.farms[i].signal_pipe[1]);
if (uwsgi.farms[i].queue_pipe[1] != -1) close(uwsgi.farms[i].queue_pipe[1]);
}
}
}
}
int uwsgi_respawn_worker(int wid) {
int respawns = uwsgi.workers[wid].respawn_count;
int i;
if (uwsgi.master_process) {
if (uwsgi.signal_pipe[wid][0] != -1) close(uwsgi.signal_pipe[wid][0]);
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.signal_pipe[wid])) {
uwsgi_error("socketpair()\n");
}
}
pid_t pid = fork();
pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
if (pid == 0) {
signal(SIGWINCH, worker_wakeup);
uwsgi.mywid = wid;
uwsgi.mypid = getpid();
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].requests = 0;
uwsgi.workers[uwsgi.mywid].failed_requests = 0;
// do not reset worker counters on reload !!!
//uwsgi.workers[uwsgi.mywid].requests = 0;
//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
uwsgi.workers[uwsgi.mywid].cheaped = 0;
uwsgi.workers[uwsgi.mywid].busy = 0;
uwsgi.workers[uwsgi.mywid].sig = 0;
// close the cache server
if (uwsgi.cache_server_fd != -1) {
close(uwsgi.cache_server_fd);
}
// reset the apps count with a copy from the master
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
uwsgi_fixup_fds(wid, 0);
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
if (uwsgi.master_process) {
// fix the communication pipe
close(uwsgi.shared->worker_signal_pipe[0]);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.signal_pipe[i][0] != -1) {
close(uwsgi.signal_pipe[i][0]);
}
}
uwsgi.my_signal_socket = uwsgi.signal_pipe[wid][1];
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
}
#endif
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
}
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
}
}
return 1;
}
else if (pid < 1) {
uwsgi_error("fork()");
}
else {
if (uwsgi.master_process) {
close(uwsgi.signal_pipe[wid][1]);
}
if (respawns > 0) {
uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
}
@@ -257,3 +295,115 @@ void uwsgi_manage_command_cron(time_t now) {
}
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
void uwsgi_send_stats(int fd) {
int i,j;
struct sockaddr_un client_src;
struct uwsgi_app *ua;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
#ifdef __linux__
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
#endif
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
fprintf(output, "\"workers\": [\n");
for (i = 0; i < uwsgi.numproc; i++) {
fprintf(output,"\t{");
fprintf(output,"\"id\": %d, ", uwsgi.workers[i+1].id);
fprintf(output,"\"pid\": %d, ", (int) uwsgi.workers[i+1].pid);
stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i+1].requests);
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i+1].exceptions);
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i+1].signals);
if (uwsgi.workers[i + 1].cheaped) {
fprintf(output,"\"status\": \"cheap\", ");
}
else {
if (uwsgi.workers[i + 1].sig) {
fprintf(output,"\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
}
else if (uwsgi.workers[i + 1].busy) {
fprintf(output,"\"status\": \"busy\", ");
}
else {
fprintf(output,"\"status\": \"idle\", ");
}
}
stats_send_llu("\"rss\": %llu, ", uwsgi.workers[i+1].rss_size);
stats_send_llu("\"vsz\": %llu, ", uwsgi.workers[i+1].vsz_size);
stats_send_llu("\"running_time\": %llu, ", uwsgi.workers[i+1].running_time);
stats_send_llu("\"last_spawn\": %llu, ", uwsgi.workers[i+1].last_spawn);
stats_send_llu("\"respawn_count\": %llu, ", uwsgi.workers[i+1].respawn_count);
stats_send_llu("\"tx\": %llu, ", uwsgi.workers[i+1].tx);
stats_send_llu("\"avg_rt\": %llu, ", uwsgi.workers[i+1].avg_response_time);
fprintf(output,"\"apps\": [\n");
for(j=0;j<uwsgi.workers[i+1].apps_cnt;j++) {
ua = &uwsgi.workers[i+1].apps[j];
fprintf(output,"\t\t{ ");
fprintf(output, "\"id\": %d, ", j);
fprintf(output, "\"modifier1\": %d, ", ua->modifier1);
fprintf(output, "\"mountpoint\": \"%.*s\", ", ua->mountpoint_len, ua->mountpoint);
stats_send_llu( "\"requests\": %llu, ", ua->requests);
stats_send_llu( "\"exceptions\": %llu, ", ua->exceptions);
if (ua->chdir) {
fprintf(output, "\"chdir\": \"%s\", ", ua->chdir);
}
else {
fprintf(output, "\"chdir\": \"\" ");
}
if (j == uwsgi.workers[i+1].apps_cnt-1) {
fprintf(output,"}\n");
}
else {
fprintf(output,"},\n");
}
}
fprintf(output,"\t\t]");
if (i == uwsgi.numproc-1) {
fprintf(output,"}\n");
}
else {
fprintf(output,"},\n");
}
}
fprintf(output,"]}\n");
fclose(output);
}
+235
View File
@@ -0,0 +1,235 @@
/*
uWSGI mules are very simple workers only managing signals or running custom code in background.
By default they born in signal-only mode, but if you patch them (passing the script/code to run) they will became fully customized daemons.
*/
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_mule_handler(void);
void uwsgi_mule(int id) {
int i;
pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
if (pid == 0) {
uwsgi.muleid = id;
// avoid race conditions
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = getpid();
uwsgi_fixup_fds(0, id);
uwsgi.my_signal_socket = uwsgi.mules[id-1].signal_pipe[1];
uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];
uwsgi_close_all_sockets();
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
if (uwsgi.mules[id-1].patch) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
// never here
break;
}
}
}
}
uwsgi_mule_handler();
}
else if (pid > 0) {
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = pid;
uwsgi_log("spawned uWSGI mule %d (pid: %d)\n", id, (int) pid);
}
}
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
struct uwsgi_mule_farm *umf = farm->mules;
while(umf) {
if (umf->mule->id == muleid) {
return 1;
}
umf = umf->next;
}
return 0;
}
int farm_has_signaled(int fd) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while(umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].signal_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
return 0;
}
int farm_has_msg(int fd) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while(umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].queue_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
return 0;
}
void uwsgi_mule_add_farm_to_queue(int queue) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
event_queue_add_fd_read(queue, uwsgi.farms[i].signal_pipe[1]);
event_queue_add_fd_read(queue, uwsgi.farms[i].queue_pipe[1]);
}
}
}
void uwsgi_mule_handler() {
ssize_t len;
uint8_t uwsgi_signal;
int rlen;
int interesting_fd;
// this must be configurable
char message[65536];
int mule_queue = event_queue_init();
event_queue_add_fd_read(mule_queue, uwsgi.signal_socket);
event_queue_add_fd_read(mule_queue, uwsgi.my_signal_socket);
event_queue_add_fd_read(mule_queue, uwsgi.mules[uwsgi.muleid-1].queue_pipe[1]);
event_queue_add_fd_read(mule_queue, uwsgi.shared->mule_queue_pipe[1]);
uwsgi_mule_add_farm_to_queue(mule_queue);
for(;;) {
rlen = event_queue_wait(mule_queue, -1, &interesting_fd);
if (rlen <= 0) {
continue;
}
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
}
}
else if (interesting_fd == uwsgi.mules[uwsgi.muleid-1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
len = read(interesting_fd, message, 65536);
if (len < 0) {
uwsgi_error("read()");
}
else {
int i,found = 0;
for(i=0;i<0xff;i++) {
if (uwsgi.p[i]->mule_msg) {
if (uwsgi.p[i]->mule_msg(message, len)) {
found = 1;
break;
}
}
}
if (!found)
uwsgi_log("*** mule %d received a %d bytes message ***\n", uwsgi.muleid, len);
}
}
}
}
struct uwsgi_mule *get_mule_by_id(int id) {
int i;
for(i=0;i<uwsgi.mules_cnt;i++) {
if (uwsgi.mules[i].id == id) {
return &uwsgi.mules[i];
}
}
return NULL;
}
struct uwsgi_farm *get_farm_by_name(char *name) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (!strcmp(uwsgi.farms[i].name, name)) {
return &uwsgi.farms[i];
}
}
return NULL;
}
struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **umf, struct uwsgi_mule *um) {
struct uwsgi_mule_farm *uwsgi_mf = *umf, *old_umf;
if (!uwsgi_mf) {
*umf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
uwsgi_mf = *umf;
}
else {
while(uwsgi_mf) {
old_umf = uwsgi_mf;
uwsgi_mf = uwsgi_mf->next;
}
uwsgi_mf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
old_umf->next = uwsgi_mf;
}
uwsgi_mf->mule = um;
uwsgi_mf->next = NULL;
return uwsgi_mf;
}
+26 -26
View File
@@ -95,7 +95,7 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
char buffer[0xffff];
char *argv[0xff] ;
int argc;
int argc = 0;
uint16_t ret;
ei_x_buff xr;
@@ -103,19 +103,20 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
ei_get_type(x->buff, &x->index, &etype, &esize);
#ifdef UWSGI_DEBUG
uwsgi_log("%d %c %c %c\n", etype, etype, ERL_SMALL_TUPLE_EXT, ERL_LARGE_TUPLE_EXT);
#endif
if (etype != ERL_SMALL_TUPLE_EXT && etype != ERL_LARGE_TUPLE_EXT) return;
uwsgi_log("decode tuple\n");
ei_decode_tuple_header(x->buff, &x->index, &arity);
#ifdef UWSGI_DEBUG
uwsgi_log("rpc arity %d\n", arity);
#endif
if (arity != 3) return ;
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c\n", etype, etype);
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
gen_call = uwsgi_malloc(esize);
@@ -127,7 +128,9 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
ei_decode_string(x->buff, &x->index, gen_call);
}
#ifdef UWSGI_DEBUG
uwsgi_log("gen call = %s\n", gen_call);
#endif
ei_get_type(x->buff, &x->index, &etype, &esize);
@@ -138,13 +141,10 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
ei_get_type(x->buff, &x->index, &etype, &esize);
ei_skip_term(x->buff, &x->index);
uwsgi_log("skip0 %d %c\n", etype, etype);
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("skip1 %d %c\n", etype, etype);
ei_decode_ref(x->buff, &x->index, &eref);
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c\n", etype, etype);
module = uwsgi_malloc(esize);
@@ -157,17 +157,16 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c\n", etype, etype);
if (etype != ERL_SMALL_TUPLE_EXT) return ;
ei_decode_tuple_header(x->buff, &x->index, &arity);
#ifdef UWSGI_DEBUG
uwsgi_log("arity: %d\n", arity);
#endif
if (arity != 5) return ;
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c\n", etype, etype);
char *method = uwsgi_malloc(esize);
@@ -181,7 +180,6 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
if (strcmp(method, "call")) return;
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c\n", etype, etype);
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
@@ -207,7 +205,9 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
ei_decode_string(x->buff, &x->index, call);
}
#ifdef UWSGI_DEBUG
uwsgi_log("RPC %s %s\n", module, call);
#endif
ei_get_type(x->buff, &x->index, &etype, &esize);
@@ -224,7 +224,9 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
ret = uwsgi_rpc(call, argc, argv, buffer);
#ifdef UWSGI_DEBUG
uwsgi_log("buffer: %.*s\n", ret, buffer);
#endif
ei_x_new_with_version(&xr);
@@ -247,7 +249,6 @@ void erlang_loop() {
int fd;
int eversion;
int i;
ei_x_buff x, xr;
@@ -286,7 +287,7 @@ void erlang_loop() {
if (em.msgtype == ERL_TICK)
continue;
uwsgi_log("From: %s To: %s RegName: %s\n", em.from.node, em.to.node, em.toname);
uwsgi_log("[erlang] message From: %s To (process): %s\n", em.from.node, em.toname);
@@ -300,20 +301,18 @@ void erlang_loop() {
uwsgi_erlang_rpc(fd, &em.from, &x);
}
else {
int uep = -1;
for(i=0;i<uerl.uep_cnt;i++) {
if (!strcmp(uerl.uep[i].name, em.toname)) {
uep = i;
struct uwsgi_erlang_process *uep = uerl.uep;
while(uep) {
if (!strcmp(uep->name, em.toname)) {
if (uep->plugin) {
uep->plugin(uep->func, &x);
}
break;
}
uep = uep->next;
}
if (uep > -1) {
if (uerl.uep[uep].plugin) {
uerl.uep[uep].plugin( uerl.uep[uep].func, &x );
}
}
else {
if (!uep) {
uwsgi_log("!!! unregistered erlang process requested, dumping it !!!\n");
dump_eterm(&x);
}
@@ -366,7 +365,6 @@ int erlang_init() {
if (uerl.name) {
uwsgi.master_process = 1;
host = strchr(uerl.name, '@');
@@ -422,10 +420,11 @@ int erlang_init() {
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
if (register_fat_gateway("erlang", erlang_loop) == NULL) {
if (register_fat_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
uwsgi_log("unable to register the erlang gateway\n");
exit(1);
}
}
return 0;
@@ -435,7 +434,8 @@ int erlang_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_ERLANG:
uerl.name = optarg;
uwsgi.master_process = 1;
uerl.name = optarg;
return 1;
case LONG_ARGS_ERLANG_COOKIE:
uerl.cookie = optarg;
+3 -4
View File
@@ -1,7 +1,5 @@
#include <ei.h>
#define MAX_UWSGI_ERLANG_PROCESSES 64
#define LONG_ARGS_ERLANG 17012
#define LONG_ARGS_ERLANG_COOKIE 17013
@@ -12,6 +10,8 @@ struct uwsgi_erlang_process {
char name[0xff];
void (*plugin)(void *, ei_x_buff *);
void *func;
struct uwsgi_erlang_process *next;
};
struct uwsgi_erlang {
@@ -24,7 +24,6 @@ struct uwsgi_erlang {
void *lock;
struct uwsgi_erlang_process uep[MAX_UWSGI_ERLANG_PROCESSES];
int uep_cnt;
struct uwsgi_erlang_process *uep;
};
+160 -28
View File
@@ -19,6 +19,7 @@
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER 150005
#define LONG_ARGS_FASTROUTER_TIMEOUT 150006
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT 150007
#define LONG_ARGS_FASTROUTER_USE_CODE_STRING 150008
#define FASTROUTER_STATUS_FREE 0
#define FASTROUTER_STATUS_CONNECTING 1
@@ -27,6 +28,8 @@
#define FASTROUTER_STATUS_RESPONSE 4
#define add_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+ufr.socket_timeout, x)
#define add_check_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+x, NULL)
#define del_check_timeout(x) rb_erase(&x->rbt, ufr.timeouts);
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
struct uwsgi_fastrouter_socket {
@@ -42,6 +45,8 @@ struct uwsgi_fastrouter {
int use_cache;
int nevents;
int queue;
int subscription_slot;
char *pattern;
@@ -51,11 +56,21 @@ struct uwsgi_fastrouter {
int base_len;
char *subscription_server;
struct uwsgi_dict *subscription_dict;
struct uwsgi_subscribe_slot *subscriptions;
int subscription_regexp;
int socket_timeout;
uint8_t code_string_modifier1;
char *code_string_code;
char *code_string_function;
struct rb_root *timeouts;
struct uwsgi_rb_timer *subscriptions_check;
int cheap;
int i_am_cheap;
} ufr;
@@ -90,9 +105,12 @@ struct option fastrouter_options[] = {
{"fastrouter-use-cache", no_argument, &ufr.use_cache, 1},
{"fastrouter-use-pattern", required_argument, 0, LONG_ARGS_FASTROUTER_USE_PATTERN},
{"fastrouter-use-base", required_argument, 0, LONG_ARGS_FASTROUTER_USE_BASE},
{"fastrouter-use-code-string", required_argument, 0, LONG_ARGS_FASTROUTER_USE_CODE_STRING},
{"fastrouter-events", required_argument, 0, LONG_ARGS_FASTROUTER_EVENTS},
{"fastrouter-cheap", no_argument, &ufr.cheap, 1},
{"fastrouter-subscription-server", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER},
{"fastrouter-subscription-slot", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT},
{"fastrouter-subscription-use-regexp", no_argument, &ufr.subscription_regexp, 1},
{"fastrouter-timeout", required_argument, 0, LONG_ARGS_FASTROUTER_TIMEOUT},
{0, 0, 0, 0},
};
@@ -124,7 +142,6 @@ struct fastrouter_session {
int status;
struct uwsgi_header uh;
uint8_t h_pos;
char buffer[0xffff];
uint16_t pos;
char *hostname;
@@ -135,23 +152,57 @@ struct fastrouter_session {
char *instance_address;
uint64_t instance_address_len;
struct uwsgi_subscriber_name *un;
struct uwsgi_subscribe_node *un;
int pass_fd;
struct uwsgi_rb_timer *timeout;
int instance_failed;
uint8_t modifier1;
char buffer[0xffff];
};
static void close_session(struct fastrouter_session **fr_table, struct fastrouter_session *fr_session) {
// check timeout expired
if (fr_session == NULL) {
if (ufr.subscription_server) {
//time_t current_time = time(NULL);
uwsgi_log("checking for node health\n");
struct uwsgi_subscribe_slot *slot = ufr.subscriptions;
while(slot) {
struct uwsgi_subscribe_node *node = slot->nodes;
while(node) {
uwsgi_log("%.*s (hits: %llu) %.*s\n", slot->keylen, slot->key, slot->hits, node->len, node->name);
node = node->next;
}
slot = slot->next;
}
del_check_timeout(ufr.subscriptions_check);
ufr.subscriptions_check = add_check_timeout(10);
}
return;
}
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
if (fr_session->instance_fd != -1) {
if (ufr.subscription_server && (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING)) {
uwsgi_log("marking %.*s as failed\n", (int) fr_session->instance_address_len,fr_session->instance_address);
fr_session->un->len = 0;
if (ufr.subscriptions && (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING)) {
if (fr_session->un && fr_session->un->len > 0) {
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
uwsgi_remove_subscribe_node(&ufr.subscriptions, fr_session->un);
if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 1;
}
}
}
close(fr_session->instance_fd);
fr_table[fr_session->instance_fd] = NULL;
@@ -176,7 +227,6 @@ static void expire_timeouts(struct fastrouter_session **fr_table) {
if (urbt->key <= current) {
close_session(fr_table, (struct fastrouter_session *)urbt->data);
uwsgi_log("timeout !!!\n");
continue;
}
@@ -216,7 +266,6 @@ struct fastrouter_session *alloc_fr_session() {
void fastrouter_loop() {
int fr_queue;
int nevents;
int interesting_fd;
int new_connection;
@@ -263,7 +312,7 @@ void fastrouter_loop() {
fr_table[i] = NULL;
}
fr_queue = event_queue_init();
ufr.queue = event_queue_init();
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
@@ -287,27 +336,37 @@ void fastrouter_loop() {
}
}
event_queue_add_fd_read(fr_queue, ufr_sock->fd);
uwsgi_log("uwsgi fastrouter/proxy bound on %s\n", ufr_sock->name);
if (!ufr.cheap) {
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
}
else {
uwsgi_log("[uwsgi-fastrouter] cheap mode requested. Waiting for subscriptions...\n");
ufr.i_am_cheap = 1;
}
ufr_sock = ufr_sock->next;
}
events = event_queue_alloc(ufr.nevents);
ufr.timeouts = uwsgi_init_rb_timer();
if (!ufr.socket_timeout) ufr.socket_timeout = 30;
if (ufr.subscription_server) {
ufr_subserver = bind_to_udp(ufr.subscription_server, 0, 0);
event_queue_add_fd_read(fr_queue, ufr_subserver);
event_queue_add_fd_read(ufr.queue, ufr_subserver);
if (!ufr.subscription_slot) ufr.subscription_slot = 30;
ufr.subscription_dict = uwsgi_dict_create(ufr.subscription_slot, 0);
// check for node status every 10 seconds
//ufr.subscriptions_check = add_check_timeout(10);
}
if (ufr.pattern) {
init_magic_table(magic_table);
}
ufr.timeouts = uwsgi_init_rb_timer();
if (!ufr.socket_timeout) ufr.socket_timeout = 30;
for (;;) {
@@ -323,7 +382,7 @@ void fastrouter_loop() {
}
}
nevents = event_queue_wait_multi(fr_queue, delta, events, ufr.nevents);
nevents = event_queue_wait_multi(ufr.queue, delta, events, ufr.nevents);
if (nevents == 0) {
expire_timeouts(fr_table);
@@ -350,12 +409,15 @@ void fastrouter_loop() {
fr_table[new_connection]->status = FASTROUTER_STATUS_RECV_HDR;
fr_table[new_connection]->h_pos = 0;
fr_table[new_connection]->pos = 0;
fr_table[new_connection]->un = NULL;
fr_table[new_connection]->instance_failed = 0;
fr_table[new_connection]->instance_address_len = 0;
fr_table[new_connection]->hostname_len = 0;
fr_table[new_connection]->hostname = NULL;
fr_table[new_connection]->timeout = add_timeout(fr_table[new_connection]);
event_queue_add_fd_read(fr_queue, new_connection);
event_queue_add_fd_read(ufr.queue, new_connection);
taken = 1;
break;
}
@@ -370,12 +432,20 @@ void fastrouter_loop() {
if (interesting_fd == ufr_subserver) {
len = recv(ufr_subserver, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(fr_queue, ufr_subserver);
event_queue_add_fd_read(ufr.queue, ufr_subserver);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf+4, len-4, fastrouter_manage_subscription, &usr);
uwsgi_add_subscriber(ufr.subscription_dict, &usr);
if (uwsgi_add_subscribe_node(&ufr.subscriptions, &usr, ufr.subscription_regexp) && ufr.i_am_cheap) {
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 0;
uwsgi_log("[uwsgi-fastrouter] leaving cheap mode...\n");
}
}
}
else {
@@ -430,10 +500,15 @@ void fastrouter_loop() {
}
#ifdef UWSGI_DEBUG
uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
//uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
#endif
if (ufr.use_cache) {
fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
if (cs_mod) {
fr_session->modifier1 = uwsgi_str_num(cs_mod+1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address))-1);
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
}
}
else if (ufr.pattern) {
magic_table['s'] = uwsgi_concat2n(fr_session->hostname, fr_session->hostname_len, "", 0);
@@ -443,7 +518,7 @@ void fastrouter_loop() {
fr_session->instance_address = tmp_socket_name;
}
else if (ufr.subscription_server) {
fr_session->un = uwsgi_get_subscriber(ufr.subscription_dict, fr_session->hostname, fr_session->hostname_len);
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;
@@ -455,6 +530,19 @@ void fastrouter_loop() {
fr_session->instance_address_len = tmp_socket_name_len;
fr_session->instance_address = tmp_socket_name;
}
else if (ufr.code_string_code && ufr.code_string_function) {
if (uwsgi.p[ufr.code_string_modifier1]->code_string) {
fr_session->instance_address = uwsgi.p[ufr.code_string_modifier1]->code_string("uwsgi_fastrouter", ufr.code_string_code, ufr.code_string_function, fr_session->hostname, fr_session->hostname_len);
if (fr_session->instance_address) {
fr_session->instance_address_len = strlen(fr_session->instance_address);
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
if (cs_mod) {
fr_session->modifier1 = uwsgi_str_num(cs_mod+1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address))-1);
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
}
}
}
}
// no address found
if (!fr_session->instance_address_len) {
@@ -470,10 +558,24 @@ void fastrouter_loop() {
if (tmp_socket_name) free(tmp_socket_name);
if (fr_session->instance_fd < 0) {
/*
if (ufr.subscription_server) {
uwsgi_log("marking %.*s as failed\n", (int) fr_session->instance_address_len,fr_session->instance_address);
fr_session->un->len = 0;
if (fr_session->un && fr_session->un->len > 0) {
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
uwsgi_remove_subscribe_node(&ufr.subscriptions, fr_session->un);
if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 1;
}
}
}
*/
fr_session->instance_failed = 1;
close_session(fr_table, fr_session);
break;
}
@@ -481,7 +583,7 @@ void fastrouter_loop() {
fr_session->status = FASTROUTER_STATUS_CONNECTING;
fr_table[fr_session->instance_fd] = fr_session;
event_queue_add_fd_write(fr_queue, fr_session->instance_fd);
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
}
break;
@@ -547,7 +649,7 @@ void fastrouter_loop() {
break;
}
event_queue_fd_write_to_read(fr_queue, fr_session->instance_fd);
event_queue_fd_write_to_read(ufr.queue, fr_session->instance_fd);
fr_session->status = FASTROUTER_STATUS_RESPONSE;
}
@@ -603,7 +705,7 @@ void fastrouter_loop() {
// fallback to destroy !!!
default:
uwsgi_log("default action\n");
uwsgi_log("unknown event: closing session\n");
close_session(fr_table, fr_session);
break;
@@ -625,9 +727,17 @@ int fastrouter_init() {
if (!ufr.nevents) ufr.nevents = 64;
if (register_gateway("fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
if (ufr.code_string_code && ufr.code_string_function) {
if (register_fat_gateway("uWSGI fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
}
}
else {
if (register_gateway("uWSGI fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
}
}
}
@@ -636,6 +746,10 @@ int fastrouter_init() {
int fastrouter_opt(int i, char *optarg) {
char *cs;
char *cs_code;
char *cs_func;
switch(i) {
case LONG_ARGS_FASTROUTER:
uwsgi_fastrouter_new_socket(generate_socket_name(optarg));
@@ -656,6 +770,24 @@ int fastrouter_opt(int i, char *optarg) {
// optimization
ufr.base_len = strlen(ufr.base);
return 1;
case LONG_ARGS_FASTROUTER_USE_CODE_STRING:
cs = uwsgi_str(optarg);
cs_code = strchr(cs, ':');
if (!cs_code) {
uwsgi_log("invalid code_string option\n");
exit(1);
}
cs_code[0] = 0;
cs_func = strchr(cs_code+1, ':');
if (!cs_func) {
uwsgi_log("invalid code_string option\n");
exit(1);
}
cs_func[0] = 0;
ufr.code_string_modifier1 = atoi(cs);
ufr.code_string_code = cs_code+1;
ufr.code_string_function = cs_func+1;
return 1;
case LONG_ARGS_FASTROUTER_TIMEOUT:
ufr.socket_timeout = atoi(optarg);
return -1;
+356
View File
@@ -0,0 +1,356 @@
#include "../python/uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
struct option gevent_options[] = {
{ 0, 0, 0, 0 }
};
#define GEVENT_SWITCH PyObject *gswitch = python_call(ugevent.greenlet_switch, ugevent.greenlet_switch_args, 0, NULL); Py_DECREF(gswitch)
#define GET_CURRENT_GREENLET python_call(ugevent.get_current, ugevent.get_current_args, 0, NULL)
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req
#define stop_the_watchers ret = PyObject_CallMethod(timer, "stop", NULL);\
if (ret) Py_DECREF(ret);\
ret = PyObject_CallMethod(watcher, "stop", NULL);\
if (ret) Py_DECREF(ret);
struct uwsgi_gevent {
PyObject *greenlet_switch;
PyObject *greenlet_switch_args;
PyObject *get_current;
PyObject *get_current_args;
PyObject *hub;
PyObject *hub_loop;
PyObject *spawn;
PyObject *greenlet_args;
PyObject *signal_args;
} ugevent;
PyObject *py_uwsgi_gevent_signal_handler(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
int signal_socket;
if (!PyArg_ParseTuple(args, "i:uwsgi_gevent_signal_handler", &signal_socket)) {
return NULL;
}
if (read(signal_socket, &uwsgi_signal, 1) <= 0) {
if (uwsgi.no_orphans) {
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
end_me(0);
}
// close the socket to end the mess...from now on the worker is alone (no master)
else close(signal_socket);
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
}
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_gevent_signal(PyObject * self, PyObject * args) {
PyTuple_SetItem(ugevent.signal_args, 1, PyInt_FromLong(uwsgi.signal_socket));
// spawn the signal_handler greenlet
PyObject *new_gl = python_call(ugevent.spawn, ugevent.signal_args, 0, NULL);
Py_DECREF(new_gl);
Py_INCREF(Py_None);
return Py_None;
}
// yes copy&paste no-DRY for me :P
PyObject *py_uwsgi_gevent_my_signal(PyObject * self, PyObject * args) {
PyTuple_SetItem(ugevent.signal_args, 1, PyInt_FromLong(uwsgi.my_signal_socket));
// spawn the signal_handler greenlet
PyObject *new_gl = python_call(ugevent.spawn, ugevent.signal_args, 0, NULL);
Py_DECREF(new_gl);
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = find_first_available_wsgi_req();
if (wsgi_req == NULL) {
uwsgi_log("async queue is full !!!\n");
goto clear;
}
uwsgi.wsgi_req = wsgi_req;
// fill wsgi_request structure
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi.sockets );
// mark core as used
uwsgi.core[wsgi_req->async_id]->in_request = 1;
gettimeofday(&wsgi_req->start_of_request, NULL);
// enter harakiri mode
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// accept the connection
if (wsgi_req_simple_accept(wsgi_req, uwsgi.sockets->fd)) {
uwsgi_close_request(wsgi_req);
free_req_queue;
goto clear;
}
// hack to easily pass wsgi_req pointer to the greenlet
PyTuple_SetItem(ugevent.greenlet_args, 1, PyLong_FromLong((long)wsgi_req));
// spawn the request greenlet
PyObject *new_gl = python_call(ugevent.spawn, ugevent.greenlet_args, 0, NULL);
Py_DECREF(new_gl);
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *uwsgi_gevent_wait(PyObject *watcher, PyObject *timer, PyObject *current) {
PyObject *ret;
// start the io watcher
ret = PyObject_CallMethod(watcher, "start", "OO", current, watcher);
if (!ret) return NULL;
Py_DECREF(ret);
// start the timeout handler
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
if (!ret) return NULL;
Py_DECREF(ret);
// pass control to the hub
return PyObject_CallMethod(ugevent.hub, "switch", NULL);
}
PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
PyObject *ret;
PyObject *py_wsgi_req = PyTuple_GetItem(args, 0);
struct wsgi_request *wsgi_req = (struct wsgi_request *) PyLong_AsLong(py_wsgi_req);
int status ;
PyObject *current_greenlet = GET_CURRENT_GREENLET;
PyObject *greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");
uwsgi.wsgi_req = wsgi_req;
// create a watcher for request socket
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
if (!watcher) goto clear1;
// a timer to implement timeoit (thanks Denis)
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (!timer) goto clear0;
for(;;) {
// wait for data in the socket
PyObject *ret = uwsgi_gevent_wait(watcher, timer, greenlet_switch);
if (!ret) goto clear_and_stop;
// do not forget to overwrite this pointer each time !!!
uwsgi.wsgi_req = wsgi_req;
// we can safely decref here as watcher and timer has got a +1 for start() method
Py_DECREF(ret);
if (ret == timer) {
uwsgi_log( "timeout. skip request.\n");
goto clear_and_stop;
}
else if (ret == watcher) {
status = wsgi_req->socket->proto(wsgi_req);
if (status < 0) {
goto clear_and_stop;
}
else if (status == 0) {
stop_the_watchers;
break;
}
}
else {
uwsgi_log("unrecognized gevent event !!!\n");
goto clear_and_stop;
}
stop_the_watchers;
}
for(;;) {
uwsgi.wsgi_req = wsgi_req;
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);
if (wsgi_req->async_status <= UWSGI_OK) {
goto clear;
}
// switch after each yield
GEVENT_SWITCH;
}
goto clear;
clear_and_stop:
stop_the_watchers;
clear:
Py_DECREF(timer);
clear0:
Py_DECREF(watcher);
clear1:
Py_DECREF(greenlet_switch);
Py_DECREF(current_greenlet);
uwsgi_close_request(wsgi_req);
uwsgi.wsgi_req = wsgi_req;
free_req_queue;
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef uwsgi_gevent_main_def[] = { {"uwsgi_gevent_main", py_uwsgi_gevent_main, METH_VARARGS, ""} };
PyMethodDef uwsgi_gevent_request_def[] = { {"uwsgi_gevent_request", py_uwsgi_gevent_request, METH_VARARGS, ""} };
PyMethodDef uwsgi_gevent_signal_def[] = { {"uwsgi_gevent_signal", py_uwsgi_gevent_signal, METH_VARARGS, ""} };
PyMethodDef uwsgi_gevent_my_signal_def[] = { {"uwsgi_gevent_my_signal", py_uwsgi_gevent_my_signal, METH_VARARGS, ""} };
PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler", py_uwsgi_gevent_signal_handler, METH_VARARGS, ""} };
void gevent_loop() {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
if (uwsgi.async < 2) {
uwsgi_log("the gevent loop engine requires async mode (--async <n>)\n");
exit(1);
}
PyObject *gevent_dict = get_uwsgi_pydict("gevent");
if (!gevent_dict) uwsgi_pyexit;
PyObject *gevent_version = PyDict_GetItemString(gevent_dict, "version_info");
if (!gevent_version) uwsgi_pyexit;
if (PyInt_AsLong(PyTuple_GetItem(gevent_version, 0)) < 1) {
uwsgi_log("uWSGI requires at least gevent 1.x version\n");
exit(1);
}
ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn");
if (!ugevent.spawn) uwsgi_pyexit;
ugevent.greenlet_switch = PyDict_GetItemString(gevent_dict, "sleep");
if (!ugevent.greenlet_switch) uwsgi_pyexit;
ugevent.greenlet_switch_args = PyTuple_New(0);
Py_INCREF(ugevent.greenlet_switch_args);
PyObject *gevent_get_hub = PyDict_GetItemString(gevent_dict, "get_hub");
ugevent.hub = python_call(gevent_get_hub, PyTuple_New(0), 0, NULL);
if (!ugevent.hub) uwsgi_pyexit;
ugevent.get_current = PyDict_GetItemString(gevent_dict, "getcurrent");
if (!ugevent.get_current) uwsgi_pyexit;
ugevent.get_current_args = PyTuple_New(0);
Py_INCREF(ugevent.get_current_args);
ugevent.hub_loop = PyObject_GetAttrString(ugevent.hub, "loop");
if (!ugevent.hub_loop) uwsgi_pyexit;
// this is the watcher for server socket
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi_sock->fd, 1);
if (!watcher) uwsgi_pyexit;
// main greenlet waiting for connection
PyObject *uwsgi_gevent_main = PyCFunction_New(uwsgi_gevent_main_def, NULL);
Py_INCREF(uwsgi_gevent_main);
// greenlet to run at each request
PyObject *uwsgi_request_greenlet = PyCFunction_New(uwsgi_gevent_request_def, NULL);
Py_INCREF(uwsgi_request_greenlet);
// pre-fill the greenlet args
ugevent.greenlet_args = PyTuple_New(2);
PyTuple_SetItem(ugevent.greenlet_args, 0, uwsgi_request_greenlet);
if (uwsgi.signal_socket > -1) {
// and these are the watcher for signal sockets
PyObject *signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.signal_socket, 1);
if (!signal_watcher) uwsgi_pyexit;
PyObject *my_signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.my_signal_socket, 1);
if (!my_signal_watcher) uwsgi_pyexit;
PyObject *uwsgi_greenlet_signal = PyCFunction_New(uwsgi_gevent_signal_def, NULL);
Py_INCREF(uwsgi_greenlet_signal);
PyObject *uwsgi_greenlet_my_signal = PyCFunction_New(uwsgi_gevent_my_signal_def, NULL);
Py_INCREF(uwsgi_greenlet_my_signal);
PyObject *uwsgi_greenlet_signal_handler = PyCFunction_New(uwsgi_gevent_signal_handler_def, NULL);
Py_INCREF(uwsgi_greenlet_signal_handler);
ugevent.signal_args = PyTuple_New(2);
PyTuple_SetItem(ugevent.signal_args, 0, uwsgi_greenlet_signal_handler);
// start the two signal watchers
if (!PyObject_CallMethod(signal_watcher, "start", "O", uwsgi_greenlet_signal)) uwsgi_pyexit;
if (!PyObject_CallMethod(my_signal_watcher, "start", "O", uwsgi_greenlet_my_signal)) uwsgi_pyexit;
}
// start the main greenlet
PyObject_CallMethod(watcher, "start", "O", uwsgi_gevent_main);
if (!PyObject_CallMethod(ugevent.hub, "join", NULL)) {
PyErr_Print();
}
uwsgi_log("the gevent Hub is no more :(\n");
}
int gevent_init() {
uwsgi_register_loop( (char *) "gevent", gevent_loop);
return 0;
}
struct uwsgi_plugin gevent_plugin = {
.name = "gevent",
.init = gevent_init,
.options = gevent_options,
};
+8
View File
@@ -0,0 +1,8 @@
from distutils import sysconfig
NAME='gevent'
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
LDFLAGS = []
LIBS = []
GCC_LIST = ['gevent']
+29 -14
View File
@@ -39,6 +39,7 @@ struct uwsgi_http {
int server;
char *subscription_server;
int subscription_regexp;
char *pattern;
int pattern_len;
@@ -60,7 +61,7 @@ struct uwsgi_http {
int socket_timeout;
struct uwsgi_dict *subscription_dict;
struct uwsgi_subscribe_slot *subscriptions;
struct rb_root *timeouts;
} uhttp;
@@ -76,6 +77,7 @@ struct option http_options[] = {
{"http-use-cluster", no_argument, &uhttp.use_cluster, 1},
{"http-events", required_argument, 0, LONG_ARGS_HTTP_EVENTS},
{"http-subscription-server", required_argument, 0, LONG_ARGS_HTTP_SUBSCRIPTION_SERVER},
{"http-subscription-use-regexp", no_argument, &uhttp.subscription_regexp, 1},
{"http-timeout", required_argument, 0, LONG_ARGS_HTTP_TIMEOUT},
{0, 0, 0, 0},
};
@@ -136,8 +138,10 @@ struct http_session {
char uss[MAX_HTTP_VEC*2];
char buffer[UMAX16];
char path_info[UMAX16];
uint16_t path_info_len;
struct uwsgi_subscriber_name *un;
struct uwsgi_subscribe_node *un;
in_addr_t ip_addr;
char ip[INET_ADDRSTRLEN];
@@ -156,9 +160,9 @@ static void close_session(struct http_session **uhttp_table, struct http_session
close(uhttp_session->fd);
uhttp_table[uhttp_session->fd] = NULL;
if (uhttp_session->instance_fd != -1) {
if (uhttp.subscription_server && (uhttp_session->instance_failed || uhttp_session->status == HTTP_STATUS_CONNECTING)) {
if (uhttp.subscriptions && (uhttp_session->instance_failed || uhttp_session->status == HTTP_STATUS_CONNECTING)) {
uwsgi_log("marking %.*s as failed\n", (int) uhttp_session->instance_address_len,uhttp_session->instance_address);
uhttp_session->un->len = 0;
uwsgi_remove_subscribe_node(&uhttp.subscriptions, uhttp_session->un);
}
close(uhttp_session->instance_fd);
uhttp_table[uhttp_session->instance_fd] = NULL;
@@ -325,13 +329,19 @@ int http_parse(struct http_session *h_session) {
base = ptr;
while(ptr < watermark) {
if (*ptr == '?' && !query_string) {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, base, ptr-base, &c);
// PATH_INFO must be url-decoded !!!
h_session->path_info_len = ptr-base;
http_url_decode(base, &h_session->path_info_len, h_session->path_info);
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, h_session->path_info, h_session->path_info_len, &c);
query_string = ptr+1;
}
else if (*ptr == ' ') {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "REQUEST_URI", 11, base, ptr-base, &c);
if (!query_string) {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, base, ptr-base, &c);
// PATH_INFO must be url-decoded !!!
h_session->path_info_len = ptr-base;
http_url_decode(base, &h_session->path_info_len, h_session->path_info);
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, h_session->path_info, h_session->path_info_len, &c);
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "QUERY_STRING", 12, "", 0, &c);
}
else {
@@ -403,6 +413,14 @@ int http_parse(struct http_session *h_session) {
ptr++;
}
int i;
for(i=0;i<uhttp.http_vars_cnt;i++) {
char *equal = strchr(uhttp.http_vars[i],'=');
if (equal) {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, uhttp.http_vars[i], equal-uhttp.http_vars[i], equal+1, strlen(equal+1), &c);
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("vec size: %d pkt size: %d load %d\n", c, h_session->uh.pktsize, uhttp.load);
#endif
@@ -466,7 +484,6 @@ void http_loop() {
if (uhttp.subscription_server) {
uhttp_subserver = bind_to_udp(uhttp.subscription_server, 0, 0);
event_queue_add_fd_read(uhttp_queue, uhttp_subserver);
uhttp.subscription_dict = uwsgi_dict_create(100, 0);
}
if (uhttp.pattern) {
@@ -542,7 +559,7 @@ void http_loop() {
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf+4, len-4, http_manage_subscription, &usr);
uwsgi_add_subscriber(uhttp.subscription_dict, &usr);
uwsgi_add_subscribe_node(&uhttp.subscriptions, &usr, uhttp.subscription_regexp);
}
}
else {
@@ -622,7 +639,7 @@ void http_loop() {
uhttp_session->instance_address_len = uhttp.to_len;
}
else if (uhttp.subscription_server) {
uhttp_session->un = uwsgi_get_subscriber(uhttp.subscription_dict, uhttp_session->hostname, uhttp_session->hostname_len);
uhttp_session->un = uwsgi_get_subscribe_node(&uhttp.subscriptions, uhttp_session->hostname, uhttp_session->hostname_len, uhttp.subscription_regexp);
if (uhttp_session->un && uhttp_session->un->len) {
uhttp_session->instance_address = uhttp_session->un->name;
uhttp_session->instance_address_len = uhttp_session->un->len;
@@ -639,6 +656,7 @@ void http_loop() {
}
uhttp_session->pass_fd = is_unix(uhttp_session->instance_address, uhttp_session->instance_address_len);
uhttp_session->instance_fd = uwsgi_connectn(uhttp_session->instance_address, uhttp_session->instance_address_len, 0, 1);
@@ -652,10 +670,7 @@ void http_loop() {
}
if (uhttp_session->instance_fd < 0) {
if (uhttp.subscription_server) {
uwsgi_log("marking %.*s as failed\n", (int) uhttp_session->instance_address_len,uhttp_session->instance_address);
uhttp_session->un->len = 0;
}
uhttp_session->instance_failed = 1;
close_session(uhttp_table, uhttp_session);
break;
}
@@ -874,7 +889,7 @@ int http_init() {
uhttp.server = bind_to_tcp(uhttp.socket_name, uwsgi.listen_queue, strchr(uhttp.socket_name,':'));
if (register_gateway("http", http_loop) == NULL) {
if (register_gateway("uWSGI http", http_loop) == NULL) {
uwsgi_log("unable to register the http gateway\n");
exit(1);
}
+95 -25
View File
@@ -374,7 +374,7 @@ void uwsgi_lua_app() {
luaL_openlibs(ulua.L[i]);
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
uwsgi_log("unable to load file %s\n", ulua.filename);
uwsgi_log("unable to load file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
exit(1);
}
// use a pcall
@@ -403,8 +403,7 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
if ((i = lua_pcall(L, 0, 1, 0)) == 0) {
if (lua_type(L, -1) == LUA_TSTRING) {
http = lua_tolstring(L, -1, &slen);
if ( (rlen = write(wsgi_req->poll.fd, http, slen)) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
return UWSGI_OK;
}
wsgi_req->response_size += rlen;
@@ -420,12 +419,12 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
/* Standard WSAPI request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log( "Invalid WSAPI request. skip.\n");
goto clear;
goto clear2;
}
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid WSAPI request. skip.\n");
goto clear;
goto clear2;
}
// put function in the stack
@@ -453,12 +452,16 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
lua_setfield(L, -2, "read");
lua_setfield(L, -2, "input");
#ifdef UWSGI_DEBUG
uwsgi_log("stack pos %d\n", lua_gettop(L));
#endif
// call function
i = lua_pcall(L, 1, 3, 0);
if (i != 0) {
uwsgi_log("%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
lua_pushvalue(L, -1);
goto clear;
}
@@ -468,26 +471,30 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
// send status
if (lua_type(L, -3) == LUA_TSTRING || lua_type(L, -3) == LUA_TNUMBER) {
http = lua_tolstring(L, -3, &slen);
if (write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len) != wsgi_req->protocol_len) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len)) != wsgi_req->protocol_len) {
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, " ", 1) != 1) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, " ", 1)) != 1) {
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
// a performance hack
ptrbuf = (char *) http;
ptrbuf[3] = 0;
wsgi_req->status = atoi(ptrbuf);
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
}
else {
raw = 1;
@@ -499,31 +506,41 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
lua_pushnil(L);
while(lua_next(L, -3) != 0) {
http = lua_tolstring(L, -2, &slen);
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, ": ", 2) != 2) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, ": ", 2)) != 2) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
http = lua_tolstring(L, -1, &slen);
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
wsgi_req->headers_size += rlen;
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
lua_pop(L, 2);
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
lua_pop(L, 1);
wsgi_req->header_cnt++;
}
if (!raw) {
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->headers_size += rlen;
}
// send body with coroutine
@@ -532,8 +549,9 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
while ( (i = lua_pcall(L, 0, 1, 0)) == 0) {
if (lua_type(L, -1) == LUA_TSTRING) {
http = lua_tolstring(L, -1, &slen);
if ( (rlen = write(wsgi_req->poll.fd, http, slen)) != (ssize_t) slen) {
perror("write()");
if ( (rlen = wsgi_req->socket->proto_write(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
lua_pop(L, 1);
lua_pushvalue(L, -1);
goto clear;
}
wsgi_req->response_size += rlen;
@@ -550,6 +568,7 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
clear:
lua_pop(L, 4);
clear2:
// set frequency
lua_gc(L, LUA_GCCOLLECT, 0);
@@ -590,6 +609,55 @@ int uwsgi_lua_magic(char *mountpoint, char *lazy) {
return 0;
}
char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, uint16_t keylen) {
static struct lua_State *L = NULL;
if (!L) {
L = luaL_newstate();
luaL_openlibs(L);
if (luaL_loadfile(L, code) || lua_pcall(L, 0, 0, 0)) {
uwsgi_log("unable to load file %s: %s\n", code, lua_tostring(L, -1));
lua_close(L);
L = NULL;
return NULL;
}
lua_getglobal(L, func);
if (!lua_isfunction(L,-1)) {
uwsgi_log("unable to find %s function in lua file %s\n", func, code);
lua_close(L);
L = NULL;
return NULL;
}
lua_pushnil(L);
}
lua_pop(L, 1);
lua_pushvalue(L, -1);
lua_pushlstring(L, key, keylen);
#ifdef UWSGI_DEBUG
uwsgi_log("stack pos %d %.*s\n", lua_gettop(L), keylen, key);
#endif
if (lua_pcall(L, 1, 1, 0) != 0) {
uwsgi_log("CAZZO\n");
uwsgi_log("error running function `f': %s",
lua_tostring(L, -1));
return NULL;
}
if (lua_isstring(L, -1)) {
const char *ret = lua_tolstring(L, -1, NULL);
return (char *)ret;
}
return NULL;
}
int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -664,6 +732,8 @@ struct uwsgi_plugin lua_plugin = {
.init_apps = uwsgi_lua_app,
.magic = uwsgi_lua_magic,
.signal_handler = uwsgi_lua_signal_handler,
.code_string = uwsgi_lua_code_string,
.rpc = uwsgi_lua_rpc,
};
+1 -1
View File
@@ -34,7 +34,7 @@ struct uwsgi_perl {
void init_perl_embedded_module(void);
void uwsgi_psgi_app(void);
int psgi_response(struct wsgi_request *, PerlInterpreter *, AV*);
int psgi_response(struct wsgi_request *, AV*);
#define psgi_xs(func) newXS("uwsgi::" #func, XS_##func, "uwsgi")
#define psgi_check_args(x) if (items < x) Perl_croak(aTHX_ "Usage: uwsgi::%s takes %d arguments", __FUNCTION__ + 3, x)
+26 -14
View File
@@ -41,19 +41,11 @@ XS(XS_stream)
AV *response = (AV* ) SvREFCNT_inc(SvRV(ST(0))) ;
if (av_len(response) == 2) {
#ifdef my_perl
while (psgi_response(wsgi_req, my_perl, response) != UWSGI_OK);
#else
while (psgi_response(wsgi_req, uperl.main, response) != UWSGI_OK);
#endif
while (psgi_response(wsgi_req, response) != UWSGI_OK);
}
else if (av_len(response) == 1) {
#ifdef my_perl
while (psgi_response(wsgi_req, my_perl, response) != UWSGI_OK);
#else
while (psgi_response(wsgi_req, uperl.main, response) != UWSGI_OK);
#endif
while (psgi_response(wsgi_req, response) != UWSGI_OK);
SvREFCNT_dec(response);
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.streaming_stash);
XSRETURN(1);
@@ -236,6 +228,7 @@ xs_init(pTHX)
void uwsgi_psgi_app() {
struct stat stat_psgi;
int id = uwsgi_apps_cnt;
if (uperl.psgi) {
@@ -291,7 +284,6 @@ void uwsgi_psgi_app() {
uperl.psgibuffer[stat_psgi.st_size] = 0;
if (uwsgi.threads < 2) {
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");
@@ -303,11 +295,31 @@ void uwsgi_psgi_app() {
exit(1);
}
if (uwsgi.threads < 2) {
free(uperl.psgibuffer);
close(uperl.fd);
}
}
struct uwsgi_app *wi = &uwsgi_apps[id];
memset(wi, 0, sizeof(struct uwsgi_app));
wi->modifier1 = 5;
wi->mountpoint = "";
wi->mountpoint_len = 0;
uwsgi_log("PSGI app %d (%s) loaded at %p\n", id, uperl.psgi, uperl.psgi_main);
uwsgi_apps_cnt++;
// check if we need to emulate fork() COW
int i;
if (uwsgi.mywid == 0) {
for(i=1;i<=uwsgi.numproc;i++) {
memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
}
}
uwsgi_log("PSGI app (%s) loaded at %p\n", uperl.psgi, uperl.psgi_main);
}
+45 -63
View File
@@ -23,7 +23,7 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
SV *newobj;
// set current context ?
//dTHX;
dTHX;
dSP;
ENTER;
@@ -49,7 +49,7 @@ SV *uwsgi_perl_call_stream(SV *func) {
SV *ret = NULL;
// set current context ?
//dTHX;
dTHX;
dSP;
ENTER;
@@ -79,7 +79,7 @@ int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
int ret;
// set current context ? needed for threading
//dTHX;
dTHX;
dSP;
ENTER;
@@ -107,6 +107,7 @@ SV *uwsgi_perl_obj_call(SV *obj, char *method) {
SV *ret = NULL;
dTHX;
dSP;
ENTER;
@@ -140,6 +141,7 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
AV *ret = NULL;
dTHX;
dSP;
ENTER;
@@ -149,6 +151,7 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
PUTBACK;
call_sv(psgi_func, G_SCALAR | G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
@@ -280,7 +283,7 @@ int uwsgi_perl_init(){
struct http_status_codes *http_sc;
int argc = 3;
int argc;
uperl.embedding[0] = "";
uperl.embedding[1] = "-e";
uperl.embedding[2] = "0";
@@ -298,6 +301,9 @@ int uwsgi_perl_init(){
#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) {
@@ -323,51 +329,19 @@ int uwsgi_perl_init(){
}
#ifdef my_perl
#ifdef USE_ITHREADS
void uwsgi_perl_enable_threads() {
int i;
if (pthread_key_create(&uperl.u_interpreter, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
uperl.interp = malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
if (!uperl.interp) {
uwsgi_error("malloc()");
exit(1);
}
uperl.interp = uwsgi_malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
uperl.interp[0] = uperl.main;
for(i=1;i<uwsgi.threads;i++) {
uperl.interp[i] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
if (!uperl.interp[i]) {
uwsgi_log("unable to create new perl interpreter\n");
exit(1);
}
}
uperl.psgi_func = uwsgi_malloc( sizeof(SV*) * uwsgi.threads );
uperl.psgi_func = malloc( sizeof(SV*) * uwsgi.threads );
if (!uperl.psgi_func) {
uwsgi_error("malloc()");
exit(1);
}
dTHXa(uperl.main);
PERL_SET_CONTEXT(uperl.main);
uperl.psgi_main = perl_eval_pv(uperl.psgibuffer, 0);
if (!uperl.psgi_main) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
}
#endif
@@ -378,12 +352,10 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
SV **harakiri;
SV *psgi_func = uperl.psgi_main;
// ugly hack
register PerlInterpreter *my_perl = uperl.main;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
return psgi_response(wsgi_req, my_perl, wsgi_req->async_placeholder);
return psgi_response(wsgi_req, wsgi_req->async_placeholder);
}
#endif
@@ -398,19 +370,14 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
return -1;
}
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1 && wsgi_req->async_id > 0) {
if (uwsgi.threads > 1) {
psgi_func = uperl.psgi_func[wsgi_req->async_id];
my_perl = pthread_getspecific(uperl.u_interpreter);
}
#endif
ENTER;
SAVETMPS;
wsgi_req->async_environ = build_psgi_env(wsgi_req);
if (!wsgi_req->async_environ) goto clear;
@@ -428,7 +395,7 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
goto clear2;
}
while (psgi_response(wsgi_req, my_perl, wsgi_req->async_result) != UWSGI_OK) {
while (psgi_response(wsgi_req, wsgi_req->async_result) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
FREETMPS;
@@ -468,26 +435,41 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
}
#ifdef USE_ITHREADS
void uwsgi_perl_init_thread(int core_id) {
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
if (core_id > 0) {
uperl.interp[core_id] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
if (!uperl.interp[core_id]) {
uwsgi_log("unable to create new perl interpreter\n");
exit(1);
}
}
dTHXa(uperl.interp[core_id]);
PERL_SET_CONTEXT(uperl.interp[core_id]);
uperl.psgi_func[core_id] = perl_eval_pv(uperl.psgibuffer, 0);
if (!uperl.psgi_func[core_id]) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
uperl.psgi_func[0] = uperl.psgi_main;
if (core_id > 0) {
uperl.psgi_func[core_id] = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
if (!uperl.psgi_func[core_id]) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
}
}
#endif
int uwsgi_perl_manage_options(int i, char *optarg) {
@@ -528,11 +510,11 @@ struct uwsgi_plugin psgi_plugin = {
.init_apps = uwsgi_psgi_app,
//.magic = uwsgi_perl_magic,
//.help = uwsgi_perl_help,
#ifdef my_perl
#ifdef USE_ITHREADS
.enable_threads = uwsgi_perl_enable_threads,
.init_thread = uwsgi_perl_init_thread,
#endif
.manage_opt = uwsgi_perl_manage_options,
.init_thread = uwsgi_perl_init_thread,
.request = uwsgi_perl_request,
.after_request = uwsgi_perl_after_request,
+2 -47
View File
@@ -2,54 +2,9 @@
extern struct uwsgi_server uwsgi;
/* statistically ordered */
struct http_status_codes hsc[] = {
{"200", "OK"},
{"302", "Found"},
{"404", "Not Found"},
{"500", "Internal Server Error"},
{"301", "Moved Permanently"},
{"304", "Not Modified"},
{"303", "See Other"},
{"403", "Forbidden"},
{"307", "Temporary Redirect"},
{"401", "Unauthorized"},
{"400", "Bad Request"},
{"405", "Method Not Allowed"},
{"408", "Request Timeout"},
extern struct http_status_codes hsc[];
{"100", "Continue"},
{"101", "Switching Protocols"},
{"201", "Created"},
{"202", "Accepted"},
{"203", "Non-Authoritative Information"},
{"204", "No Content"},
{"205", "Reset Content"},
{"206", "Partial Content"},
{"300", "Multiple Choices"},
{"305", "Use Proxy"},
{"402", "Payment Required"},
{"406", "Not Acceptable"},
{"407", "Proxy Authentication Required"},
{"409", "Conflict"},
{"410", "Gone"},
{"411", "Length Required"},
{"412", "Precondition Failed"},
{"413", "Request Entity Too Large"},
{"414", "Request-URI Too Long"},
{"415", "Unsupported Media Type"},
{"416", "Requested Range Not Satisfiable"},
{"417", "Expectation Failed"},
{"501", "Not Implemented"},
{"502", "Bad Gateway"},
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{ "", NULL },
};
int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *response) {
int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
SV **status_code, **hitem ;
AV *headers, *body =NULL;
+6 -2
View File
@@ -1,7 +1,11 @@
import os,sys
NAME='psgi'
CFLAGS = [os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip()]
LDFLAGS = [os.popen('perl -MExtUtils::Embed -e ldopts').read().rstrip()]
CFLAGS = os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip().split()
LDFLAGS = os.popen('perl -MExtUtils::Embed -e ldopts').read().rstrip().split()
LIBS = []
GCC_LIST = ['uwsgi_plmodule', 'psgi_loader', 'psgi_response', 'psgi_plugin']
for item in LDFLAGS:
if item.endswith('DynaLoader.a'):
GCC_LIST.append(item)
+21 -8
View File
@@ -304,7 +304,7 @@ void pyerl_call_registered(void *func, ei_x_buff *x) {
PyTuple_SetItem(pyargs, 0, erl_to_py(x));
python_call((PyObject *) func, pyargs, 0);
python_call((PyObject *) func, pyargs, 0, NULL);
}
PyObject *pyerl_register_process(PyObject * self, PyObject * args) {
@@ -316,17 +316,30 @@ PyObject *pyerl_register_process(PyObject * self, PyObject * args) {
return NULL;
}
if (uerl.uep_cnt >= MAX_UWSGI_ERLANG_PROCESSES)
return PyErr_Format(PyExc_ValueError, "You can define max %d erlang registered processes", MAX_UWSGI_ERLANG_PROCESSES);
if (strlen(name) > 0xff-1)
return PyErr_Format(PyExc_ValueError, "Invalid erlang process name");
strcpy(uerl.uep[uerl.uep_cnt].name, name);
uerl.uep[uerl.uep_cnt].plugin = pyerl_call_registered;
uerl.uep[uerl.uep_cnt].func = callable;
struct uwsgi_erlang_process *uep = uerl.uep, *old_uep;
if (!uep) {
uerl.uep = uwsgi_malloc(sizeof(struct uwsgi_erlang_process));
uep = uerl.uep;
}
else {
while(uep) {
old_uep = uep;
uep = uep->next;
}
uep = uwsgi_malloc(sizeof(struct uwsgi_erlang_process));
old_uep->next = uep;
}
strcpy(uep->name, name);
uep->plugin = pyerl_call_registered;
uep->func = callable;
uep->next = NULL;
uerl.uep_cnt++;
Py_INCREF(Py_None);
return Py_None;
+7
View File
@@ -3,6 +3,11 @@
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
@@ -26,5 +31,7 @@ void gil_real_release() {
#endif
}
#endif
void gil_fake_get() {}
void gil_fake_release() {}
+2
View File
@@ -15,6 +15,7 @@ int PyFrame_GetLineNumber(PyFrameObject *frame) {
int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
#ifndef UWSGI_PYPY
switch(what) {
case PyTrace_CALL:
uwsgi_log("[uWSGI Python profiler] CALL: %s (line %d) -> %s %d args, stacksize %d\n",
@@ -29,6 +30,7 @@ int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, Py
PyEval_GetFuncName(arg), frame->f_code->co_argcount, frame->f_code->co_stacksize);
break;
}
#endif
return 0;
}
+392
View File
@@ -0,0 +1,392 @@
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern PyTypeObject uwsgi_InputType;
extern struct http_status_codes hsc[];
void *uwsgi_request_subhandler_pump(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
PyObject *zero;
int i;
PyObject *pydictkey, *pydictvalue;
char *port = memchr(wsgi_req->host, ':', wsgi_req->host_len);
if (port) {
zero = PyString_FromStringAndSize(wsgi_req->host, (port-wsgi_req->host));
PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
Py_DECREF(zero);
zero = PyString_FromStringAndSize(port, wsgi_req->host_len-((port+1)-wsgi_req->host));
PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
Py_DECREF(zero);
}
else {
zero = PyString_FromStringAndSize(wsgi_req->host, wsgi_req->host_len);
PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
Py_DECREF(zero);
zero = PyString_FromStringAndSize("80", 2);
PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
Py_DECREF(zero);
}
zero = PyString_FromStringAndSize(wsgi_req->remote_addr, wsgi_req->remote_addr_len);
PyDict_SetItemString(wsgi_req->async_environ, "remote_addr", zero);
Py_DECREF(zero);
zero = PyString_FromStringAndSize(wsgi_req->path_info, wsgi_req->path_info_len);
PyDict_SetItemString(wsgi_req->async_environ, "uri", zero);
Py_DECREF(zero);
if (wsgi_req->query_string_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->query_string, wsgi_req->query_string_len);
PyDict_SetItemString(wsgi_req->async_environ, "query_string", zero);
Py_DECREF(zero);
}
zero = PyString_FromStringAndSize(uwsgi_lower(wsgi_req->method, wsgi_req->method_len), wsgi_req->method_len);
PyDict_SetItemString(wsgi_req->async_environ, "method", zero);
Py_DECREF(zero);
if (wsgi_req->post_cl > 0) {
PyDict_SetItemString(wsgi_req->async_environ, "content_length", PyInt_FromLong(wsgi_req->post_cl));
if (wsgi_req->content_type_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->content_type, wsgi_req->content_type_len);
PyDict_SetItemString(wsgi_req->async_environ, "content_type", zero);
Py_DECREF(zero);
}
}
PyObject *headers = PyDict_New();
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
if (wsgi_req->hvec[i].iov_len < 6) continue;
if (!uwsgi_startswith(wsgi_req->hvec[i].iov_base, "HTTP_", 5)) {
(void) uwsgi_lower(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5);
#ifdef PYTHREE
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5, NULL);
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
PyObject *old_value = PyDict_GetItem(headers, pydictkey);
if (old_value) {
if (PyString_Check(old_value)) {
PyObject *new_value = PyList_New(0);
PyList_Append(new_value, old_value);
old_value = new_value;
PyDict_SetItem(headers, pydictkey, old_value);
Py_DECREF(old_value);
}
PyList_Append(old_value, pydictvalue);
}
else {
PyDict_SetItem(headers, pydictkey, pydictvalue);
}
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
}
PyDict_SetItemString(wsgi_req->async_environ, "headers", headers);
Py_DECREF(headers);
// if async_post is mapped as a file, directly use it as wsgi.input
if (wsgi_req->async_post) {
#ifdef PYTHREE
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "pump_body", "rb", 0, NULL, NULL, NULL, 0);
#else
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "pump_body", "r", NULL);
#endif
}
else {
// create wsgi.input custom object
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
}
PyDict_SetItemString(wsgi_req->async_environ, "body", wsgi_req->async_input);
if (wsgi_req->scheme_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
zero = PyString_FromString("https");
}
else {
zero = PyString_FromString("http");
}
}
else {
zero = PyString_FromString("http");
}
PyDict_SetItemString(wsgi_req->async_environ, "scheme", zero);
Py_DECREF(zero);
wsgi_req->async_app = wi->callable;
// export .env only in non-threaded mode
if (uwsgi.threads < 2) {
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
}
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
if (uwsgi.cores > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
}
// cache this ?
if (uwsgi.cluster_fd >= 0) {
zero = PyString_FromString(uwsgi.cluster);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
Py_DECREF(zero);
zero = PyString_FromString(uwsgi.hostname);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero);
Py_DECREF(zero);
}
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
// call
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
}
int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
PyObject *pychunk;
ssize_t wsize;
int i;
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)) {
PyObject *status = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "status");
if (!status) {
uwsgi_log("invalid Pump response (status code).\n");
goto clear;
}
PyObject *headers = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "headers");
if (!headers) {
uwsgi_log("invalid Pump response (headers).\n");
goto clear;
}
wsgi_req->async_placeholder = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "body");
if (!wsgi_req->async_placeholder) {
uwsgi_log("invalid Pump response (body).\n");
goto clear;
}
// get the status code
if (!PyInt_Check(status)) {
uwsgi_log("invalid Pump response (status code).\n");
goto clear;
}
if (uwsgi_num2str2n(PyInt_AsLong(status), sc, 4) != 3) {
uwsgi_log("invalid Pump response (status code).\n");
goto clear;
}
int found = 0;
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
if (http_sc->key[0] == sc[0] && http_sc->key[1] == sc[1] && http_sc->key[2] == sc[2]) {
wsgi_req->hvec[4].iov_base = (char *) http_sc->message;
wsgi_req->hvec[4].iov_len = http_sc->message_size;
found = 1;
break;
}
}
if (!found) {
uwsgi_log("invalid Pump response (status code).\n");
goto clear;
}
wsgi_req->hvec[0].iov_base = wsgi_req->protocol;
wsgi_req->hvec[0].iov_len = wsgi_req->protocol_len;
wsgi_req->hvec[1].iov_base = " ";
wsgi_req->hvec[1].iov_len = 1;
wsgi_req->hvec[2].iov_base = sc;
wsgi_req->hvec[2].iov_len = 3;
wsgi_req->hvec[3].iov_base = " ";
wsgi_req->hvec[3].iov_len = 1;
wsgi_req->hvec[5].iov_base = "\r\n";
wsgi_req->hvec[5].iov_len = 2;
UWSGI_RELEASE_GIL
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6);
UWSGI_GET_GIL
if (wsize < 0) {
uwsgi_error("writev()");
}
wsgi_req->headers_size += wsize;
PyObject *hhkey, *hhvalue;
#ifdef UWSGI_PYTHON_OLD
int hhpos = 0;
#else
Py_ssize_t hhpos = 0;
#endif
while (PyDict_Next(headers, &hhpos, &hhkey, &hhvalue)) {
if (!PyString_Check(hhkey)) continue;
wsgi_req->hvec[0].iov_base = PyString_AsString(hhkey);
wsgi_req->hvec[0].iov_len = PyString_Size(hhkey);
((char*)wsgi_req->hvec[0].iov_base)[0] = toupper((int) ((char*)wsgi_req->hvec[0].iov_base)[0]);
wsgi_req->hvec[1].iov_base = ": ";
wsgi_req->hvec[1].iov_len = 2;
wsgi_req->hvec[3].iov_base = "\r\n";
wsgi_req->hvec[3].iov_len = 2;
if (PyList_Check(hhvalue)) {
for(i=0;i<PyList_Size(hhvalue);i++) {
PyObject *item = PyList_GetItem(hhvalue, i);
if (PyString_Check(item)) {
wsgi_req->hvec[2].iov_base = PyString_AsString(item);
wsgi_req->hvec[2].iov_len = PyString_Size(item);
UWSGI_RELEASE_GIL
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4);
UWSGI_GET_GIL
if (wsize < 0) {
uwsgi_error("writev()");
}
wsgi_req->headers_size += wsize;
}
}
}
else if (PyString_Check(hhvalue)) {
wsgi_req->hvec[2].iov_base = PyString_AsString(hhvalue);
wsgi_req->hvec[2].iov_len = PyString_Size(hhvalue);
UWSGI_RELEASE_GIL
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4);
UWSGI_GET_GIL
if (wsize < 0) {
uwsgi_error("writev()");
}
wsgi_req->headers_size += wsize;
}
}
wsgi_req->socket->proto_write(wsgi_req, "\r\n", 2);
Py_INCREF((PyObject *)wsgi_req->async_placeholder);
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;
}
wsgi_req->response_size += wsize;
goto clear;
}
#ifdef PYTHREE
else if ((wsgi_req->sendfile_fd = PyObject_AsFileDescriptor((PyObject *)wsgi_req->async_placeholder)) > -1) {
#else
else if (PyFile_Check((PyObject *)wsgi_req->async_placeholder)) {
wsgi_req->sendfile_fd = fileno(PyFile_AsFile((PyObject *)wsgi_req->async_placeholder));
#endif
wsize = uwsgi_sendfile(wsgi_req);
if (wsize < 0) {
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
PyObject *tmp = (PyObject *)wsgi_req->async_placeholder;
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_placeholder );
Py_DECREF(tmp);
if (!wsgi_req->async_placeholder) {
goto clear;
}
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
}
else {
uwsgi_log("invalid Pump response.\n");
goto clear;
}
#endif
}
pychunk = PyIter_Next(wsgi_req->async_placeholder);
if (!pychunk) {
if (PyErr_Occurred()) PyErr_Print();
goto clear;
}
if (PyString_Check(pychunk)) {
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
uwsgi_error("write()");
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;
}
+154 -66
View File
@@ -22,12 +22,62 @@ PyMethodDef uwsgi_eventfd_read_method[] = { {"uwsgi_eventfd_read", py_eventfd_re
PyMethodDef uwsgi_eventfd_write_method[] = { {"uwsgi_eventfd_write", py_eventfd_write, METH_VARARGS, ""}};
#endif
int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThreadState *interpreter) {
#ifdef UWSGI_MINTERPRETERS
void set_dyn_pyhome(char *home, uint16_t pyhome_len) {
char venv_version[15];
PyObject *site_module;
PyObject *pysys_dict = get_uwsgi_pydict("sys");
PyObject *pypath = pypath = PyDict_GetItemString(pysys_dict, "path");
if (!pypath) {
PyErr_Print();
exit(1);
}
// simulate a pythonhome directive
if (uwsgi.wsgi_req->pyhome_len > 0) {
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len);
#ifdef UWSGI_DEBUG
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->pyhome_len, uwsgi.wsgi_req->pyhome);
#endif
PyDict_SetItemString(pysys_dict, "prefix", venv_path);
PyDict_SetItemString(pysys_dict, "exec_prefix", venv_path);
venv_version[14] = 0;
if (snprintf(venv_version, 15, "/lib/python%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION) == -1) {
return;
}
// check here
PyString_Concat(&venv_path, PyString_FromString(venv_version));
if (PyList_Insert(pypath, 0, venv_path)) {
PyErr_Print();
}
site_module = PyImport_ImportModule("site");
if (site_module) {
PyImport_ReloadModule(site_module);
}
}
}
#endif
int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThreadState *interpreter, int app_type) {
PyObject *zero;
PyObject *app_list = NULL, *applications = NULL;
int id = uwsgi.apps_cnt;
int id = uwsgi_apps_cnt;
int multiapp = 0;
#ifdef UWSGI_ASYNC
@@ -38,23 +88,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
struct uwsgi_app *wi;
if (wsgi_req->script_name_len == 0) {
wsgi_req->script_name = "";
}
else if (wsgi_req->script_name_len == 1) {
if (wsgi_req->script_name[0] == '/') {
wsgi_req->script_name = "";
wsgi_req->script_name_len = 0;
}
}
if (uwsgi.vhost) {
mountpoint = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|", 1, wsgi_req->script_name, wsgi_req->script_name_len);
}
else {
mountpoint = uwsgi_strncopy(wsgi_req->script_name, wsgi_req->script_name_len);
}
mountpoint = uwsgi_strncopy(wsgi_req->appid, wsgi_req->appid_len);
if (uwsgi_get_app_id(mountpoint, strlen(mountpoint), -1) != -1) {
uwsgi_log( "mountpoint %.*s already configured. skip.\n", strlen(mountpoint), mountpoint);
@@ -63,7 +98,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
wi = &uwsgi.apps[id];
wi = &uwsgi_apps[id];
memset(wi, 0, sizeof(struct uwsgi_app));
wi->mountpoint = mountpoint;
@@ -110,7 +145,9 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
continue;
}
#ifdef UWSGI_DEBUG
uwsgi_log("%s = %s\n", PyString_AsString(k), PyString_AsString(env_value));
#endif
if (PyObject_SetItem(py_environ, k, env_value)) {
PyErr_Print();
@@ -125,7 +162,9 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
}
#ifdef UWSGI_MINTERPRETERS
if (interpreter == NULL && id) {
wi->interpreter = Py_NewInterpreter();
if (!wi->interpreter) {
uwsgi_log( "unable to initialize the new python interpreter\n");
@@ -148,6 +187,13 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
wi->interpreter = up.main_thread;
}
if (wsgi_req->pyhome_len) {
set_dyn_pyhome(wsgi_req->pyhome, wsgi_req->pyhome_len);
}
#else
wi->interpreter = up.main_thread;
#endif
if (wsgi_req->touch_reload_len) {
struct stat trst;
char *touch_reload = uwsgi_strncopy(wsgi_req->touch_reload, wsgi_req->touch_reload_len);
@@ -160,7 +206,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
wi->callable = up.loaders[loader](arg1);
if (!wi->callable) {
uwsgi_log("unable to load app SCRIPT_NAME=%s\n", mountpoint);
uwsgi_log("unable to load app %d (mountpoint='%s') (callable not found or import error)\n", id, mountpoint);
goto doh;
}
@@ -184,12 +230,22 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
wi->mountpoint = PyString_AsString(app_mnt);
wi->mountpoint_len = strlen(wi->mountpoint);
wsgi_req->script_name = wi->mountpoint;
wsgi_req->script_name_len = wi->mountpoint_len;
wsgi_req->appid = wi->mountpoint;
wsgi_req->appid_len = wi->mountpoint_len;
#ifdef UWSGI_DEBUG
uwsgi_log("main mountpoint = %s\n", wi->mountpoint);
#endif
wi->callable = PyDict_GetItem(applications, app_mnt);
if (PyString_Check((PyObject *) wi->callable)) {
PyObject *callables_dict = get_uwsgi_pydict((char *)arg1);
if (callables_dict) {
wi->callable = PyDict_GetItem(callables_dict, (PyObject *)wi->callable);
}
}
}
Py_INCREF((PyObject *)wi->callable);
#ifdef UWSGI_ASYNC
wi->environ = malloc(sizeof(PyObject*)*uwsgi.cores);
if (!wi->environ) {
@@ -212,47 +268,29 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
#endif
// check function args
// by defaut it is a WSGI app
wi->argc = 2;
zero = PyObject_GetAttrString(wi->callable, "__code__");
if (!zero) {
zero = PyObject_GetAttrString(wi->callable, "__call__");
if (zero) {
zero = PyObject_GetAttrString(wi->callable, "__code__");
}
else {
uwsgi_log("WARNING: unable to get the number of callable args. Fallback to WSGI\n");
}
}
wi->argc = 1;
// avoid __code__ attr error propagation
PyErr_Clear();
if (zero) {
zero = PyObject_GetAttrString(zero, "co_argcount");
wi->argc = (int) PyInt_AsLong(zero);
}
if (wi->argc == 2) {
if (app_type == PYTHON_APP_TYPE_WSGI) {
#ifdef UWSGI_DEBUG
uwsgi_log("-- WSGI callable detected --\n");
uwsgi_log("-- WSGI callable selected --\n");
#endif
wi->request_subhandler = uwsgi_request_subhandler_wsgi;
wi->response_subhandler = uwsgi_response_subhandler_wsgi;
wi->argc = 2;
}
#ifdef UWSGI_WEB3
else if (wi->argc == 1) {
else if (app_type == PYTHON_APP_TYPE_WEB3) {
#ifdef UWSGI_DEBUG
uwsgi_log("-- Web3 callable detected --\n");
uwsgi_log("-- Web3 callable selected --\n");
#endif
wi->request_subhandler = uwsgi_request_subhandler_web3;
wi->response_subhandler = uwsgi_response_subhandler_web3;
}
else if (app_type == PYTHON_APP_TYPE_PUMP) {
#ifdef UWSGI_DEBUG
uwsgi_log("-- Pump callable selected --\n");
#endif
else {
uwsgi_log("-- INVALID callable detected --\n");
goto doh;
wi->request_subhandler = uwsgi_request_subhandler_pump;
wi->response_subhandler = uwsgi_response_subhandler_pump;
}
#ifdef UWSGI_ASYNC
@@ -270,7 +308,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
// add start_response on WSGI app
if (wi->argc == 2) {
Py_INCREF((PyObject *)up.wsgi_spitout);
if (app_type == PYTHON_APP_TYPE_WSGI) {
if (PyTuple_SetItem(wi->args[i], 1, up.wsgi_spitout)) {
uwsgi_log("unable to set start_response in args tuple\n");
exit(1);
@@ -279,8 +318,10 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
#else
// add start_response on WSGI app
Py_INCREF((PyObject *)up.wsgi_spitout);
wi->wsgi_args = PyTuple_New(wi->argc);
if (wi->argc == 2) {
if (app_type == PYTHON_APP_TYPE_WSGI) {
if (PyTuple_SetItem(wi->wsgi_args, 1, up.wsgi_spitout)) {
uwsgi_log("unable to set start_response in args tuple\n");
exit(1);
@@ -288,7 +329,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
#endif
if (wi->argc == 2) {
if (app_type == PYTHON_APP_TYPE_WSGI) {
#ifdef UWSGI_SENDFILE
// prepare sendfile() for WSGI app
wi->sendfile = PyCFunction_New(uwsgi_sendfile_method, NULL);
@@ -300,6 +341,19 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
#endif
}
// cache most used values
wi->gateway_version = PyTuple_New(2);
PyTuple_SetItem(wi->gateway_version, 0, PyInt_FromLong(1));
PyTuple_SetItem(wi->gateway_version, 1, PyInt_FromLong(0));
Py_INCREF((PyObject *)wi->gateway_version);
wi->uwsgi_version = PyString_FromString(UWSGI_VERSION);
Py_INCREF((PyObject *)wi->uwsgi_version);
wi->uwsgi_node = PyString_FromString(uwsgi.hostname);
Py_INCREF((PyObject *)wi->uwsgi_node);
if (uwsgi.threads > 1 && id) {
// if we have multiple threads we need to initialize a PyThreadState for each one
for(i=0;i<uwsgi.threads;i++) {
@@ -316,19 +370,22 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
PyThreadState_Swap(up.main_thread);
}
if (wi->argc == 1) {
uwsgi_log( "Web3 application %d (SCRIPT_NAME=%.*s) ready on interpreter %p", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter);
if (app_type == PYTHON_APP_TYPE_WSGI) {
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
else {
uwsgi_log( "WSGI application %d (SCRIPT_NAME=%.*s) ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
else if (app_type == PYTHON_APP_TYPE_WEB3) {
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
else if (app_type == PYTHON_APP_TYPE_PUMP) {
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
if (!wsgi_req->script_name_len) {
if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
uwsgi_rawlog(" (default app)");
uwsgi.default_app = id;
}
uwsgi.apps_cnt++;
uwsgi_apps_cnt++;
uwsgi_rawlog("\n");
@@ -340,9 +397,29 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
continue;
}
wsgi_req->script_name = PyString_AsString(app_mnt);
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
init_uwsgi_app(LOADER_CALLABLE, PyDict_GetItem(applications, app_mnt), wsgi_req, wi->interpreter);
wsgi_req->appid = PyString_AsString(app_mnt);
wsgi_req->appid_len = strlen(wsgi_req->appid);
PyObject *a_callable = PyDict_GetItem(applications, app_mnt);
if (PyString_Check(a_callable)) {
PyObject *callables_dict = get_uwsgi_pydict((char *)arg1);
if (callables_dict) {
a_callable = PyDict_GetItem(callables_dict, a_callable);
}
}
if (!a_callable) {
uwsgi_log("skipping broken app %s\n", wsgi_req->appid);
continue;
}
init_uwsgi_app(LOADER_CALLABLE, a_callable, wsgi_req, wi->interpreter, app_type);
}
}
// 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;
}
}
@@ -351,6 +428,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
doh:
free(mountpoint);
PyErr_Print();
#ifdef UWSGI_MINTERPRETERS
if (interpreter == NULL && id) {
Py_EndInterpreter(wi->interpreter);
if (uwsgi.threads > 1) {
@@ -360,6 +438,7 @@ doh:
PyThreadState_Swap(up.main_thread);
}
}
#endif
return -1;
}
@@ -404,7 +483,9 @@ 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;
@@ -427,8 +508,10 @@ 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");
@@ -441,7 +524,7 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
tmp_callable = PyDict_GetItemString(wsgi_dict, quick_callable);
quick_callable[strlen(quick_callable)] = '(';
if (tmp_callable) {
return python_call(tmp_callable, PyTuple_New(0), 0);
return python_call(tmp_callable, PyTuple_New(0), 0, NULL);
}
}
@@ -523,7 +606,7 @@ PyObject *uwsgi_file_loader(void *arg1) {
char *callable = up.callable;
if (!callable) callable = "application";
wsgi_file_module = uwsgi_pyimport_by_filename("uwsgi_wsgi_file", filename);
wsgi_file_module = uwsgi_pyimport_by_filename(uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename)), filename);
if (!wsgi_file_module) {
PyErr_Print();
exit(1);
@@ -599,6 +682,8 @@ PyObject *uwsgi_paste_loader(void *arg1) {
PyObject *uwsgi_eval_loader(void *arg1) {
#ifndef UWSGI_PYPY
char *code = (char *) arg1;
PyObject *wsgi_eval_module, *wsgi_eval_callable = NULL;
@@ -654,6 +739,9 @@ PyObject *uwsgi_eval_loader(void *arg1) {
}
return wsgi_eval_callable;
#else
return NULL;
#endif
}
+345 -79
View File
@@ -3,6 +3,8 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_python up;
extern struct http_status_codes hsc[];
#include <glob.h>
extern PyTypeObject uwsgi_InputType;
@@ -12,8 +14,9 @@ struct option uwsgi_python_options[] = {
{"file", required_argument, 0, LONG_ARGS_FILE_CONFIG},
{"eval", required_argument, 0, LONG_ARGS_EVAL_CONFIG},
{"module", required_argument, 0, 'w'},
{"wsgi", required_argument, 0, 'w'},
{"callable", required_argument, 0, LONG_ARGS_CALLABLE},
{"test", required_argument, 0, 'j'},
{"test", required_argument, 0, 'J'},
{"home", required_argument, 0, 'H'},
{"virtualenv", required_argument, 0, 'H'},
{"venv", required_argument, 0, 'H'},
@@ -26,10 +29,17 @@ struct option uwsgi_python_options[] = {
{"pyimport", required_argument, 0, LONG_ARGS_PYIMPORT},
{"py-import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"python-import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"spooler-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-pyimport", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-py-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-python-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"pp", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"pyargv", required_argument, 0, LONG_ARGS_PYARGV},
{"optimize", required_argument, 0, 'O'},
{"paste", required_argument, 0, LONG_ARGS_PASTE},
{"web3", required_argument, 0, LONG_ARGS_WEB3},
{"pump", required_argument, 0, LONG_ARGS_PUMP},
{"wsgi-lite", required_argument, 0, LONG_ARGS_WSGI_LITE},
#ifdef UWSGI_INI
{"ini-paste", required_argument, 0, LONG_ARGS_INI_PASTE},
#endif
@@ -37,7 +47,12 @@ struct option uwsgi_python_options[] = {
{"ignore-script-name", no_argument, &up.ignore_script_name, 1},
{"pep3333-input", no_argument, &up.pep3333_input, 1},
{"reload-os-env", no_argument, &up.reload_os_env, 1},
#ifndef UWSGI_PYPY
{"no-site", no_argument, &Py_NoSiteFlag, 1},
#endif
{"pyshell", no_argument, 0, LONG_ARGS_PYSHELL},
{"python", required_argument, 0, LONG_ARGS_PYTHON_RUN},
{"py", required_argument, 0, LONG_ARGS_PYTHON_RUN},
{0, 0, 0, 0},
};
@@ -60,6 +75,7 @@ struct uwsgi_help_item uwsgi_python_help[] = {
{"file <file>", "use python file instead of python module for configuration"},
{"eval <code>", "evaluate code for app configuration"},
{"ini-paste <inifile>", "path of ini config file that contains paste configuration"},
{"pyshell", "run a python interactive shell in the uwsgi environment (steals a worker)"},
{ 0, 0},
@@ -88,9 +104,14 @@ PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARG
int uwsgi_python_init() {
#ifndef UWSGI_PYPY
char *pyversion = strchr(Py_GetVersion(), '\n');
uwsgi_log("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
#else
uwsgi_log("PyPy version: %s\n", PYPY_VERSION);
#endif
#ifndef UWSGI_PYPY
if (up.home != NULL) {
#ifdef PYTHREE
wchar_t *wpyhome;
@@ -119,9 +140,12 @@ int uwsgi_python_init() {
#endif
Py_OptimizeFlag = up.optimize;
Py_Initialize();
Py_OptimizeFlag = up.optimize;
#endif
up.wsgi_spitout = PyCFunction_New(uwsgi_spit_method, NULL);
up.wsgi_writeout = PyCFunction_New(uwsgi_write_method, NULL);
@@ -144,6 +168,7 @@ int uwsgi_python_init() {
void uwsgi_python_reset_random_seed() {
#ifndef UWSGI_PYPY
PyObject *random_module, *random_dict, *random_seed;
// reinitialize the random seed (thanks Jonas Borgström)
@@ -163,23 +188,34 @@ void uwsgi_python_reset_random_seed() {
}
}
}
#endif
}
void uwsgi_python_post_fork() {
#ifdef UWSGI_SPOOLER
if (uwsgi.shared->spooler_pid > 0) {
if (uwsgi.shared->spooler_pid == getpid()) {
UWSGI_GET_GIL
}
}
#endif
uwsgi_python_reset_random_seed();
#ifndef UWSGI_PYPY
#ifdef UWSGI_EMBEDDED
// call the post_fork_hook
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
if (uwsgi_dict) {
PyObject *pfh = PyDict_GetItemString(uwsgi_dict, "post_fork_hook");
if (pfh) {
python_call(pfh, PyTuple_New(0), 0);
python_call(pfh, PyTuple_New(0), 0, NULL);
}
}
PyErr_Clear();
#endif
#endif
UWSGI_RELEASE_GIL
@@ -187,6 +223,7 @@ UWSGI_RELEASE_GIL
PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
#ifndef UWSGI_PYPY
FILE *pyfile;
struct _node *py_file_node = NULL;
PyObject *py_compiled_node, *py_file_module;
@@ -195,7 +232,7 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
char *real_filename = filename;
if (strncmp(filename, "http://", 7) && strncmp(filename, "sym://", 6)) {
if (!uwsgi_check_scheme(filename)) {
pyfile = fopen(filename, "r");
if (!pyfile) {
@@ -225,7 +262,8 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
if (!py_file_node) {
PyErr_Print();
uwsgi_log("failed to parse file %s\n", real_filename);
free(real_filename);
if (is_a_package)
free(real_filename);
fclose(pyfile);
return NULL;
}
@@ -271,10 +309,12 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
}
return py_file_module;
#else
return NULL;
#endif
}
void init_uwsgi_vars() {
int i;
@@ -283,11 +323,6 @@ void init_uwsgi_vars() {
PyObject *modules = PyImport_GetModuleDict();
PyObject *tmp_module;
#ifdef UWSGI_MINTERPRETERS
char venv_version[15];
PyObject *site_module;
#endif
/* add cwd to pythonpath */
pysys = PyImport_ImportModule("sys");
if (!pysys) {
@@ -310,39 +345,6 @@ void init_uwsgi_vars() {
exit(1);
}
#ifdef UWSGI_MINTERPRETERS
// simulate a pythonhome directive
if (uwsgi.wsgi_req->pyhome_len > 0) {
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len);
#ifdef UWSGI_DEBUG
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->pyhome_len, uwsgi.wsgi_req->pyhome);
#endif
PyDict_SetItemString(pysys_dict, "prefix", venv_path);
PyDict_SetItemString(pysys_dict, "exec_prefix", venv_path);
venv_version[14] = 0;
if (snprintf(venv_version, 15, "/lib/python%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION) == -1) {
return;
}
// check here
PyString_Concat(&venv_path, PyString_FromString(venv_version));
if (PyList_Insert(pypath, 0, venv_path)) {
PyErr_Print();
}
site_module = PyImport_ImportModule("site");
if (site_module) {
PyImport_ReloadModule(site_module);
}
}
#endif
if (PyList_Insert(pypath, 0, UWSGI_PYFROMSTRING(".")) != 0) {
PyErr_Print();
}
@@ -436,12 +438,17 @@ void init_uwsgi_embedded_module() {
exit(1);
}
Py_INCREF((PyObject *) &uwsgi_InputType);
up.embedded_dict = PyModule_GetDict(new_uwsgi_module);
if (!up.embedded_dict) {
uwsgi_log("could not get uwsgi module __dict__\n");
exit(1);
}
// just for safety
Py_INCREF(up.embedded_dict);
if (PyDict_SetItemString(up.embedded_dict, "version", PyString_FromString(UWSGI_VERSION))) {
PyErr_Print();
exit(1);
@@ -523,7 +530,12 @@ void init_uwsgi_embedded_module() {
if (PyDict_Contains(py_opt_dict, PyString_FromString(uwsgi.exported_opts[i]->key))) {
PyObject *py_opt_item = PyDict_GetItemString(py_opt_dict, uwsgi.exported_opts[i]->key);
if (PyList_Check(py_opt_item)) {
PyList_Append(py_opt_item, PyString_FromString(uwsgi.exported_opts[i]->value));
if (uwsgi.exported_opts[i]->value == NULL) {
PyList_Append(py_opt_item, Py_True);
}
else {
PyList_Append(py_opt_item, PyString_FromString(uwsgi.exported_opts[i]->value));
}
}
else {
PyObject *py_opt_list = PyList_New(0);
@@ -553,6 +565,23 @@ void init_uwsgi_embedded_module() {
exit(1);
}
PyObject *py_magic_table = PyDict_New();
uint8_t mtk;
for (i = 0; i <= 0xff; i++) {
// a bit of magic :P
mtk = i;
if (uwsgi.magic_table[i]) {
if (uwsgi.magic_table[i][0] != 0) {
PyDict_SetItem(py_magic_table, PyString_FromStringAndSize((char *) &mtk, 1), PyString_FromString(uwsgi.magic_table[i]));
}
}
}
if (PyDict_SetItemString(up.embedded_dict, "magic_table", py_magic_table)) {
PyErr_Print();
exit(1);
}
#ifdef UNBIT
if (PyDict_SetItemString(up.embedded_dict, "unbit", Py_True)) {
#else
@@ -631,9 +660,19 @@ void init_uwsgi_embedded_module() {
init_uwsgi_module_sharedarea(new_uwsgi_module);
}
init_uwsgi_module_cache(new_uwsgi_module);
if (uwsgi.cache_max_items > 0) {
init_uwsgi_module_cache(new_uwsgi_module);
}
init_uwsgi_module_queue(new_uwsgi_module);
if (uwsgi.queue_size > 0) {
init_uwsgi_module_queue(new_uwsgi_module);
}
#ifdef UWSGI_SNMP
if (uwsgi.snmp) {
init_uwsgi_module_snmp(new_uwsgi_module);
}
#endif
if (up.extension) {
up.extension();
@@ -697,9 +736,16 @@ int uwsgi_python_manage_options(int i, char *optarg) {
uwsgi_log("you can specify at most %d --pymodule-alias options\n", MAX_PYMODULE_ALIAS);
}
return 1;
case LONG_ARGS_PYSHELL:
uwsgi.honour_stdin = 1;
up.pyshell = 1;
return 1;
case LONG_ARGS_PYIMPORT:
uwsgi_string_new_list(&up.import_list, optarg);
return 1;
case LONG_ARGS_SPOOLER_PYIMPORT:
uwsgi_string_new_list(&up.spooler_import_list, optarg);
return 1;
case LONG_ARGS_POST_PYMODULE_ALIAS:
uwsgi_string_new_list(&up.post_pymodule_alias, optarg);
return 1;
@@ -716,7 +762,7 @@ int uwsgi_python_manage_options(int i, char *optarg) {
case LONG_ARGS_PYARGV:
up.argv = optarg;
return 1;
case 'j':
case 'J':
up.test_module = optarg;
return 1;
case 'H':
@@ -732,15 +778,24 @@ int uwsgi_python_manage_options(int i, char *optarg) {
#ifdef UWSGI_INI
case LONG_ARGS_INI_PASTE:
uwsgi.ini = optarg;
if (uwsgi.ini[0] != '/') {
up.paste = uwsgi_concat4("config:", uwsgi.cwd, "/", uwsgi.ini);
uwsgi_string_new_list(&uwsgi.ini,optarg);
if (optarg[0] != '/') {
up.paste = uwsgi_concat4("config:", uwsgi.cwd, "/", optarg);
}
else {
up.paste = uwsgi_concat2("config:", uwsgi.ini);
up.paste = uwsgi_concat2("config:", optarg);
}
return 1;
#endif
case LONG_ARGS_WEB3:
up.web3 = optarg;
return 1;
case LONG_ARGS_PUMP:
up.pump = optarg;
return 1;
case LONG_ARGS_WSGI_LITE:
up.wsgi_lite = optarg;
return 1;
case LONG_ARGS_PASTE:
up.paste = optarg;
return 1;
@@ -752,14 +807,31 @@ int uwsgi_python_manage_options(int i, char *optarg) {
return 0;
}
int uwsgi_python_mount_app(char *mountpoint, char *app) {
int uwsgi_python_mount_app(char *mountpoint, char *app, int regexp) {
uwsgi.wsgi_req->script_name = mountpoint;
uwsgi.wsgi_req->script_name_len = strlen(mountpoint);
int id;
uwsgi.wsgi_req->appid = mountpoint;
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
if (uwsgi.single_interpreter) {
return init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread);
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
return init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL);
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
#ifdef UWSGI_PCRE
int i;
if (regexp && id != -1) {
struct uwsgi_app *ua = &uwsgi_apps[id];
uwsgi_regexp_build(mountpoint, &ua->pattern, &ua->pattern_extra);
if (uwsgi.mywid == 0) {
for(i=1;i<=uwsgi.numproc;i++) {
uwsgi.workers[i].apps[id].pattern = ua->pattern;
uwsgi.workers[i].apps[id].pattern_extra = ua->pattern_extra;
}
}
}
#endif
return id;
}
@@ -775,11 +847,17 @@ char *uwsgi_pythonize(char *orig) {
else if (!strncmp(name, "http://", 7)) {
name+=7;
}
else if (!strncmp(name, "data://", 7)) {
name+=7;
}
len = strlen(name);
for(i=0;i<len;i++) {
if (name[i] == '/') {
name[i] = '.';
if (name[i] == '.') {
name[i] = '_';
}
else if (name[i] == '/') {
name[i] = '_';
}
}
@@ -792,24 +870,56 @@ char *uwsgi_pythonize(char *orig) {
}
void uwsgi_python_spooler_init(void) {
struct uwsgi_string_list *upli = up.spooler_import_list;
UWSGI_GET_GIL
while(upli) {
if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) {
uwsgi_pyimport_by_filename(uwsgi_pythonize(upli->value), upli->value);
}
else {
if (PyImport_ImportModule(upli->value) == NULL) {
PyErr_Print();
}
}
upli = upli->next;
}
UWSGI_RELEASE_GIL
}
void uwsgi_python_init_apps() {
struct http_status_codes *http_sc;
if (uwsgi.async > 1) {
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
#ifndef UWSGI_PYPY
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
#endif
}
init_pyargv();
#ifdef UWSGI_MINTERPRETERS
#ifndef UWSGI_PYPY
#ifdef UWSGI_EMBEDDED
init_uwsgi_embedded_module();
#endif
#endif
#ifdef __linux__
#ifndef PYTHREE
#ifndef UWSGI_PYPY
#ifdef UWSGI_EMBEDDED
uwsgi_init_symbol_import();
#endif
#endif
#endif
if (up.test_module != NULL) {
@@ -885,23 +995,38 @@ void uwsgi_python_init_apps() {
if (up.wsgi_config != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread);
init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.file_config != NULL) {
init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, up.main_thread);
init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.paste != NULL) {
init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, up.main_thread);
init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.eval != NULL) {
init_uwsgi_app(LOADER_EVAL, up.eval, uwsgi.wsgi_req, up.main_thread);
init_uwsgi_app(LOADER_EVAL, up.eval, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.web3 != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.web3, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WEB3);
}
if (up.pump != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.pump, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_PUMP);
// filling http status codes
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = (int) strlen(http_sc->message);
}
}
if (up.wsgi_lite != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.wsgi_lite, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI_LITE);
}
if (uwsgi.profiler) {
#ifndef UWSGI_PYPY
if (!strcmp(uwsgi.profiler, "pycall")) {
PyEval_SetProfile(uwsgi_python_profiler_call, NULL);
}
#endif
}
}
@@ -952,7 +1077,9 @@ void uwsgi_python_enable_threads() {
up.swap_ts = threaded_swap_ts;
up.reset_ts = threaded_reset_ts;
}
uwsgi_log("threads support enabled\n");
}
@@ -963,6 +1090,9 @@ void uwsgi_python_init_thread(int core_id) {
pts = PyThreadState_New(up.main_thread->interp);
pthread_setspecific(up.upt_save_key, (void *) pts);
pthread_setspecific(up.upt_gil_key, (void *) pts);
#ifdef UWSGI_DEBUG
uwsgi_log("pts %d = %p\n", core_id, pts);
#endif
}
@@ -975,16 +1105,16 @@ int uwsgi_python_xml(char *node, char *content) {
}
if (!strcmp("script", node)) {
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("file", node)) {
return init_uwsgi_app(LOADER_FILE, content, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_FILE, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("eval", node)) {
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("wsgi", node)) {
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("module", node)) {
uwsgi.wsgi_req->module = content;
@@ -995,10 +1125,10 @@ int uwsgi_python_xml(char *node, char *content) {
uwsgi.wsgi_req->callable++;
uwsgi.wsgi_req->callable_len = strlen(uwsgi.wsgi_req->callable);
uwsgi.wsgi_req->module_len = strlen(uwsgi.wsgi_req->module);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else {
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
return 1;
}
@@ -1010,12 +1140,13 @@ int uwsgi_python_xml(char *node, char *content) {
else if (!strcmp("callable", node)) {
uwsgi.wsgi_req->callable = content;
uwsgi.wsgi_req->callable_len = strlen(content);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
return 0;
}
#ifndef UWSGI_PYPY
void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
PyThreadState *tstate = PyThreadState_GET();
@@ -1029,6 +1160,57 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
up.current_main_frame = tstate->frame;
}
}
#endif
char *uwsgi_python_code_string(char *id, char *code, char *function, char *key, uint16_t keylen) {
PyObject *cs_module = NULL;
PyObject *cs_dict = NULL;
UWSGI_GET_GIL;
cs_module = PyImport_ImportModule(id);
if (!cs_module) {
PyErr_Clear();
cs_module = uwsgi_pyimport_by_filename(id, code);
}
if (!cs_module) {
UWSGI_RELEASE_GIL;
return NULL;
}
cs_dict = PyModule_GetDict(cs_module);
if (!cs_dict) {
PyErr_Print();
UWSGI_RELEASE_GIL;
return NULL;
}
PyObject *func = PyDict_GetItemString(cs_dict, function);
if (!func) {
uwsgi_log("function %s not available in %s\n", function, code);
PyErr_Print();
UWSGI_RELEASE_GIL;
return NULL;
}
PyObject *args = PyTuple_New(1);
PyTuple_SetItem(args, 0, PyString_FromStringAndSize(key, keylen));
PyObject *ret = python_call(func, args, 0, NULL);
Py_DECREF(args);
if (ret && PyString_Check(ret)) {
char *val = PyString_AsString(ret);
UWSGI_RELEASE_GIL;
return val;
}
UWSGI_RELEASE_GIL;
return NULL;
}
int uwsgi_python_signal_handler(uint8_t sig, void *handler) {
@@ -1046,9 +1228,10 @@ int uwsgi_python_signal_handler(uint8_t sig, void *handler) {
PyTuple_SetItem(args, 0, PyInt_FromLong(sig));
ret = python_call(handler, args, 0);
ret = python_call(handler, args, 0, NULL);
Py_DECREF(args);
if (ret) {
Py_DECREF(ret);
UWSGI_RELEASE_GIL;
return 0;
}
@@ -1060,6 +1243,8 @@ clear:
uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
UWSGI_GET_GIL;
uint8_t i;
PyObject *pyargs = PyTuple_New(argc);
PyObject *ret;
@@ -1073,7 +1258,7 @@ uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
PyTuple_SetItem(pyargs, i, PyString_FromString(argv[i]));
}
ret = python_call((PyObject *) func, pyargs, 0);
ret = python_call((PyObject *) func, pyargs, 0, NULL);
if (ret) {
if (PyString_Check(ret)) {
@@ -1082,6 +1267,7 @@ uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
if (rl <= 0xffff) {
memcpy(buffer, rv, rl);
Py_DECREF(ret);
UWSGI_RELEASE_GIL;
return rl;
}
}
@@ -1090,6 +1276,7 @@ uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
if (PyErr_Occurred())
PyErr_Print();
UWSGI_RELEASE_GIL;
return 0;
@@ -1143,8 +1330,9 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si
PyDict_SetItemString(spool_dict, "body", PyString_FromStringAndSize(body, body_len));
}
PyTuple_SetItem(pyargs, 0, spool_dict);
ret = python_call(spool_func, pyargs, 0);
ret = python_call(spool_func, pyargs, 0, NULL);
if (ret) {
if (!PyInt_Check(ret)) {
// error, retry
@@ -1166,6 +1354,7 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si
return -1;
}
#ifndef UWSGI_PYPY
void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
PyThreadState *tstate = PyThreadState_GET();
@@ -1180,10 +1369,77 @@ void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
}
}
#endif
void uwsgi_python_fixup() {
// set hacky modifier 30
uwsgi.p[30] = uwsgi.p[0];
uwsgi.p[30] = uwsgi_malloc( sizeof(struct uwsgi_plugin) );
memcpy(uwsgi.p[30], uwsgi.p[0], sizeof(struct uwsgi_plugin) );
uwsgi.p[30]->init_thread = NULL;
}
void uwsgi_python_hijack(void) {
// the pyshell will be execute only in the first worker
#ifndef UWSGI_PYPY
if (up.pyshell && uwsgi.mywid == 1) {
// re-map stdin to stdout and stderr if we are logging to a file
if (uwsgi.logfile) {
if (dup2(0, 1) < 0) {
uwsgi_error("dup2()");
}
if (dup2(0, 2) < 0) {
uwsgi_error("dup2()");
}
}
UWSGI_GET_GIL;
PyImport_ImportModule("readline");
PyRun_InteractiveLoop(stdin, "uwsgi");
exit(0);
}
#endif
}
int uwsgi_python_mule(char *opt) {
if (uwsgi_endswith(opt, ".py")) {
UWSGI_GET_GIL;
if (uwsgi_pyimport_by_filename("__main__", opt) == NULL) {
return 0;
}
UWSGI_RELEASE_GIL;
return 1;
}
return 0;
}
int uwsgi_python_mule_msg(char *message, size_t len) {
UWSGI_GET_GIL;
PyObject *mule_msg_hook = PyDict_GetItemString(up.embedded_dict, "mule_msg_hook");
if (!mule_msg_hook) {
// ignore
UWSGI_RELEASE_GIL;
return 0;
}
PyObject *pyargs = PyTuple_New(1);
PyTuple_SetItem(pyargs, 0, PyString_FromStringAndSize(message, len));
PyObject *ret = python_call(mule_msg_hook, pyargs, 0, NULL);
Py_DECREF(pyargs);
if (ret) {
Py_DECREF(ret);
}
if (PyErr_Occurred())
PyErr_Print();
UWSGI_RELEASE_GIL;
return 1;
}
struct uwsgi_plugin python_plugin = {
@@ -1195,7 +1451,7 @@ struct uwsgi_plugin python_plugin = {
.post_fork = uwsgi_python_post_fork,
.options = uwsgi_python_options,
.manage_opt = uwsgi_python_manage_options,
.short_options = "w:O:H:j:",
.short_options = "w:O:H:J:",
.request = uwsgi_request_wsgi,
.after_request = uwsgi_after_request_wsgi,
.init_apps = uwsgi_python_init_apps,
@@ -1211,14 +1467,24 @@ struct uwsgi_plugin python_plugin = {
.magic = uwsgi_python_magic,
#ifndef UWSGI_PYPY
.suspend = uwsgi_python_suspend,
.resume = uwsgi_python_resume,
#endif
.hijack_worker = uwsgi_python_hijack,
.spooler_init = uwsgi_python_spooler_init,
.signal_handler = uwsgi_python_signal_handler,
.rpc = uwsgi_python_rpc,
.mule = uwsgi_python_mule,
.mule_msg = uwsgi_python_mule_msg,
.spooler = uwsgi_python_spooler,
.code_string = uwsgi_python_code_string,
.help = uwsgi_python_help,
};
+25 -5
View File
@@ -8,7 +8,7 @@ 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) {
PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi_request *wsgi_req) {
PyObject *pyret;
@@ -22,7 +22,13 @@ PyObject *python_call(PyObject *callable, PyObject *args, int catch) {
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
uwsgi_log("Memory Error detected !!!\n");
}
uwsgi.workers[uwsgi.mywid].exceptions++;
// this can be in a spooler or in the master
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].exceptions++;
if (wsgi_req) {
uwsgi_apps[wsgi_req->app_id].exceptions++;
}
}
if (!catch) {
PyErr_Print();
}
@@ -39,7 +45,7 @@ PyObject *python_call(PyObject *callable, PyObject *args, int catch) {
int uwsgi_python_call(struct wsgi_request *wsgi_req, PyObject *callable, PyObject *args) {
wsgi_req->async_result = python_call(callable, args, 0);
wsgi_req->async_result = python_call(callable, args, 0, wsgi_req);
if (wsgi_req->async_result) {
while ( manage_python_response(wsgi_req) != UWSGI_OK) {
@@ -66,8 +72,9 @@ void init_pyargv() {
up.py_argv[0] = "uwsgi";
#endif
if (up.argv != NULL && !up.argc) {
up.argc++;
up.argc = 1;
if (up.argv != NULL) {
#ifdef PYTHREE
wchar_t *wcargv = malloc( sizeof( wchar_t ) * (strlen(up.argv)+1));
if (!wcargv) {
@@ -98,7 +105,20 @@ void init_pyargv() {
}
}
#ifndef UWSGI_PYPY
PySys_SetArgv(up.argc, up.py_argv);
#endif
PyObject *sys_dict = get_uwsgi_pydict("sys");
if (!sys_dict) {
uwsgi_log("unable to load python sys module !!!\n");
exit(1);
}
#ifdef PYTHREE
PyDict_SetItemString(sys_dict, "executable", PyUnicode_FromString(uwsgi.binary_path));
#else
PyDict_SetItemString(sys_dict, "executable", PyString_FromString(uwsgi.binary_path));
#endif
}
+221 -17
View File
@@ -1,6 +1,6 @@
#include "uwsgi_python.h"
#ifndef PYTHREE
#ifndef UWSGI_PYPY
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
@@ -17,6 +17,7 @@ struct _symzipimporter {
PyObject *items;
} uwsgi_symbol_zip_importer_object;
static char *symbolize(char *name) {
char *base = uwsgi_concat2(name, "");
@@ -200,9 +201,14 @@ static PyObject* symzipimporter_load_module(PyObject *self, PyObject *args) {
PyObject *source = PyObject_CallMethod(this->zip, "read", "(s)", filename);
free(filename);
PyObject *code = Py_CompileString(PyString_AsString(source), modname, Py_file_input);
if (!code) {
PyErr_Print();
goto shit;
}
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
Py_DECREF(code);
shit:
Py_DECREF(source);
free(modname);
return mod;
@@ -230,9 +236,14 @@ static PyObject* symzipimporter_load_module(PyObject *self, PyObject *args) {
PyObject *source = PyObject_CallMethod(this->zip, "read", "(s)", filename);
free(filename);
PyObject *code = Py_CompileString(PyString_AsString(source), modname, Py_file_input);
if (!code) {
PyErr_Print();
goto shit2;
}
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
Py_DECREF(code);
shit2:
Py_DECREF(source);
free(modname);
return mod;
@@ -305,9 +316,14 @@ static PyObject* symimporter_load_module(PyObject *self, PyObject *args) {
modname = uwsgi_concat3("sym://", fullname2, "_py");
code = Py_CompileString(source, modname, Py_file_input);
if (!code) {
PyErr_Print();
goto shit;
}
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
Py_DECREF(code);
shit:
free(source);
free(modname);
free(fullname2);
@@ -333,9 +349,14 @@ static PyObject* symimporter_load_module(PyObject *self, PyObject *args) {
PyDict_SetItemString(dict, "__loader__", self);
code = Py_CompileString(source, modname, Py_file_input);
if (!code) {
PyErr_Print();
goto shit2;
}
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
Py_DECREF(code);
shit2:
free(source);
free(modname);
free(fullname2);
@@ -350,17 +371,19 @@ clear:
}
static PyMethodDef symimporter_methods[] = {
{"find_module", symimporter_find_module, METH_VARARGS},
{"load_module", symimporter_load_module, METH_VARARGS},
{"find_module", symimporter_find_module, METH_VARARGS},
{"load_module", symimporter_load_module, METH_VARARGS},
{ NULL, NULL },
};
static PyMethodDef symzipimporter_methods[] = {
{"find_module", symzipimporter_find_module, METH_VARARGS},
{"load_module", symzipimporter_load_module, METH_VARARGS},
{"find_module", symzipimporter_find_module, METH_VARARGS},
{"load_module", symzipimporter_load_module, METH_VARARGS},
{ NULL, NULL },
};
static void uwsgi_symimporter_free(struct _symimporter *self) {
PyObject_Del(self);
PyObject_Del(self);
}
@@ -403,9 +426,130 @@ static PyTypeObject SymImporter_Type = {
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
PyObject_GC_Del, /* tp_free */
0, /* tp_free */
};
static int
zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
{
char *name;
char *prefix = NULL;
int len = 0;
if (!PyArg_ParseTuple(args, "s", &name))
return -1;
// avoid GC !!!
name = uwsgi_concat2(name, "");
if (uwsgi_check_scheme(name)) {
prefix = uwsgi_get_last_char(name, '/');
prefix = uwsgi_get_last_char(prefix, ':');
}
else {
prefix = uwsgi_get_last_char(name, ':');
}
if (prefix) {
prefix[0] = 0;
}
char *body = uwsgi_open_and_read(name, &len, 0, NULL);
if (!body) {
return -1;
}
PyObject *stringio = PyImport_ImportModule("StringIO");
if (!stringio) {
return -1;
}
#ifdef PYTHREE
PyObject *source_code = PyObject_CallMethodObjArgs(stringio, PyString_FromString("StringIO"), PyString_FromStringAndSize(body, len));
#else
PyObject *stringio_dict = PyModule_GetDict(stringio);
if (!stringio_dict) {
return -1;
}
PyObject *stringio_stringio = PyDict_GetItemString(stringio_dict, "StringIO");
if (!stringio_stringio) {
return -1;
}
PyObject *stringio_args = PyTuple_New(1);
PyTuple_SetItem(stringio_args, 0, PyString_FromStringAndSize(body, len));
PyObject *source_code = PyInstance_New(stringio_stringio, stringio_args, NULL);
#endif
if (!source_code) {
return -1;
}
PyObject *zipfile = PyImport_ImportModule("zipfile");
if (!zipfile) {
PyErr_Print();
return -1;
}
#ifdef PYTHREE
self->zip = PyObject_CallMethodObjArgs(zipfile, PyString_FromString("ZipFile"), source_code);
#else
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
if (!zipfile_dict) {
return -1;
}
PyObject *zipfile_zipfile = PyDict_GetItemString(zipfile_dict, "ZipFile");
if (!zipfile_zipfile) {
return -1;
}
PyObject *zipfile_args = PyTuple_New(1);
PyTuple_SetItem(zipfile_args, 0, source_code);
self->zip = PyInstance_New(zipfile_zipfile, zipfile_args, NULL);
#endif
if (!self->zip) {
return -1;
}
Py_INCREF(self->zip);
self->items = PyObject_CallMethod(self->zip, "namelist", NULL);
if (!self->items) {
return -1;
}
Py_INCREF(self->items);
self->prefix = NULL;
if (prefix) {
self->prefix = prefix+1;
prefix[0] = ':';
}
return 0;
}
static int
symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
{
@@ -439,55 +583,57 @@ symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds
PyObject *stringio = PyImport_ImportModule("StringIO");
if (!stringio) {
PyErr_Print();
return -1;
}
#ifdef PYTHREE
PyObject *source_code = PyObject_CallMethodObjArgs(stringio, PyString_FromString("StringIO"), PyString_FromStringAndSize(code_start, code_end-code_start));
#else
PyObject *stringio_dict = PyModule_GetDict(stringio);
if (!stringio_dict) {
PyErr_Print();
return -1;
}
PyObject *stringio_stringio = PyDict_GetItemString(stringio_dict, "StringIO");
if (!stringio_stringio) {
PyErr_Print();
return -1;
}
PyObject *stringio_args = PyTuple_New(1);
PyTuple_SetItem(stringio_args, 0, PyString_FromStringAndSize(code_start, code_end-code_start));
PyObject *source_code = PyInstance_New(stringio_stringio, stringio_args, NULL);
#endif
if (!source_code) {
PyErr_Print();
return -1;
}
PyObject *zipfile = PyImport_ImportModule("zipfile");
if (!zipfile) {
PyErr_Print();
return -1;
}
#ifdef PYTHREE
self->zip = PyObject_CallMethodObjArgs(zipfile, PyString_FromString("ZipFile"), source_code);
#else
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
if (!zipfile_dict) {
PyErr_Print();
return -1;
}
PyObject *zipfile_zipfile = PyDict_GetItemString(zipfile_dict, "ZipFile");
if (!zipfile_zipfile) {
PyErr_Print();
return -1;
}
PyObject *zipfile_args = PyTuple_New(1);
PyTuple_SetItem(zipfile_args, 0, source_code);
self->zip = PyInstance_New(zipfile_zipfile, zipfile_args, NULL);
#endif
if (!self->zip) {
PyErr_Print();
return -1;
}
@@ -495,7 +641,6 @@ symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds
self->items = PyObject_CallMethod(self->zip, "namelist", NULL);
if (!self->items) {
PyErr_Print();
return -1;
}
@@ -550,9 +695,52 @@ static PyTypeObject SymZipImporter_Type = {
(initproc) symzipimporter_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
PyObject_GC_Del, /* tp_free */
0, /* tp_free */
};
static PyTypeObject ZipImporter_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"uwsgi.ZipImporter",
sizeof(struct _symzipimporter),
0, /* tp_itemsize */
(destructor) uwsgi_symimporter_free, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT,
"uwsgi zip importer", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
symzipimporter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc) zipimporter_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, /* tp_free */
};
int uwsgi_init_symbol_import() {
@@ -563,6 +751,12 @@ int uwsgi_init_symbol_import() {
exit(1);
}
if (PyType_Ready(&ZipImporter_Type) < 0) {
PyErr_Print();
uwsgi_log("unable to initialize zip importer module\n");
exit(1);
}
if (PyType_Ready(&SymZipImporter_Type) < 0) {
PyErr_Print();
uwsgi_log("unable to initialize symbols zip importer module\n");
@@ -576,6 +770,7 @@ int uwsgi_init_symbol_import() {
exit(1);
}
Py_INCREF((PyObject *)&SymImporter_Type);
if (PyModule_AddObject(uwsgi_em, "SymbolsImporter",
(PyObject *)&SymImporter_Type) < 0) {
PyErr_Print();
@@ -583,6 +778,15 @@ int uwsgi_init_symbol_import() {
exit(1);
}
Py_INCREF((PyObject *)&ZipImporter_Type);
if (PyModule_AddObject(uwsgi_em, "ZipImporter",
(PyObject *)&ZipImporter_Type) < 0) {
PyErr_Print();
uwsgi_log("unable to initialize zip importer object\n");
exit(1);
}
Py_INCREF((PyObject *)&SymZipImporter_Type);
if (PyModule_AddObject(uwsgi_em, "SymbolsZipImporter",
(PyObject *)&SymZipImporter_Type) < 0) {
PyErr_Print();
File diff suppressed because it is too large Load Diff
+46 -6
View File
@@ -15,9 +15,22 @@
#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 PYTHON_APP_TYPE_WSGI 0
#define PYTHON_APP_TYPE_WEB3 1
#define PYTHON_APP_TYPE_WSGI2 2
#define PYTHON_APP_TYPE_PUMP 3
#define PYTHON_APP_TYPE_WSGI_LITE 4
#if PY_MINOR_VERSION == 4 && PY_MAJOR_VERSION == 2
#define Py_ssize_t ssize_t
#define UWSGI_PYTHON_OLD
#endif
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 7
@@ -83,6 +96,18 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define LOADER_MAX 8
#define UWSGI_PY_READLINE_BUFSIZE 1024
typedef struct uwsgi_Input {
PyObject_HEAD
char readline[UWSGI_PY_READLINE_BUFSIZE];
size_t readline_size;
size_t readline_max_size;
size_t readline_pos;
size_t pos;
struct wsgi_request *wsgi_req;
} uwsgi_Input;
struct uwsgi_python {
char *home;
@@ -104,8 +129,11 @@ struct uwsgi_python {
char *test_module;
int pyshell;
struct uwsgi_string_list *python_path;
struct uwsgi_string_list *import_list;
struct uwsgi_string_list *spooler_import_list;
struct uwsgi_string_list *post_pymodule_alias;
PyObject *loader_dict;
@@ -116,6 +144,9 @@ struct uwsgi_python {
char *paste;
char *eval;
char *web3;
char *pump;
char *wsgi_lite;
char *callable;
@@ -152,6 +183,7 @@ struct uwsgi_python {
void (*extension)(void);
int reload_os_env;
};
@@ -165,7 +197,7 @@ void uwsgi_paste_config(char *);
void uwsgi_file_config(char *);
void uwsgi_eval_config(char *);
int init_uwsgi_app(int, void *, struct wsgi_request *wsgi_req, PyThreadState *);
int init_uwsgi_app(int, void *, struct wsgi_request *, PyThreadState *, int);
PyObject *py_eventfd_read(PyObject *, PyObject *);
@@ -174,7 +206,7 @@ PyObject *py_eventfd_write(PyObject *, PyObject *);
int manage_python_response(struct wsgi_request *);
int uwsgi_python_call(struct wsgi_request *, PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *, int);
PyObject *python_call(PyObject *, PyObject *, int, struct wsgi_request *);
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *);
@@ -187,10 +219,11 @@ PyObject *py_uwsgi_spit(PyObject *, PyObject *);
void init_pyargv(void);
#ifdef UWSGI_WEB3
void *uwsgi_request_subhandler_web3(struct wsgi_request *, struct uwsgi_app *);
int uwsgi_response_subhandler_web3(struct wsgi_request *);
#endif
void *uwsgi_request_subhandler_pump(struct wsgi_request *, struct uwsgi_app *);
int uwsgi_response_subhandler_pump(struct wsgi_request *);
PyObject *uwsgi_uwsgi_loader(void *);
PyObject *uwsgi_dyn_loader(void *);
@@ -220,6 +253,7 @@ void init_uwsgi_module_spooler(PyObject *);
void init_uwsgi_module_sharedarea(PyObject *);
void init_uwsgi_module_cache(PyObject *);
void init_uwsgi_module_queue(PyObject *);
void init_uwsgi_module_snmp(PyObject *);
PyObject *uwsgi_pyimport_by_filename(char *, char *);
@@ -232,8 +266,14 @@ int uwsgi_python_profiler_call(PyObject *, PyFrameObject *, int, PyObject *);
void uwsgi_python_reset_random_seed(void);
char *uwsgi_pythonize(char *);
#ifdef UWSGI_PYPY
#undef UWSGI_MINTERPRETERS
#endif
#define uwsgi_pyexit {PyErr_Print();exit(1);}
#ifdef __linux__
#ifndef PYTHREE
int uwsgi_init_symbol_import(void);
#endif
#endif
+25 -17
View File
@@ -3,29 +3,37 @@ import os,sys
from distutils import sysconfig
NAME='python'
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter']
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter']
#OBJ_LIST = ['/usr/lib/libpython2.6.a']
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
if 'pypy_version_info' in sys.__dict__:
CFLAGS.append('-DUWSGI_PYPY')
LDFLAGS = []
LIBS = sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
if not 'UWSGI_PYTHON_NOLIB' in os.environ:
LIBS = sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
LIBS.append('-L' + sysconfig.get_config_var('LIBPL'))
else:
try:
LDFLAGS.append("-L%s" % sysconfig.get_config_var('LIBDIR'))
os.environ['LD_RUN_PATH'] = "%s" % (sysconfig.get_config_var('LIBDIR'))
except:
LDFLAGS.append("-L%s/lib" % sysconfig.PREFIX)
os.environ['LD_RUN_PATH'] = "%s/lib" % sysconfig.PREFIX
version = sysconfig.get_config_var('VERSION')
try:
version = version + sys.abiflags
except:
pass
LIBS.append('-lpython' + version)
else:
try:
LDFLAGS.append("-L%s" % sysconfig.get_config_var('LIBDIR'))
os.environ['LD_RUN_PATH'] = "%s" % (sysconfig.get_config_var('LIBDIR'))
except:
LDFLAGS.append("-L%s/lib" % sysconfig.PREFIX)
os.environ['LD_RUN_PATH'] = "%s/lib" % sysconfig.PREFIX
version = sysconfig.get_config_var('VERSION')
try:
version = version + sys.abiflags
except:
pass
LIBS.append('-lpython' + version)
LIBS = []
#if str(PYLIB_PATH) != '':
# libs.insert(0,'-L' + PYLIB_PATH)
+131 -53
View File
@@ -1,20 +1,70 @@
#include "uwsgi.h"
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern PyTypeObject uwsgi_InputType;
void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
PyObject *zero, *wsgi_socket;
PyObject *zero;
wsgi_socket = PyFile_FromFile(wsgi_req->async_post, "web3_input", "r", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "web3.input", wsgi_socket);
Py_DECREF(wsgi_socket);
int i;
PyObject *pydictkey, *pydictvalue;
char *path_info;
zero = PyTuple_New(2);
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
PyDict_SetItemString(wsgi_req->async_environ, "web3.version", zero);
Py_DECREF(zero);
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
#ifdef PYTHREE
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
wsgi_req->uh.modifier1 = 0;
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
if (pydictvalue) {
if (PyString_Check(pydictvalue)) {
path_info = PyString_AsString(pydictvalue);
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
}
}
}
}
}
// if async_post is mapped as a file, directly use it as wsgi.input
if (wsgi_req->async_post) {
#ifdef PYTHREE
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "web3_input", "rb", 0, NULL, NULL, NULL, 0);
#else
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "web3_input", "r", NULL);
#endif
}
else {
// create wsgi.input custom object
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
}
PyDict_SetItemString(wsgi_req->async_environ, "web3.input", wsgi_req->async_input);
PyDict_SetItemString(wsgi_req->async_environ, "web3.version", wi->gateway_version);
zero = PyFile_FromFile(stderr, "web3_input", "w", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "web3.errors", zero);
@@ -31,35 +81,53 @@ void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_
}
if (wsgi_req->scheme_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
zero = PyString_FromString("https");
zero = UWSGI_PYFROMSTRING("https");
}
else {
zero = PyString_FromString("http");
zero = UWSGI_PYFROMSTRING("http");
}
}
else {
zero = PyString_FromString("http");
zero = UWSGI_PYFROMSTRING("http");
}
PyDict_SetItemString(wsgi_req->async_environ, "web3.url_scheme", zero);
Py_DECREF(zero);
wsgi_req->async_app = wi->wsgi_callable;
wsgi_req->async_app = wi->callable;
PyDict_SetItemString(uwsgi.embedded_dict, "env", wsgi_req->async_environ);
// export .env only in non-threaded mode
if (uwsgi.threads < 2) {
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
}
// TODO: fix this
//PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", uwsgi_version);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
if (uwsgi.cores > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
}
// cache this ?
if (uwsgi.cluster_fd >= 0) {
zero = PyString_FromString(uwsgi.cluster);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
Py_DECREF(zero);
zero = PyString_FromString(uwsgi.hostname);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero);
Py_DECREF(zero);
}
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
// call
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions);
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
}
@@ -68,16 +136,7 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
PyObject *pychunk;
ssize_t wsize;
// return or yield ? (PyString on python2 PyBytes on python3)
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
uwsgi_error("write()");
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
UWSGI_GET_GIL
// ok its a yield
if (!wsgi_req->async_placeholder) {
@@ -86,19 +145,51 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
uwsgi_log("invalid Web3 response.\n");
goto clear;
}
if (py_uwsgi_spit(NULL, (PyObject *)wsgi_req->async_result) == Py_None) {
wsgi_req->async_placeholder = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 0);
Py_INCREF((PyObject *)wsgi_req->async_placeholder);
PyObject *spit_args = PyTuple_New(2);
PyObject *status = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 1);
Py_INCREF(status);
PyTuple_SetItem(spit_args, 0, status);
PyObject *headers = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 2);
Py_INCREF(headers);
PyTuple_SetItem(spit_args, 1, headers);
if (py_uwsgi_spit(NULL, spit_args) == Py_None) {
Py_DECREF(spit_args);
goto clear;
}
wsgi_req->async_result = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 0);
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_result );
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;
}
wsgi_req->response_size += wsize;
goto clear;
}
PyObject *tmp = (PyObject *)wsgi_req->async_placeholder;
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_placeholder );
Py_DECREF(tmp);
if (!wsgi_req->async_placeholder) {
goto clear2;
goto clear;
}
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
}
@@ -119,9 +210,8 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
}
if (PyString_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
uwsgi_error("write()");
Py_DECREF(pychunk);
goto clear;
@@ -131,34 +221,22 @@ int uwsgi_response_subhandler_web3(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);
}
if (wsgi_req->async_post && !wsgi_req->fd_closed) {
fclose(wsgi_req->async_post);
if (!uwsgi.post_buffering || wsgi_req->post_cl <= (size_t) uwsgi.post_buffering) {
wsgi_req->fd_closed = 1;
}
}
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
clear2:
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
#ifdef UWSGI_DEBUG
if (wsgi_req->async_placeholder) {
uwsgi_debug("wsgi_req->async_placeholder: %d\n", ((PyObject *)wsgi_req->async_placeholder)->ob_refcnt);
}
if (wsgi_req->async_result) {
uwsgi_debug("wsgi_req->async_result: %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
}
if (wsgi_req->async_app) {
uwsgi_debug("wsgi_req->async_app: %d\n", ((PyObject *)wsgi_req->async_app)->ob_refcnt);
}
#endif
UWSGI_RELEASE_GIL
return UWSGI_OK;
}
+49 -145
View File
@@ -4,16 +4,6 @@ extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
typedef struct uwsgi_Input {
PyObject_HEAD
char readline[1024];
size_t readline_size;
size_t readline_max_size;
size_t readline_pos;
size_t pos;
struct wsgi_request *wsgi_req;
} uwsgi_Input;
PyObject *uwsgi_Input_iter(PyObject *self) {
Py_INCREF(self);
return self;
@@ -56,13 +46,13 @@ PyObject *uwsgi_Input_getline(uwsgi_Input *self) {
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data");
}
if (self->readline_max_size > 0 && self->readline_max_size < 1024) {
if (self->readline_max_size > 0 && self->readline_max_size < UWSGI_PY_READLINE_BUFSIZE) {
rlen = read(wsgi_req->poll.fd, self->readline, self->readline_max_size);
}
else {
rlen = read(wsgi_req->poll.fd, self->readline, 1024);
rlen = read(wsgi_req->poll.fd, self->readline, UWSGI_PY_READLINE_BUFSIZE);
}
if (rlen < 0) {
if (rlen <= 0) {
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data");
}
@@ -166,7 +156,7 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
}
rlen = read(self->wsgi_req->poll.fd, tmp_buf+tmp_pos, remains);
if (rlen < 0) {
if (rlen <= 0) {
free(tmp_buf);
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data");
@@ -221,12 +211,18 @@ static PyObject *uwsgi_Input_close(uwsgi_Input *self, PyObject *args) {
return Py_None;
}
static PyObject *uwsgi_Input_fileno(uwsgi_Input *self, PyObject *args) {
return PyInt_FromLong(self->wsgi_req->poll.fd);
}
static PyMethodDef uwsgi_Input_methods[] = {
{ "read", (PyCFunction)uwsgi_Input_read, METH_VARARGS, 0 },
{ "readline", (PyCFunction)uwsgi_Input_readline, METH_VARARGS, 0 },
{ "readlines", (PyCFunction)uwsgi_Input_readlines, METH_VARARGS, 0 },
// add close to allow mod_wsgi compatibility
{ "close", (PyCFunction)uwsgi_Input_close, METH_VARARGS, 0 },
{ "fileno", (PyCFunction)uwsgi_Input_fileno, METH_VARARGS, 0 },
{ NULL, NULL}
};
@@ -327,16 +323,10 @@ PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
int i;
PyObject *pydictkey, *pydictvalue;
char *path_info;
struct uwsgi_app *wi;
int tmp_stderr;
char *what;
int what_len;
int free_appid = 0;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
@@ -363,7 +353,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
/* Standard WSGI request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log( "Invalid WSGI request. skip.\n");
uwsgi_log( "Empty python request. skip.\n");
return -1;
}
@@ -372,76 +362,59 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
if (!up.ignore_script_name) {
if (!wsgi_req->script_name)
wsgi_req->script_name = "";
if (wsgi_req->appid_len == 0) {
if (!up.ignore_script_name) {
wsgi_req->appid = wsgi_req->script_name;
wsgi_req->appid_len = wsgi_req->script_name_len;
}
if (uwsgi.vhost) {
what = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
what_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
wsgi_req->appid = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
wsgi_req->appid_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
#ifdef UWSGI_DEBUG
uwsgi_debug("VirtualHost SCRIPT_NAME=%s\n", what);
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
#endif
free_appid = 1;
}
else {
what = wsgi_req->script_name;
what_len = wsgi_req->script_name_len;
}
}
if ( (wsgi_req->app_id = uwsgi_get_app_id(what, what_len, 0)) == -1) {
if (wsgi_req->script_name_len > 1 || uwsgi.default_app < 0 || uwsgi.vhost) {
/* unavailable app for this SCRIPT_NAME */
wsgi_req->app_id = -1;
if (wsgi_req->script_len > 0
|| wsgi_req->module_len > 0
|| wsgi_req->file_len > 0
|| wsgi_req->paste_len > 0
) {
// this part must be heavy locked in threaded modes
if (uwsgi.threads > 1) {
pthread_mutex_lock(&up.lock_pyloaders);
}
UWSGI_GET_GIL
if (uwsgi.single_interpreter) {
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, up.main_thread);
}
else {
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, NULL);
}
UWSGI_RELEASE_GIL
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&up.lock_pyloaders);
}
}
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
wsgi_req->app_id = uwsgi.default_app;
if (uwsgi.no_default_app) {
wsgi_req->app_id = -1;
}
if (wsgi_req->dynamic) {
// this part must be heavy locked in threaded modes
if (uwsgi.threads > 1) {
pthread_mutex_lock(&up.lock_pyloaders);
}
UWSGI_GET_GIL
if (uwsgi.single_interpreter) {
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
else {
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
}
UWSGI_RELEASE_GIL
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&up.lock_pyloaders);
}
}
if (uwsgi.vhost) {
free(what);
}
}
else {
wsgi_req->app_id = 0;
}
if (free_appid) {
free(wsgi_req->appid);
}
if (wsgi_req->app_id == -1) {
// use default app ?
if (!uwsgi.no_default_app && uwsgi.default_app >= 0) {
wsgi_req->app_id = uwsgi.default_app;
}
else {
internal_server_error(wsgi_req, "wsgi application not found");
goto clear2;
}
internal_server_error(wsgi_req, "Python application not found");
goto clear2;
}
wi = &uwsgi.apps[wsgi_req->app_id];
wi = &uwsgi_apps[wsgi_req->app_id];
up.swap_ts(wsgi_req, wi);
@@ -455,21 +428,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
if (wsgi_req->protocol_len < 5) {
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req, "invalid HTTP protocol !!!");
goto clear;
}
if (strncmp(wsgi_req->protocol, "HTTP/", 5)) {
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req, "invalid HTTP protocol !!!");
goto clear;
}
#ifdef UWSGI_ASYNC
wsgi_req->async_environ = wi->environ[wsgi_req->async_id];
wsgi_req->async_args = wi->args[wsgi_req->async_id];
@@ -485,60 +443,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
Py_INCREF((PyObject *)wsgi_req->async_environ);
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
#ifdef PYTHREE
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
wsgi_req->uh.modifier1 = 0;
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
if (pydictvalue) {
if (PyString_Check(pydictvalue)) {
path_info = PyString_AsString(pydictvalue);
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
}
}
}
}
}
// if async_post is mapped as a file, directly use it as wsgi.input
if (wsgi_req->async_post) {
#ifdef PYTHREE
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "wsgi_input", "rb", 0, NULL, NULL, NULL, 0);
#else
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
#endif
}
else {
// create wsgi.input custom object
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
}
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input);
wsgi_req->async_result = wi->request_subhandler(wsgi_req, wi);
UWSGI_RELEASE_GIL
+2 -7
View File
@@ -38,7 +38,8 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
// in this way, error will be reported to the log
PyErr_Restore(exc_type, exc_val, exc_tb);
goto clear;
// the error is reported, let's continue...
//goto clear;
}
}
@@ -190,9 +191,6 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
UWSGI_RELEASE_GIL
iov_ret = wsgi_req->socket->proto_writev_header(wsgi_req, iov_ptr, iov_size);
UWSGI_GET_GIL
if (iov_ret < 0) {
uwsgi_error("writev()");
}
wsgi_req->headers_size += iov_ret;
iov_ptr += iov_size;
remains -= iov_size;
@@ -201,9 +199,6 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
UWSGI_RELEASE_GIL
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, j + 1);
UWSGI_GET_GIL
if (wsgi_req->headers_size < 0) {
uwsgi_error("writev()");
}
#endif
//uwsgi_log("%d %p\n", wsgi_req->poll.fd, up.wsgi_writeout);
+86 -25
View File
@@ -2,19 +2,74 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern PyTypeObject uwsgi_InputType;
void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
PyObject *zero;
int i;
PyObject *pydictkey, *pydictvalue;
char *path_info;
//static PyObject *uwsgi_version = NULL;
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
#ifdef PYTHREE
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
/*
if (uwsgi_version == NULL) {
uwsgi_version = PyString_FromString(UWSGI_VERSION);
}
*/
#ifdef UWSGI_DEBUG
uwsgi_log("%p %d %p %d\n", pydictkey, wsgi_req->hvec[i].iov_len, pydictvalue, wsgi_req->hvec[i + 1].iov_len);
#endif
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
wsgi_req->uh.modifier1 = 0;
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
if (pydictvalue) {
if (PyString_Check(pydictvalue)) {
path_info = PyString_AsString(pydictvalue);
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
}
}
}
}
}
#ifndef UWSGI_PYPY
// if async_post is mapped as a file, directly use it as wsgi.input
if (wsgi_req->async_post) {
#ifdef PYTHREE
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "wsgi_input", "rb", 0, NULL, NULL, NULL, 0);
#else
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
#endif
}
else {
// create wsgi.input custom object
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
}
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);
@@ -28,19 +83,18 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
}
#endif
// cache this
zero = PyTuple_New(2);
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", zero);
Py_DECREF(zero);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", wi->gateway_version);
zero = PyFile_FromFile(stderr, "wsgi_input", "w", NULL);
#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);
if (uwsgi.threads > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multithread", Py_True);
}
@@ -55,18 +109,18 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
}
if (wsgi_req->scheme_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
zero = PyString_FromString("https");
zero = UWSGI_PYFROMSTRING("https");
}
else {
zero = PyString_FromString("http");
zero = UWSGI_PYFROMSTRING("http");
}
}
else {
zero = PyString_FromString("http");
zero = UWSGI_PYFROMSTRING("http");
}
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
Py_DECREF(zero);
@@ -74,19 +128,23 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
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
zero = PyString_FromString(UWSGI_VERSION);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", zero);
Py_DECREF(zero);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
if (uwsgi.cores > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
zero = PyInt_FromLong(wsgi_req->async_id);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", zero);
Py_DECREF(zero);
}
// cache this ?
if (uwsgi.cluster_fd >= 0) {
zero = PyString_FromString(uwsgi.cluster);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
@@ -96,9 +154,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
Py_DECREF(zero);
}
zero = PyString_FromString(uwsgi.hostname);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", zero);
Py_DECREF(zero);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
#ifdef UWSGI_ROUTING
@@ -113,7 +169,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
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);
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions, wsgi_req);
}
int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
@@ -138,7 +194,11 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
#ifdef UWSGI_SENDFILE
#ifdef __FreeBSD__
if ( ((wsgi_req->sendfile_obj == wsgi_req->async_result) || ( wsgi_req->sendfile_fd_size > 0 && wsgi_req->response_size < wsgi_req->sendfile_fd_size)) && wsgi_req->sendfile_fd != -1) {
#else
if (wsgi_req->sendfile_obj == wsgi_req->async_result && wsgi_req->sendfile_fd != -1) {
#endif
sf_len = uwsgi_sendfile(wsgi_req);
if (sf_len < 1) goto clear;
wsgi_req->response_size += sf_len;
@@ -180,6 +240,7 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
uwsgi_log("Memory Error detected !!!\n");
}
uwsgi.workers[uwsgi.mywid].exceptions++;
uwsgi_apps[wsgi_req->app_id].exceptions++;
PyErr_Print();
}
goto clear;
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python24'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
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')
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python25'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
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')
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python26'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
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')
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python27'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
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')
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python30'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler'])
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')
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python31'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler'])
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')
+1 -1
View File
@@ -2,7 +2,7 @@ import os,sys
NAME='python32'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler'])
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')
+75
View File
@@ -0,0 +1,75 @@
#include "../python/uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern char **environ;
PyObject *u_run(PyObject *self, PyObject *args) {
char **argv;
size_t size = 2;
int i;
if (PyTuple_Size(args) < 1) {
return PyErr_Format(PyExc_ValueError, "you have to specify at least one uWSGI option to run() it");
}
PyObject *the_arg = PyTuple_GetItem(args, 0);
if (PyList_Check(the_arg)) {
size = PyList_Size(the_arg) + 2;
}
else if (PyTuple_Check(the_arg)) {
size = PyTuple_Size(the_arg) + 2;
}
else if (PyString_Check(the_arg)) {
size = 3;
}
argv = uwsgi_malloc(sizeof(char *) * size);
memset(argv, 0, sizeof(char *) * size);
// will be overwritten
argv[0] = "uwsgi";
if (PyList_Check(the_arg)) {
for(i=0;i<PyList_Size(the_arg);i++) {
argv[i+1] = PyString_AsString( PyList_GetItem(the_arg, i) );
}
}
else if (PyTuple_Check(the_arg)) {
for(i=0;i<PyTuple_Size(the_arg);i++) {
argv[i+1] = PyString_AsString( PyTuple_GetItem(the_arg, i) );
}
}
else if (PyString_Check(the_arg)) {
argv[1] = PyString_AsString( the_arg );
}
uwsgi_init(size-1, argv, environ);
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef methods[] = {
{"run", u_run, METH_VARARGS, "run the uWSGI server"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
initpyuwsgi()
{
(void) Py_InitModule("pyuwsgi", methods);
}
int pyuwsgi_init() { return 0; }
struct uwsgi_plugin pyuwsgi_plugin = {
.name = "pyuwsgi",
.init = pyuwsgi_init,
};
+11
View File
@@ -0,0 +1,11 @@
from distutils import sysconfig
import os
os.environ['UWSGI_PYTHON_NOLIB'] = '1'
NAME='pyuwsgi'
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
LDFLAGS = []
LIBS = []
GCC_LIST = ['pyuwsgi']
+193 -52
View File
@@ -9,6 +9,7 @@ struct 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},
{"rbshell", optional_argument, 0, LONG_ARGS_RUBY_SHELL},
{0, 0, 0, 0},
@@ -32,53 +33,7 @@ void uwsgi_ruby_exception(void) {
/* statistically ordered */
static struct http_status_codes hsc[] = {
{"200", "OK"},
{"302", "Found"},
{"404", "Not Found"},
{"500", "Internal Server Error"},
{"301", "Moved Permanently"},
{"304", "Not Modified"},
{"303", "See Other"},
{"403", "Forbidden"},
{"307", "Temporary Redirect"},
{"401", "Unauthorized"},
{"400", "Bad Request"},
{"405", "Method Not Allowed"},
{"408", "Request Timeout"},
{"100", "Continue"},
{"101", "Switching Protocols"},
{"201", "Created"},
{"202", "Accepted"},
{"203", "Non-Authoritative Information"},
{"204", "No Content"},
{"205", "Reset Content"},
{"206", "Partial Content"},
{"300", "Multiple Choices"},
{"305", "Use Proxy"},
{"402", "Payment Required"},
{"406", "Not Acceptable"},
{"407", "Proxy Authentication Required"},
{"409", "Conflict"},
{"410", "Gone"},
{"411", "Length Required"},
{"412", "Precondition Failed"},
{"413", "Request Entity Too Large"},
{"414", "Request-URI Too Long"},
{"415", "Unsupported Media Type"},
{"416", "Requested Range Not Satisfiable"},
{"417", "Expectation Failed"},
{"501", "Not Implemented"},
{"502", "Bad Gateway"},
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{ "", NULL },
};
extern struct http_status_codes hsc[];
VALUE rb_uwsgi_io_new(VALUE class, VALUE wr) {
@@ -186,6 +141,142 @@ VALUE require_rails(VALUE arg) {
VALUE init_rack_app(VALUE);
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
uint8_t uwsgi_signal = NUM2INT(signum);
if (uwsgi_signal_registered(uwsgi_signal)) {
return Qtrue;
}
return Qfalse;
}
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
uint8_t uwsgi_signal = NUM2INT(signum);
char *signal_kind = RSTRING_PTR(sigkind);
if (uwsgi_register_signal(uwsgi_signal, signal_kind, (void *) rbhandler, 7)) {
rb_raise(rb_eRuntimeError, "unable to register signal %d", uwsgi_signal);
return Qnil;
}
rb_gc_register_address(&rbhandler);
return Qtrue;
}
VALUE uwsgi_ruby_signal(VALUE *class, VALUE signum) {
uint8_t uwsgi_signal = NUM2INT(signum);
ssize_t rlen;
rlen = write(uwsgi.signal_socket, &uwsgi_signal, 1);
if (rlen != 1) {
uwsgi_error("write()");
}
return Qtrue;
}
VALUE rack_call_signal_handler(VALUE args) {
return rb_funcall(rb_ary_entry(args, 0), rb_intern("call"), 1, rb_ary_entry(args, 1));
}
int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
int error = 0;
VALUE rbhandler = (VALUE) handler;
VALUE args = rb_ary_new2(2);
rb_ary_store(args, 0, rbhandler);
VALUE rbsig = INT2NUM(sig);
rb_ary_store(args, 1, rbsig);
VALUE ret = rb_protect(rack_call_signal_handler, args, &error);
if (error) {
uwsgi_ruby_exception();
// free resources (useless ?)
rb_gc_unregister_address(&args);
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&rbsig);
return -1;
}
// free resources (useless ?)
rb_gc_unregister_address(&args);
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&rbsig);
return 0;
}
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
uint8_t uwsgi_signal = NUM2INT(rbsignum);
int minute = NUM2INT(rbmin);
int hour = NUM2INT(rbhour);
int day = NUM2INT(rbday);
int month = NUM2INT(rbmon);
int week = NUM2INT(rbweek);
if (uwsgi_signal_add_cron(uwsgi_signal, minute, hour, day, month, week)) {
rb_raise(rb_eRuntimeError, "unable to add cron");
return Qnil;
}
return Qtrue;
}
VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
uint8_t uwsgi_signal = NUM2INT(rbsignum);
int seconds = NUM2INT(secs);
if (uwsgi_add_timer(uwsgi_signal, seconds)) {
rb_raise(rb_eRuntimeError, "unable to add timer");
return Qnil;
}
return Qtrue;
}
VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
uint8_t uwsgi_signal = NUM2INT(rbsignum);
int seconds = NUM2INT(secs);
if (uwsgi_signal_add_rb_timer(uwsgi_signal, seconds, 0)) {
rb_raise(rb_eRuntimeError, "unable to add rb_timer");
return Qnil;
}
return Qtrue;
}
VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
uint8_t uwsgi_signal = NUM2INT(rbsignum);
char *filename = RSTRING_PTR(rbfilename);
if (uwsgi_add_file_monitor(uwsgi_signal, filename)) {
rb_raise(rb_eRuntimeError, "unable to add file monitor");
return Qnil;
}
return Qtrue;
}
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -253,13 +344,13 @@ int uwsgi_rack_init(){
char **argv = sargv;
#endif
int error;
// filling http status codes
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = (int) strlen(http_sc->message);
}
ur.unprotected = 0;
#ifdef RUBY19
ruby_sysinit(&argc, &argv);
@@ -281,6 +372,20 @@ int uwsgi_rack_init(){
rb_define_module_function(rb_uwsgi_embedded, "wait_fd_read", uwsgi_ruby_wait_fd_read, 2);
rb_define_module_function(rb_uwsgi_embedded, "wait_fd_write", uwsgi_ruby_wait_fd_write, 2);
rb_define_module_function(rb_uwsgi_embedded, "async_connect", uwsgi_ruby_async_connect, 1);
rb_define_module_function(rb_uwsgi_embedded, "signal", uwsgi_ruby_signal, 1);
rb_define_module_function(rb_uwsgi_embedded, "register_signal", uwsgi_ruby_register_signal, 3);
rb_define_module_function(rb_uwsgi_embedded, "signal_registered", uwsgi_ruby_signal_registered, 1);
rb_define_module_function(rb_uwsgi_embedded, "add_cron", rack_uwsgi_add_cron, 6);
rb_define_module_function(rb_uwsgi_embedded, "add_timer", rack_uwsgi_add_timer, 2);
rb_define_module_function(rb_uwsgi_embedded, "add_rb_timer", rack_uwsgi_add_rb_timer, 2);
rb_define_module_function(rb_uwsgi_embedded, "add_file_monitor", rack_uwsgi_add_file_monitor, 2);
return 0;
}
void uwsgi_rack_init_apps(void) {
int error;
if (ur.rack) {
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error);
@@ -289,9 +394,12 @@ int uwsgi_rack_init(){
exit(1);
}
if (ur.dispatcher == Qnil) {
uwsgi_log("unable to find RACK entry point\n");
exit(1);
}
rb_gc_register_address(&ur.dispatcher);
goto ready;
}
else if (ur.rails) {
if (chdir(ur.rails)) {
@@ -314,10 +422,18 @@ int uwsgi_rack_init(){
uwsgi_log("unable to load rails dispatcher\n");
exit(1);
}
goto ready;
}
return;
ready:
ur.call = rb_intern("call");
if (!ur.call) {
uwsgi_log("unable to find RACK entry point\n");
return;
}
rb_gc_register_address(&ur.call);
@@ -332,8 +448,6 @@ int uwsgi_rack_init(){
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);
return 0;
}
VALUE call_dispatch(VALUE env) {
@@ -521,7 +635,21 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
rb_ary_store(rbv, 1, INT2NUM(1));
rb_hash_aset(env, rb_str_new2("rack.version"), rbv);
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
if (wsgi_req->scheme_len > 0) {
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new(wsgi_req->scheme, wsgi_req->scheme_len));
}
else if (wsgi_req->https_len > 0) {
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("https"));
}
else {
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
}
}
else {
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
}
rb_hash_aset(env, rb_str_new2("rack.multithread"), Qfalse);
rb_hash_aset(env, rb_str_new2("rack.multiprocess"), Qtrue);
@@ -625,7 +753,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
wsgi_req->response_size = uwsgi_sendfile(wsgi_req);
if (wsgi_req->response_size > 0) {
while(wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
uwsgi_log("sendfile_fd_size = %d\n", wsgi_req->sendfile_fd_size);
//uwsgi_log("sendfile_fd_size = %d\n", wsgi_req->sendfile_fd_size);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
}
}
@@ -692,11 +820,16 @@ void uwsgi_rack_after_request(struct wsgi_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:
@@ -788,6 +921,9 @@ int uwsgi_rack_mount_app(char *mountpoint, char *app) {
}
*/
void uwsgi_rack_hijack(void) {
}
struct uwsgi_plugin rack_plugin = {
.name = "rack",
@@ -798,6 +934,11 @@ struct uwsgi_plugin rack_plugin = {
.request = uwsgi_rack_request,
.after_request = uwsgi_rack_after_request,
.signal_handler = uwsgi_rack_signal_handler,
.hijack = uwsgi_rack_hijack,
.init_apps = uwsgi_rack_init_apps,
//.mount_app = uwsgi_rack_mount_app,
.manage_xml = uwsgi_rack_xml,
+3
View File
@@ -6,6 +6,7 @@
#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
#ifndef RUBY19
#define rb_errinfo() ruby_errinfo
@@ -59,6 +60,8 @@ struct uwsgi_rack {
pthread_mutex_t gvl;
int rb_shell;
};
void uwsgi_ruby_exception(void);
+188
View File
@@ -0,0 +1,188 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
#define RRDTOOL_OPT_BASE 177000
#define RRDTOOL_OPT_RRDTOOL RRDTOOL_OPT_BASE+1
#define RRDTOOL_OPT_RRDTOOL_MAX_DS RRDTOOL_OPT_BASE+2
struct uwsgi_rrdtool {
void *lib;
int (*create)(int, char **);
int (*update)(int, char **);
struct uwsgi_string_list *rrd;
int max_ds;
char *update_area;
} u_rrd;
struct option rrdtool_options[] = {
{"rrdtool", required_argument, 0, RRDTOOL_OPT_RRDTOOL},
{"rrdtool-max-ds", required_argument, 0, RRDTOOL_OPT_RRDTOOL_MAX_DS},
{0, 0, 0, 0},
};
int rrdtool_init() {
u_rrd.lib = dlopen("librrd.so", RTLD_LAZY);
if (!u_rrd.lib) return -1;
u_rrd.create = dlsym(u_rrd.lib, "rrd_create");
if (!u_rrd.create) {
dlclose(u_rrd.lib);
return -1;
}
u_rrd.update = dlsym(u_rrd.lib, "rrd_update");
if (!u_rrd.update) {
dlclose(u_rrd.lib);
return -1;
}
if (!u_rrd.max_ds) u_rrd.max_ds = 30;
uwsgi_log("*** RRDtool library available at %p ***\n", u_rrd.lib);
return 0;
}
int rrdtool_opt(int i, char *optarg) {
switch(i) {
case RRDTOOL_OPT_RRDTOOL:
uwsgi.master_process = 1;
uwsgi_string_new_list(&u_rrd.rrd, optarg);
return 1;
case RRDTOOL_OPT_RRDTOOL_MAX_DS:
u_rrd.max_ds = atoi(optarg);
return 1;
}
return 0;
}
void rrdtool_post_init() {
struct uwsgi_string_list *usl = u_rrd.rrd;
char **argv;
int i;
if (!u_rrd.lib || !u_rrd.create) return;
// do not waste time if no --rrdtool option is defiend
if (!u_rrd.rrd) return;
if (uwsgi.numproc > u_rrd.max_ds) {
uwsgi_log("!!! NOT ENOUGH SLOTS IN RRDTOOL DS TO HOST WORKERS DATA (increase them with --rrdtool-max-ds) !!!\n");
dlclose(u_rrd.lib);
return;
}
// alloc space for DS_REQ + DS WORKER + RRA + create + filename
argv = uwsgi_malloc( sizeof(char *) * (1 + u_rrd.max_ds + 4 + 1 +1));
argv[0] = "create";
argv[2] = "DS:requests:DERIVE:600:0:U";
// create DS for workers
for(i=0;i<u_rrd.max_ds;i++) {
int max_size = sizeof("DS:worker65536:DERIVE:600:0:U")+1;
argv[3+i] = uwsgi_malloc( max_size );
if (snprintf(argv[3+i], max_size, "DS:worker%d:DERIVE:600:0:U", i+1) < 25) {
uwsgi_log("unable to create args for rrd_create()\n");
exit(1);
}
}
// create RRA
argv[3+u_rrd.max_ds] = "RRA:AVERAGE:0.5:1:288" ;
argv[3+u_rrd.max_ds+1] = "RRA:AVERAGE:0.5:12:168" ;
argv[3+u_rrd.max_ds+2] = "RRA:AVERAGE:0.5:288:31" ;
argv[3+u_rrd.max_ds+3] = "RRA:AVERAGE:0.5:2016:52";
while(usl) {
if (!uwsgi_file_exists(usl->value)) {
argv[1] = usl->value;
if (u_rrd.create((1 + u_rrd.max_ds + 4 + 1 +1), argv)) {
uwsgi_error("rrd_create()");
exit(1);
}
}
usl->value = realpath(usl->value, NULL);
if (!usl->value) {
uwsgi_error("realpath()");
exit(1);
}
usl = usl->next;
}
// free DS
for(i=0;i<u_rrd.max_ds;i++) {
free(argv[3+i]);
}
free(argv);
//now allocate memory for updates
u_rrd.update_area = uwsgi_malloc( 1+((1+sizeof(UMAX64_STR)) * (u_rrd.max_ds+1))+1 );
memset(u_rrd.update_area, 0, 1+((1+sizeof(UMAX64_STR)) * (u_rrd.max_ds+1))+1 );
u_rrd.update_area[0] = 'N';
}
void rrdtool_master_cycle() {
static time_t last_update = 0;
char *ptr;
int rlen, i;
char *argv[3];
struct uwsgi_string_list *usl = u_rrd.rrd;
if (!u_rrd.lib || !u_rrd.create || !u_rrd.rrd) return ;
if (last_update == 0) last_update = time(NULL);
// update every 5 minutes
if (uwsgi.current_time - last_update >= 300) {
ptr = u_rrd.update_area+1;
rlen = snprintf(ptr, 1+sizeof(UMAX64_STR), ":%llu", (unsigned long long )uwsgi.workers[0].requests);
if (rlen < 2) return;
ptr+=rlen;
for(i=0;i<u_rrd.max_ds;i++) {
if (i+1 <= uwsgi.numproc) {
rlen = snprintf(ptr, 1+sizeof(UMAX64_STR), ":%llu", (unsigned long long )uwsgi.workers[1+i].requests);
if (rlen < 2) return;
}
else {
memcpy(ptr, ":U", 2);
rlen = 2;
}
ptr+=rlen;
}
last_update = uwsgi.current_time;
argv[0] = "update";
argv[2] = u_rrd.update_area;
while(usl) {
argv[1] = usl->value;
if (u_rrd.update(3, argv)) {
uwsgi_log_verbose("ERROR: rrd_update(\"%s\", \"%s\")\n", argv[1], argv[2]);
}
usl = usl->next;
}
}
}
struct uwsgi_plugin rrdtool_plugin = {
.options = rrdtool_options,
.manage_opt = rrdtool_opt,
.master_cycle = rrdtool_master_cycle,
.post_init = rrdtool_post_init,
.init = rrdtool_init,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='rrdtool'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['rrdtool']
+33
View File
@@ -0,0 +1,33 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
int (*symcall_function)(struct wsgi_request *);
int uwsgi_symcall_init(){
symcall_function = dlsym(RTLD_DEFAULT, "pypy_uwsgi_request");
uwsgi_log("symcall function ptr: %p\n", symcall_function);
return 0;
}
int uwsgi_symcall_request(struct wsgi_request *wsgi_req) {
return symcall_function(wsgi_req);
}
void uwsgi_symcall_after_request(struct wsgi_request *wsgi_req) {
// TODO
}
struct uwsgi_plugin symcall_plugin = {
.name = "symcall",
.modifier1 = 18,
.init = uwsgi_symcall_init,
.request = uwsgi_symcall_request,
.after_request = uwsgi_symcall_after_request,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='symcall'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['symcall_plugin']
+72 -6
View File
@@ -42,6 +42,20 @@ static uint16_t http_add_uwsgi_header(struct wsgi_request *wsgi_req, char *hh, i
if (uwsgi_strncmp("CONTENT_TYPE", 12, hh, keylen) && uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
keylen += 5;
prefix = 1;
if (!uwsgi_strncmp("IF_MODIFIED_SINCE", 17, hh, keylen)) {
wsgi_req->if_modified_since = val;
wsgi_req->if_modified_since_len = vallen;
}
else if (!uwsgi_strncmp("X_FORWARDED_SSL", 15, hh, keylen)) {
if (vallen == 2 && val[0] == 'o' && val[1] == 'n') {
wsgi_req->scheme = "https";
wsgi_req->scheme_len = 5;
}
}
else if (uwsgi.vhost_host && !uwsgi_strncmp("HOST", 4, hh, keylen)) {
wsgi_req->host = val;
wsgi_req->host_len = vallen;
}
}
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
wsgi_req->post_cl = uwsgi_str_num(val, vallen);
@@ -92,10 +106,14 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
char ip[INET_ADDRSTRLEN+1];
struct sockaddr_in *http_sin = (struct sockaddr_in *) &wsgi_req->c_addr;
wsgi_req->path_info_pos = -1;
// REQUEST_METHOD
while (ptr < watermark) {
if (*ptr == ' ') {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_METHOD", 14, base, ptr - base);
wsgi_req->method = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->method_len = ptr - base;
ptr++;
break;
}
@@ -106,17 +124,46 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
base = ptr;
while (ptr < watermark) {
if (*ptr == '?' && !query_string) {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
if (watermark + (ptr - base) < (char *)(wsgi_req->proto_parser_buf + uwsgi.buffer_size)) {
wsgi_req->path_info = watermark;
wsgi_req->path_info_len = ptr - base;
http_url_decode(base, &wsgi_req->path_info_len, wsgi_req->path_info);
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, wsgi_req->path_info, wsgi_req->path_info_len);
}
else {
uwsgi_log("not enough space in wsgi_req http proto_parser_buf to encode PATH_INFO, consider tuning it with --buffer-size\n");
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->path_info_len = ptr - base;
}
wsgi_req->path_info_pos = 3;
query_string = ptr + 1;
}
else if (*ptr == ' ') {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, base, ptr - base);
wsgi_req->uri = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->uri_len = ptr - base;
if (!query_string) {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
if (watermark + (ptr - base) < (char *)(wsgi_req->proto_parser_buf + uwsgi.buffer_size)) {
wsgi_req->path_info = watermark;
wsgi_req->path_info_len = ptr - base;
http_url_decode(base, &wsgi_req->path_info_len, wsgi_req->path_info);
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, wsgi_req->path_info, wsgi_req->path_info_len);
}
else {
uwsgi_log("not enough space in wsgi_req http proto_parser_buf to encode PATH_INFO, consider tuning it with --buffer-size\n");
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->path_info_len = ptr - base;
}
wsgi_req->path_info_pos = 5;
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
}
else {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, query_string, ptr - query_string);
wsgi_req->query_string = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - query_string);
wsgi_req->query_string_len = ptr - query_string;
}
ptr++;
break;
@@ -133,6 +180,8 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
if (*(ptr + 1) != '\n')
return 0;
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PROTOCOL", 15, base, ptr - base);
wsgi_req->protocol = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->protocol_len = ptr - base;
ptr += 2;
break;
}
@@ -140,18 +189,31 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
}
// SCRIPT_NAME
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SCRIPT_NAME", 11, "", 0);
if (!uwsgi.manage_script_name) {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SCRIPT_NAME", 11, "", 0);
}
// SERVER_NAME
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len);
wsgi_req->host = uwsgi.hostname;
wsgi_req->host_len = uwsgi.hostname_len;
// SERVER_PORT
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "3031", 4);
char *server_port = strchr(wsgi_req->socket->name, ':');
if (server_port) {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, server_port+1, strlen(server_port+1));
}
else {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
}
// REMOTE_ADDR
memset(ip, 0, INET_ADDRSTRLEN+1);
if (inet_ntop(AF_INET, (void *) &http_sin->sin_addr.s_addr, ip, INET_ADDRSTRLEN)) {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, ip, strlen(ip));
wsgi_req->remote_addr = (wsgi_req->buffer + wsgi_req->uh.pktsize) - strlen(ip);
wsgi_req->remote_addr_len = strlen(ip);
}
else {
uwsgi_error("inet_ntop()");
@@ -230,7 +292,11 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
len = read(wsgi_req->poll.fd, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos, uwsgi.buffer_size - wsgi_req->proto_parser_pos);
if (len <= 0) {
free(wsgi_req->proto_parser_buf);
uwsgi_error("recv()");
if (len < 0) {
uwsgi_error("recv()");
}
// this is simple ping packet
else { return -2; }
return -1;
}
@@ -253,7 +319,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
remains = len - (j + 1);
http_parse(wsgi_req, ptr);
//is there a Content_Length ?
if (wsgi_req->post_cl) {
if (wsgi_req->post_cl > 0) {
wsgi_req->async_post = tmpfile();
if (!wsgi_req->async_post) {
free(wsgi_req->proto_parser_buf);
+24 -4
View File
@@ -115,17 +115,37 @@ int uwsgi_proto_uwsgi_parser(struct wsgi_request *wsgi_req) {
}
ssize_t uwsgi_proto_uwsgi_writev_header(struct wsgi_request * wsgi_req, struct iovec * iovec, size_t iov_len) {
return writev(wsgi_req->poll.fd, iovec, iov_len);
ssize_t wlen = writev(wsgi_req->poll.fd, iovec, iov_len);
if (wlen < 0) {
uwsgi_req_error("writev()");
return 0;
}
return wlen;
}
ssize_t uwsgi_proto_uwsgi_writev(struct wsgi_request * wsgi_req, struct iovec * iovec, size_t iov_len) {
return writev(wsgi_req->poll.fd, iovec, iov_len);
ssize_t wlen = writev(wsgi_req->poll.fd, iovec, iov_len);
if (wlen < 0) {
uwsgi_req_error("writev()");
return 0;
}
return wlen;
}
ssize_t uwsgi_proto_uwsgi_write(struct wsgi_request * wsgi_req, char *buf, size_t len) {
return write(wsgi_req->poll.fd, buf, len);
ssize_t wlen = write(wsgi_req->poll.fd, buf, len);
if (wlen < 0) {
uwsgi_req_error("write()");
return 0;
}
return wlen;
}
ssize_t uwsgi_proto_uwsgi_write_header(struct wsgi_request * wsgi_req, char *buf, size_t len) {
return write(wsgi_req->poll.fd, buf, len);
ssize_t wlen = write(wsgi_req->poll.fd, buf, len);
if (wlen < 0) {
uwsgi_req_error("write()");
return 0;
}
return wlen;
}
-1
View File
@@ -454,7 +454,6 @@ ssize_t uwsgi_proto_zeromq_sendfile(struct wsgi_request * wsgi_req) {
wsgi_req->sendfile_fd_chunk = 65536;
if (uwsgi.async > 1) {
len = read(wsgi_req->sendfile_fd, buf, UMIN(remains, wsgi_req->sendfile_fd_chunk));
if (len != (int) UMIN(remains, wsgi_req->sendfile_fd_chunk)) {
+176 -24
View File
@@ -355,7 +355,7 @@ int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
exit(1);
}
else if (rlen == 0) {
uwsgi_log( "timeout waiting for header. skip request.\n");
uwsgi_log( "timeout. skip request.\n");
//close(upoll->fd);
return 0;
}
@@ -366,7 +366,10 @@ int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
status = uwsgi_proto_uwsgi_parser(wsgi_req);
}
if (status < 0) {
uwsgi_log("error parsing request\n");
if (status == -1)
uwsgi_log("error parsing request\n");
else if (status == -2)
uwsgi_log("open-close packet (ping/check) received\n");
//close(upoll->fd);
return 0;
}
@@ -405,7 +408,7 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
*argc = *argc + 1;
}
else {
uwsgi_log( "invalid uwsgi array. skip this request.\n");
uwsgi_log( "invalid uwsgi array. skip this var.\n");
return -1;
}
}
@@ -419,6 +422,73 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
return 0;
}
int uwsgi_simple_parse_vars(struct wsgi_request *wsgi_req, char *ptrbuf, char *bufferend) {
uint16_t strsize;
while (ptrbuf < bufferend) {
if (ptrbuf + 2 < bufferend) {
memcpy(&strsize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
strsize = uwsgi_swap16(strsize);
#endif
/* key cannot be null */
if (!strsize) {
uwsgi_log( "uwsgi key cannot be null. skip this request.\n");
return -1;
}
ptrbuf += 2;
if (ptrbuf + strsize < bufferend) {
// var key
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
ptrbuf += strsize;
// value can be null (even at the end) so use <=
if (ptrbuf + 2 <= bufferend) {
memcpy(&strsize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
strsize = uwsgi_swap16(strsize);
#endif
ptrbuf += 2;
if (ptrbuf + strsize <= bufferend) {
if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this header.\n");
return -1;
}
// var value
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this var.\n");
return -1;
}
ptrbuf += strsize;
}
else {
uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
return -1;
}
}
else {
uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
return -1;
}
}
}
}
return 0;
}
int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
char *buffer = wsgi_req->buffer;
@@ -429,10 +499,19 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
ptrbuf = buffer;
bufferend = ptrbuf + wsgi_req->uh.pktsize;
int i, script_name= -1, path_info= -1;
int i, script_name= -1;
/* set an HTTP 500 status as default */
wsgi_req->status = 500;
// has the protocol already parsed the request ?
if (wsgi_req->uri_len > 0) {
i = uwsgi_simple_parse_vars(wsgi_req, ptrbuf, bufferend);
if (i == 0) goto next;
return i;
}
wsgi_req->path_info_pos = -1;
while (ptrbuf < bufferend) {
if (ptrbuf + 2 < bufferend) {
@@ -442,7 +521,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
#endif
/* key cannot be null */
if (!strsize) {
uwsgi_log( "uwsgi key cannot be null. skip this request.\n");
uwsgi_log( "uwsgi key cannot be null. skip this var.\n");
return -1;
}
@@ -472,7 +551,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
else if (!uwsgi_strncmp("PATH_INFO", 9, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->path_info = ptrbuf;
wsgi_req->path_info_len = strsize;
path_info = wsgi_req->var_cnt + 1;
wsgi_req->path_info_pos = wsgi_req->var_cnt + 1;
#ifdef UWSGI_DEBUG
uwsgi_debug("PATH_INFO=%.*s\n", wsgi_req->path_info_len, wsgi_req->path_info);
#endif
@@ -493,7 +572,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->method = ptrbuf;
wsgi_req->method_len = strsize;
}
else if (!uwsgi_strncmp("REMOTE_ADDR", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
else if (!uwsgi.log_x_forwarded_for && !uwsgi_strncmp("REMOTE_ADDR", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_addr = ptrbuf;
wsgi_req->remote_addr_len = strsize;
}
@@ -508,14 +587,17 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
else if (!uwsgi_strncmp("UWSGI_SCRIPT", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len )) {
wsgi_req->script = ptrbuf;
wsgi_req->script_len = strsize;
wsgi_req->dynamic = 1;
}
else if (!uwsgi_strncmp("UWSGI_MODULE", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->module = ptrbuf;
wsgi_req->module_len = strsize;
wsgi_req->dynamic = 1;
}
else if (!uwsgi_strncmp("UWSGI_CALLABLE", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->callable = ptrbuf;
wsgi_req->callable_len = strsize;
wsgi_req->dynamic = 1;
}
else if (!uwsgi_strncmp("UWSGI_PYHOME", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->pyhome = ptrbuf;
@@ -525,9 +607,14 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->chdir = ptrbuf;
wsgi_req->chdir_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_APPID", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->appid = ptrbuf;
wsgi_req->appid_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_FILE", 10, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->file = ptrbuf;
wsgi_req->file_len = strsize;
wsgi_req->dynamic = 1;
}
else if (!uwsgi_strncmp("UWSGI_TOUCH_RELOAD", 18, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->touch_reload = ptrbuf;
@@ -570,6 +657,14 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->if_modified_since = ptrbuf;
wsgi_req->if_modified_since_len = strsize;
}
else if (uwsgi.log_x_forwarded_for && !uwsgi_strncmp("HTTP_X_FORWARDED_FOR", 20, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_addr = ptrbuf;
wsgi_req->remote_addr_len = strsize;
}
else if (!uwsgi_strncmp("CONTENT_TYPE", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->content_type = ptrbuf;
wsgi_req->content_type_len = strsize;
}
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->post_cl = get_content_length(ptrbuf, strsize);
if (uwsgi.limit_post) {
@@ -585,7 +680,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this header.\n");
uwsgi_log( "max vec size reached. skip this var.\n");
return -1;
}
// var value
@@ -596,7 +691,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this header.\n");
uwsgi_log( "max vec size reached. skip this var.\n");
return -1;
}
ptrbuf += strsize;
@@ -618,6 +713,8 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
}
}
next:
if (uwsgi.post_buffering > 0 && !wsgi_req->body_as_file && !wsgi_req->async_post) {
// read to disk if post_cl > post_buffering (it will eventually do upload progress...)
if (wsgi_req->post_cl >= (size_t) uwsgi.post_buffering) {
@@ -661,7 +758,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
}
if (uwsgi.manage_script_name) {
if (uwsgi.apps_cnt > 0 && wsgi_req->path_info_len > 1) {
if (uwsgi_apps_cnt > 0 && wsgi_req->path_info_len > 1 && wsgi_req->path_info_pos != -1) {
// starts with 1 as the 0 app is the default (/) one
int best_found = 0;
char *orig_path_info = wsgi_req->path_info;
@@ -669,30 +766,33 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
// if SCRIPT_NAME is not allocated, add a slot for it
if (script_name == -1) {
if (wsgi_req->var_cnt >= uwsgi.vec_size - (4 + 2)) {
uwsgi_log( "max vec size reached. skip this header.\n");
uwsgi_log( "max vec size reached. skip this var.\n");
return -1;
}
wsgi_req->var_cnt++;
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = "SCRIPT_NAME";
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = 11;
wsgi_req->var_cnt++;
script_name = wsgi_req->var_cnt;
wsgi_req->hvec[script_name].iov_base = "";
wsgi_req->hvec[script_name].iov_len = 0;
wsgi_req->var_cnt++;
}
for(i=0;i<uwsgi.apps_cnt;i++) {
//uwsgi_log("app mountpoint = %.*s\n", uwsgi.apps[i].mountpoint_len, uwsgi.apps[i].mountpoint);
if (orig_path_info_len >= uwsgi.apps[i].mountpoint_len) {
if (!uwsgi_startswith(orig_path_info, uwsgi.apps[i].mountpoint, uwsgi.apps[i].mountpoint_len) && uwsgi.apps[i].mountpoint_len > best_found) {
best_found = uwsgi.apps[i].mountpoint_len;
wsgi_req->script_name = uwsgi.apps[i].mountpoint;
wsgi_req->script_name_len = uwsgi.apps[i].mountpoint_len;
for(i=0;i<uwsgi_apps_cnt;i++) {
//uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
if (orig_path_info_len >= uwsgi_apps[i].mountpoint_len) {
if (!uwsgi_startswith(orig_path_info, uwsgi_apps[i].mountpoint, uwsgi_apps[i].mountpoint_len) && uwsgi_apps[i].mountpoint_len > best_found) {
best_found = uwsgi_apps[i].mountpoint_len;
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
wsgi_req->path_info = orig_path_info+wsgi_req->script_name_len;
wsgi_req->path_info_len = orig_path_info_len-wsgi_req->script_name_len;
wsgi_req->hvec[script_name].iov_base = wsgi_req->script_name;
wsgi_req->hvec[script_name].iov_len = wsgi_req->script_name_len;
wsgi_req->hvec[path_info].iov_base = wsgi_req->path_info;
wsgi_req->hvec[path_info].iov_len = wsgi_req->path_info_len;
wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
#ifdef UWSGI_DEBUG
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
#endif
@@ -1236,6 +1336,48 @@ int uwsgi_simple_send_string(char *socket_name, uint8_t modifier1, uint8_t modif
return 0;
}
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
int i;
int count = 0;
char *ext = NULL;
for(i=namelen-1;i>=0;i--) {
if (!isalnum( (int)name[i])) {
if (name[i] == '.') {
ext = name+(namelen-count);
break;
}
}
count++;
}
if (ext) {
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
while(udd) {
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
udd->hits++;
// auto optimization
if (udd->prev) {
if (udd->hits > udd->prev->hits) {
struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
if (udd_parent) {
udd_parent->next = udd;
}
udd_prev->prev = udd;
udd_prev->next = udd->next;
udd->prev = udd_parent;
udd->next = udd_prev;
}
}
*size = udd->vallen;
return udd->value;
}
udd = udd->next;
}
}
return NULL;
}
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len, char *orig_document_root, uint16_t orig_document_root_len) {
@@ -1260,6 +1402,8 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
return -1;
}
if (!stat(real_filename, &st)) {
int mime_type_size = 0;
char *mime_type = uwsgi_get_mime_type(path_info, path_info_len, &mime_type_size);
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
if (st.st_mtime <= ims) {
@@ -1292,11 +1436,19 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
while(ah) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ah->value, ah->len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
wsgi_req->header_cnt++;
ah = ah->next;
}
if (mime_type_size > 0 && mime_type) {
wsgi_req->header_cnt++;
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "Content-Type: ", 14);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, mime_type, mime_type_size);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
}
if (uwsgi.file_serve_mode == 1) {
wsgi_req->header_cnt = 2;
wsgi_req->header_cnt += 2;
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Accel-Redirect: ", 18);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, orig_document_root, orig_document_root_len);
if (orig_document_root[orig_document_root_len-1] != '/') {
@@ -1308,7 +1460,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
}
else if (uwsgi.file_serve_mode == 2) {
wsgi_req->header_cnt = 2;
wsgi_req->header_cnt += 2;
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Sendfile: ", 12);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, orig_document_root, orig_document_root_len);
if (orig_document_root[orig_document_root_len-1] != '/') {
@@ -1320,7 +1472,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
}
else {
wsgi_req->header_cnt = 1;
wsgi_req->header_cnt += 1;
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
wsgi_req->sendfile_fd = open(real_filename, O_RDONLY);
+18
View File
@@ -0,0 +1,18 @@
import sys
import os
import pyuwsgi
orig_args = sys.argv
orig_executable = sys.executable
orig_args.insert(0, orig_executable)
uwsgi_args = []
for arg in sys.argv[2:]:
uwsgi_args.append(arg)
#pyuwsgi.run('welcome.ini')
pyuwsgi.run(uwsgi_args)
# if you are here uWSGI has been reloaded
os.execv(orig_executable, orig_args)
+22
View File
@@ -0,0 +1,22 @@
import sys
import os
import pyuwsgi
orig_args = sys.argv
orig_executable = sys.executable
orig_args.insert(0, orig_executable)
uwsgi_args = []
uwsgi_args.append('--socket')
uwsgi_args.append(':3031')
#uwsgi_args.append('--master')
uwsgi_args.append('--module')
#uwsgi_args.append('welcome')
uwsgi_args.append('hello')
#pyuwsgi.run('welcome.ini')
pyuwsgi.run(uwsgi_args)
# if you are here uWSGI has been reloaded
os.execv(orig_executable, orig_args)
+53 -33
View File
@@ -6,17 +6,15 @@ void uwsgi_init_queue() {
if (!uwsgi.queue_blocksize)
uwsgi.queue_blocksize = 8192;
if (uwsgi.queue_blocksize % uwsgi.page_size != 0) {
uwsgi_log("invalid queue blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.queue_blocksize, uwsgi.page_size);
if ((uwsgi.queue_blocksize * uwsgi.queue_size) % uwsgi.page_size != 0) {
uwsgi_log("invalid queue size/blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.queue_blocksize, uwsgi.page_size);
exit(1);
}
uwsgi.shared->queue_pos = 0;
uwsgi.shared->queue_pull_pos = 0;
if (uwsgi.queue_store) {
uwsgi.queue_filesize = uwsgi.queue_blocksize * uwsgi.queue_size;
uwsgi.queue_filesize = uwsgi.queue_blocksize * uwsgi.queue_size + 16;
int queue_fd;
struct stat qst;
@@ -45,16 +43,26 @@ void uwsgi_init_queue() {
exit(1);
}
uwsgi.queue = mmap(NULL, uwsgi.queue_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0);
uwsgi_queue_fix();
// fix header
uwsgi.queue_header = uwsgi.queue;
uwsgi.queue+=16;
}
else {
uwsgi.queue = mmap(NULL, uwsgi.queue_blocksize * uwsgi.queue_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
uwsgi.queue = mmap(NULL, (uwsgi.queue_blocksize * uwsgi.queue_size)+16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
// fix header
uwsgi.queue_header = uwsgi.queue;
uwsgi.queue+=16;
uwsgi.queue_header->pos = 0;
uwsgi.queue_header->pull_pos = 0;
}
if (!uwsgi.queue) {
uwsgi_error("mmap()");
exit(1);
}
uwsgi.queue_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.queue_lock);
@@ -78,33 +86,20 @@ char *uwsgi_queue_get(uint64_t index, uint64_t *size) {
}
void uwsgi_queue_fix() {
uint64_t i;
char *value;
uint64_t size;
for(i=0;i< uwsgi.queue_size;i++) {
// valid record ?
value = uwsgi_queue_get(i, &size);
if (value && size) {
uwsgi.shared->queue_pos++;
}
else {
return;
}
}
}
char *uwsgi_queue_pop(uint64_t *size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (uwsgi.shared->queue_pos > 0) uwsgi.shared->queue_pos--;
if (uwsgi.queue_header->pos == 0) {
uwsgi.queue_header->pos = uwsgi.queue_size-1;
}
else {
uwsgi.queue_header->pos--;
}
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.shared->queue_pos);
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pos);
uqi = (struct uwsgi_queue_item *) ptr;
if (!uqi->size) return NULL;
@@ -122,16 +117,16 @@ char *uwsgi_queue_pull(uint64_t *size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.shared->queue_pull_pos);
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pull_pos);
uqi = (struct uwsgi_queue_item *) ptr;
if (!uqi->size) return NULL;
*size = uqi->size;
uwsgi.shared->queue_pull_pos++;
uwsgi.queue_header->pull_pos++;
if (uwsgi.shared->queue_pull_pos >= uwsgi.queue_size) uwsgi.shared->queue_pull_pos = 0;
if (uwsgi.queue_header->pull_pos >= uwsgi.queue_size) uwsgi.queue_header->pull_pos = 0;
// remove item
uqi->size = 0;
@@ -150,7 +145,7 @@ int uwsgi_queue_push(char *message, uint64_t size) {
if (!size) return 0;
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.shared->queue_pos);
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr += sizeof(struct uwsgi_queue_item);
@@ -159,9 +154,34 @@ int uwsgi_queue_push(char *message, uint64_t size) {
uqi->ts = time(NULL);
memcpy(ptr, message, size);
uwsgi.shared->queue_pos++;
uwsgi.queue_header->pos++;
if (uwsgi.shared->queue_pos >= uwsgi.queue_size) uwsgi.shared->queue_pos = 0;
if (uwsgi.queue_header->pos >= uwsgi.queue_size) uwsgi.queue_header->pos = 0;
return 1;
}
int uwsgi_queue_set(uint64_t pos, char *message, uint64_t size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (!size) return 0;
if (pos >= uwsgi.queue_size) return 0;
ptr = ptr + (uwsgi.queue_blocksize*pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr += sizeof(struct uwsgi_queue_item);
uqi->size = size;
uqi->ts = time(NULL);
memcpy(ptr, message, size);
return 1;
}
+19 -23
View File
@@ -1,35 +1,31 @@
#ifdef UWSGI_PCRE
#include "uwsgi.h"
#include <pcre.h>
int uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra) {
/*
const char *errstr;
int erroff;
void uwsgi_regexp_match(regexp, what) {
int ret,i;
for(i=0;i<uwsgi->nroutes;i++) {
ret = pcre_exec(ur->pattern, ur->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len, 0, 0, wsgi_req->ovector, (ur->args+1)*3 );
if (ret >= 0) {
if (ur->action) {
ur->action(uwsgi, wsgi_req, ur);
}
else {
uwsgi_route_action_wsgi(uwsgi, wsgi_req, ur);
}
}
// TODO check for errors if < 0 && != NO_MATCH
*pattern = pcre_compile( (const char *)re, 0, &errstr, &erroff, NULL);
if (!*pattern) {
uwsgi_log("pcre error: %s at offset %d\n", errstr, erroff);
return -1;
}
return;
*pattern_extra = (pcre_extra *) pcre_study((const pcre*)*pattern, 0, &errstr);
if (!*pattern_extra) {
pcre_free(*pattern);
uwsgi_log("pcre (study) error: %s\n", errstr);
return -1;
}
return 0;
}
*/
int uwsgi_regexp_match(pcre *pattern, pcre_extra *pattern_extra, char *subject, int length) {
return pcre_exec((const pcre*)pattern, (const pcre_extra *)pattern_extra, subject, length, 0, 0, NULL, 0 );
}
#endif
+5 -3
View File
@@ -56,9 +56,11 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
sf_ret = sendfile(filefd, sockfd, 0, 0, NULL, &sf_len, 0);
}
if (sf_ret) {
uwsgi_error("sendfile()");
return 0;
if (sf_ret < 0) {
if (errno != EAGAIN) {
uwsgi_error("sendfile()");
return 0;
}
}
return sf_len;
+40 -10
View File
@@ -6,8 +6,23 @@ import shutil
from setuptools import setup
from setuptools.dist import Distribution
from setuptools.command.install import install
from setuptools.command.install_lib import install_lib
from setuptools.command.build_ext import build_ext
"""
This is a hack allowing you installing uWSGI and uwsgidecorators via pip and easy_install
"""
uwsgi_compiled = False
def get_profile():
profile = os.environ.get('UWSGI_PROFILE','buildconf/default.ini')
if not profile.endswith('.ini'):
profile = "%s.ini" % profile
if not '/' in profile:
profile = "buildconf/%s" % profile
return profile
def patch_bin_path(cmd, conf):
@@ -26,30 +41,44 @@ def patch_bin_path(cmd, conf):
class uWSGIBuilder(build_ext):
def run(self):
conf = uc.uConf('buildconf/default.ini')
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
global uwsgi_compiled
if not uwsgi_compiled:
conf = uc.uConf(get_profile())
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
uwsgi_compiled = True
class uWSGIInstall(install):
def run(self):
# hack, hack and still hack. We need to find a solution...
if self.record:
record_file = open(self.record,'w')
global uwsgi_compiled
if not uwsgi_compiled:
conf = uc.uConf(get_profile())
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
uwsgi_compiled = True
install.run(self)
conf = uc.uConf('buildconf/default.ini')
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
class uWSGIInstallLib(install_lib):
def run(self):
global uwsgi_compiled
if not uwsgi_compiled:
conf = uc.uConf(get_profile())
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
uwsgi_compiled = True
install_lib.run(self)
class uWSGIDistribution(Distribution):
def __init__(self, *attrs):
Distribution.__init__(self, *attrs)
self.cmdclass['install'] = uWSGIInstall
self.cmdclass['install_lib'] = uWSGIInstallLib
self.cmdclass['build_ext'] = uWSGIBuilder
setup(name='uWSGI',
version=uc.uwsgi_version,
description='The uWSGI server',
@@ -57,6 +86,7 @@ setup(name='uWSGI',
author_email='info@unbit.it',
url='http://projects.unbit.it/uwsgi/',
license='GPL2',
py_modules = ['uwsgidecorators'],
distclass = uWSGIDistribution,
)
+104 -3
View File
@@ -12,7 +12,55 @@ int uwsgi_signal_handler(uint8_t sig) {
return -1;
}
return uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
// set harakiri here (if required and if i am a worker)
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].sig = 1;
uwsgi.workers[uwsgi.mywid].signum = sig;
uwsgi.workers[uwsgi.mywid].signals++;
if(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
}
else if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid-1].sig = 1;
uwsgi.mules[uwsgi.muleid-1].signum = sig;
uwsgi.mules[uwsgi.muleid-1].signals++;
if(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0 && (getpid() == uwsgi.shared->spooler_pid)) {
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
}
#endif
int ret = uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].sig = 0;
if(uwsgi.workers[uwsgi.mywid].harakiri > 0) {
set_harakiri(0);
}
}
else if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid-1].sig = 0;
if(uwsgi.mules[uwsgi.muleid-1].harakiri > 0) {
set_mule_harakiri(0);
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0 && (getpid() == uwsgi.shared->spooler_pid)) {
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
}
#endif
return ret;
}
int uwsgi_signal_registered(uint8_t sig) {
@@ -166,7 +214,7 @@ void uwsgi_route_signal(uint8_t sig) {
// send to all workers
else if (!strcmp(use->receiver, "workers")) {
for(i=1;i<=uwsgi.numproc;i++) {
if (write(uwsgi.signal_pipe[i][0], &sig, 1) != 1) {
if (write(uwsgi.workers[i].signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
@@ -178,7 +226,7 @@ void uwsgi_route_signal(uint8_t sig) {
if (i > uwsgi.numproc) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
if (write(uwsgi.signal_pipe[i][0], &sig, 1) != 1) {
if (write(uwsgi.workers[i].signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
@@ -187,6 +235,7 @@ void uwsgi_route_signal(uint8_t sig) {
else if (!strcmp(use->receiver, "subscribed")) {
}
// route to spooler
#ifdef UWSGI_SPOOLER
else if (!strcmp(use->receiver, "spooler")) {
if (ushared->worker_signal_pipe[0] != -1) {
if (write(ushared->spooler_signal_pipe[0], &sig, 1) != 1) {
@@ -195,6 +244,58 @@ void uwsgi_route_signal(uint8_t sig) {
}
}
}
#endif
else if (!strcmp(use->receiver, "mules")) {
for(i=0;i<uwsgi.mules_cnt;i++) {
if (write(uwsgi.mules[i].signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i+1);
}
}
}
else if (!strncmp(use->receiver, "mule", 4)) {
i = atoi(use->receiver+4);
if (i > uwsgi.mules_cnt) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
else if (i == 0) {
if (write(ushared->mule_signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to a mule\n", sig);
}
}
else {
if (write(uwsgi.mules[i-1].signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i);
}
}
}
else if (!strncmp(use->receiver, "farm_", 5)) {
char *name = use->receiver+5;
struct uwsgi_farm *uf = get_farm_by_name(name);
if (!uf) {
uwsgi_log("unknown farm: %s\n", name);
return;
}
if (write(uf->signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, uf->id, uf->name);
}
}
else if (!strncmp(use->receiver, "farm", 4)) {
i = atoi(use->receiver+4);
if (i > uwsgi.farms_cnt || i <= 0) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
else {
if (write(uwsgi.farms[i-1].signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, i, uwsgi.farms[i-1].name);
}
}
}
else {
// unregistered signal, sending it to all the workers
uwsgi_log("^^^ UNSUPPORTED SIGNAL TARGET: %s ^^^\n", use->receiver);
+10
View File
@@ -0,0 +1,10 @@
/* this is a skeleton to use libuwsgi in external projects */
extern char **environ;
int uwsgi_init(int, char **, char **);
int main(int argc, char **argv, char **environ) {
uwsgi_init(argc, argv, environ);
}
-117
View File
@@ -350,123 +350,6 @@ static int get_snmp_integer(uint8_t * ptr, uint64_t * val) {
return size + oid_sz;
}
/*
PyObject *py_snmp_counter32(PyObject * self, PyObject * args) {
uint8_t oid_num;
uint32_t oid_val = 0;
if (!PyArg_ParseTuple(args, "bI:snmp_set_counter32", &oid_num, &oid_val)) {
return NULL;
}
if (oid_num > 100 || oid_num < 1)
goto clear;
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER32;
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
Py_INCREF(Py_True);
return Py_True;
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_snmp_counter64(PyObject * self, PyObject * args) {
uint8_t oid_num;
uint64_t oid_val = 0;
if (!PyArg_ParseTuple(args, "bK:snmp_set_counter64", &oid_num, &oid_val)) {
return NULL;
}
if (oid_num > 100 || oid_num < 1)
goto clear;
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER64;
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
Py_INCREF(Py_True);
return Py_True;
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_snmp_gauge(PyObject * self, PyObject * args) {
uint8_t oid_num;
uint32_t oid_val = 0;
if (!PyArg_ParseTuple(args, "bI:snmp_set_gauge", &oid_num, &oid_val)) {
return NULL;
}
if (oid_num > 100 || oid_num < 1)
goto clear;
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_GAUGE;
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
Py_INCREF(Py_True);
return Py_True;
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_snmp_community(PyObject * self, PyObject * args) {
char *snmp_community;
if (!PyArg_ParseTuple(args, "s:snmp_set_community", &snmp_community)) {
return NULL;
}
if (strlen(snmp_community) > 72) {
uwsgi_log( "*** warning the supplied SNMP community string will be truncated to 72 chars ***\n");
memcpy(uwsgi.shared->snmp_community, snmp_community, 72);
}
else {
memcpy(uwsgi.shared->snmp_community, snmp_community, strlen(snmp_community) + 1);
}
Py_INCREF(Py_True);
return Py_True;
}
static PyMethodDef uwsgi_snmp_methods[] = {
{"snmp_set_counter32", py_snmp_counter32, METH_VARARGS, ""},
{"snmp_set_counter64", py_snmp_counter64, METH_VARARGS, ""},
{"snmp_set_gauge", py_snmp_gauge, METH_VARARGS, ""},
{"snmp_set_community", py_snmp_community, METH_VARARGS, ""},
{NULL, NULL},
};
void snmp_init() {
PyMethodDef *uwsgi_function;
for (uwsgi_function = uwsgi_snmp_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(uwsgi.embedded_dict, uwsgi_function->ml_name, func);
Py_DECREF(func);
}
uwsgi_log( "SNMP python functions initialized.\n");
}
*/
#else
#warning "*** SNMP support is disabled ***"
#endif
+44 -1
View File
@@ -474,7 +474,13 @@ socklen_t socket_to_in_addr(char *socket_name, char *port, struct sockaddr_in *s
sin_addr->sin_addr.s_addr = INADDR_ANY;
}
else {
sin_addr->sin_addr.s_addr = inet_addr(socket_name);
char *resolved = uwsgi_resolve_ip(socket_name);
if (resolved) {
sin_addr->sin_addr.s_addr = inet_addr(resolved);
}
else {
sin_addr->sin_addr.s_addr = inet_addr(socket_name);
}
}
return sizeof(struct sockaddr_in);
@@ -749,6 +755,20 @@ struct uwsgi_socket *uwsgi_new_socket(char *name) {
if (!name) return uwsgi_sock;
if (name[0] == '=') {
int shared_socket = atoi(uwsgi_sock->name+1);
if (shared_socket >= 0) {
struct uwsgi_socket *uss = uwsgi_get_shared_socket_by_num(shared_socket);
if (!uss) {
uwsgi_log("unable to use shared socket %d\n", shared_socket);
exit(1);
}
uwsgi_sock->bound = 1;
uwsgi_sock->shared = 1;
uwsgi_sock->from_shared = shared_socket;
return uwsgi_sock;
}
}
char *tcp_port = strchr(name, ':');
if (tcp_port) {
// INET socket, check for 0 port
@@ -951,6 +971,29 @@ int uwsgi_get_shared_socket_fd_by_num(int num) {
return -1;
}
struct uwsgi_socket *uwsgi_get_shared_socket_by_num(int num) {
int counter = 0;
struct uwsgi_socket *found_sock = NULL, *uwsgi_sock = uwsgi.shared_sockets;
while(uwsgi_sock) {
if (counter == num) {
found_sock = uwsgi_sock;
break;
}
counter++;
uwsgi_sock = uwsgi_sock->next;
}
if (found_sock) {
return found_sock;
}
return NULL;
}
void uwsgi_add_sockets_to_queue(int queue) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
+64 -28
View File
@@ -9,43 +9,52 @@ static void spooler_scandir(char *);
#endif
void spooler_manage_task(char *, char *);
// fake function to allow waking the spooler
void spooler_wakeup() {}
pid_t spooler_start() {
int i;
if (uwsgi.master_process) {
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]);
// setup internal signalling system
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->spooler_signal_pipe)) {
uwsgi_error("socketpair()\n");
exit(1);
}
}
pid_t pid = fork();
pid_t pid = uwsgi_fork("uWSGI spooler");
if (pid < 0) {
uwsgi_error("fork()");
exit(1);
}
else if (pid == 0) {
// USR1 will be used to wake up the spooler
signal(SIGUSR1, spooler_wakeup);
uwsgi.mywid = -1;
uwsgi.mypid = getpid();
// avoid race conditions !!!
uwsgi.shared->spooler_pid = uwsgi.mypid;
uwsgi_fixup_fds(0, 0);
uwsgi_close_all_sockets();
if (uwsgi.master_process) {
close(uwsgi.shared->spooler_signal_pipe[0]);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.signal_pipe[i][0] != -1) {
close(uwsgi.signal_pipe[i][0]);
}
}
}
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->spooler_init) {
uwsgi.gp[i]->spooler_init();
}
}
spooler();
}
else if (pid > 0) {
if (uwsgi.master_process) {
close(uwsgi.shared->spooler_signal_pipe[1]);
}
uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uwsgi.spool_dir, pid);
}
@@ -160,13 +169,20 @@ int spool_request(char *filename, int rn, int core_id, char *buffer, int size, c
uwsgi_unlock(uwsgi.spooler_lock);
/* wake up the spooler ... (HACKY) */
if (uwsgi.shared->spooler_pid > 0 ) {
(void) kill(uwsgi.shared->spooler_pid, SIGUSR1);
}
return 1;
clear:
uwsgi_unlock(uwsgi.spooler_lock);
uwsgi_error("write()");
unlink(filename);
if (unlink(filename)) {
uwsgi_error("unlink()");
}
close(fd);
return 0;
}
@@ -220,6 +236,8 @@ void spooler() {
if (uwsgi.spooler_ordered) {
#ifdef __linux__
spooler_scandir(uwsgi.spool_dir);
#else
spooler_readdir(uwsgi.spool_dir);
#endif
}
else {
@@ -231,10 +249,8 @@ void spooler() {
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[1]) {
uint8_t uwsgi_signal;
if (read(interesting_fd, &uwsgi_signal, 1) <= 0) {
if (uwsgi.no_orphans) {
uwsgi_log_verbose("uWSGI spooler screams: UAAAAAAH my master died, i will follow him...\n");
end_me(0);
}
}
else {
#ifdef UWSGI_DEBUG
@@ -333,7 +349,12 @@ void spooler_manage_task(char *dir, char *task) {
if (!access(task, R_OK | W_OK)) {
uwsgi_log("managing spool request %s ...\n", task);
#ifdef __sun__
// lockf needs write permission
spool_fd = open(task, O_RDWR);
#else
spool_fd = open(task, O_RDONLY);
#endif
if (spool_fd < 0) {
uwsgi_error_open(task);
return;
@@ -382,16 +403,29 @@ void spooler_manage_task(char *dir, char *task) {
close(spool_fd);
if (uwsgi.spooler_chdir) {
if (chdir(uwsgi.spooler_chdir)) {
uwsgi_error("chdir()");
}
}
int callable_found = 0;
for(i=0;i<0xff;i++) {
if (uwsgi.p[i]->spooler) {
time_t now = time(NULL);
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
if (body) {
free(body);
}
if (ret == 0) continue;
callable_found = 1;
if (ret == -2) {
uwsgi_log("done with task/spool %s after %d seconds\n", task, time(NULL)-now);
destroy_spool(dir, task);
}
@@ -399,6 +433,9 @@ void spooler_manage_task(char *dir, char *task) {
break;
}
}
if (!callable_found) {
uwsgi_log("unable to find the spooler function, have you loaded it into the spooler process ?\n");
}
}
}
@@ -416,7 +453,6 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
return -1;
}
uwsgi_log("managing spool request...\n");
i = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, wsgi_req->buffer, wsgi_req->uh.pktsize, NULL, 0, NULL, 0);
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
+274
View File
@@ -0,0 +1,274 @@
#include "uwsgi.h"
/*
subscription subsystem
each subscription slot is as an auto-optmizing linked list. Originally it was a uwsgi_dict (now removed from uWSGI) but this
would have not be able to support regexp as keys.
each slot has another circular linked list containing the nodes names
the structure and system is very similar to uwsgi_dyn_dict already used by the mime type parser
This system is not mean to run on shared memory. If you have multiple processes for the same app, you have to create
a new subscriptions slot list.
*/
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, int regexp) {
struct uwsgi_subscribe_slot *current_slot = *slot;
if (keylen > 0xff) return NULL;
while(current_slot) {
#ifdef UWSGI_PCRE
if (regexp) {
if (uwsgi_regexp_match(current_slot->pattern, current_slot->pattern_extra, key, keylen) >= 0) {
return current_slot;
}
}
else {
#endif
if (!uwsgi_strncmp(key, keylen, current_slot->key, current_slot->keylen)) {
// auto optimization
if (current_slot->prev) {
if (current_slot->hits > current_slot->prev->hits) {
struct uwsgi_subscribe_slot *slot_parent = current_slot->prev->prev, *slot_prev = current_slot->prev;
if (slot_parent) {
slot_parent->next = current_slot;
}
else {
*slot = current_slot;
}
slot_prev->prev = current_slot;
slot_prev->next = current_slot->next;
current_slot->next = slot_prev;
current_slot->prev = slot_parent;
}
}
return current_slot;
}
#ifdef UWSGI_PCRE
}
#endif
current_slot = current_slot->next;
}
return NULL;
}
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, int regexp) {
if (keylen > 0xff) return NULL;
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen, regexp);
uint64_t rr_pos = 0;
if (current_slot) {
// node found, move up in the list increasing hits
current_slot->hits++;
struct uwsgi_subscribe_node *node = current_slot->nodes;
while(node) {
if (rr_pos == current_slot->rr) {
current_slot->rr++;
return node;
}
node = node->next;
rr_pos++;
}
current_slot->rr = 0;
return current_slot->nodes;
}
return NULL;
}
void uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_node *node) {
struct uwsgi_subscribe_node *a_node;
struct uwsgi_subscribe_slot *node_slot = node->slot;
struct uwsgi_subscribe_slot *prev_slot = node_slot->prev;
struct uwsgi_subscribe_slot *next_slot = node_slot->next;
// over-engineering to avoid race conditions
node->len = 0;
if (node == node_slot->nodes) {
node_slot->nodes = node->next;
}
else {
a_node = node_slot->nodes;
while(a_node) {
if (a_node->next == node) {
a_node->next = node->next;
break;
}
a_node = a_node->next;
}
}
free(node);
// no more nodes, remove the slot too
if (node_slot->nodes == NULL) {
if (prev_slot) {
prev_slot->next = next_slot;
}
if (next_slot) {
next_slot->prev = prev_slot;
}
#ifdef UWSGI_PCRE
if (node_slot->pattern) {
pcre_free(node_slot->pattern);
}
if (node_slot->pattern_extra) {
pcre_free(node_slot->pattern_extra);
}
#endif
free(node_slot);
// am i the only slot ?
if (!prev_slot && !next_slot) {
*slot = NULL;
}
}
}
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_req *usr, int regexp) {
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, usr->key, usr->keylen, 0), *old_slot = NULL, *a_slot;
struct uwsgi_subscribe_node *node, *old_node = NULL;
if (usr->address_len > 0xff) return NULL;
if (current_slot) {
node = current_slot->nodes;
while(node) {
if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) {
node->last_check = time(NULL);
return node;
}
old_node = node;
node = node->next;
}
node = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
node->len = usr->address_len;
node->modifier1 = usr->modifier1;
node->modifier2 = usr->modifier2;
node->last_check = time(NULL);
node->slot = current_slot;
memcpy(node->name, usr->address, usr->address_len);
if (old_node) {
old_node->next = node;
}
node->next = NULL;
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
return node;
}
else {
current_slot = uwsgi_malloc(sizeof(struct uwsgi_subscribe_slot));
current_slot->keylen = usr->keylen;
memcpy(current_slot->key, usr->key, usr->keylen);
current_slot->key[usr->keylen] = 0;
current_slot->hits = 0;
current_slot->rr = 0;
#ifdef UWSGI_PCRE
current_slot->pattern = NULL;
current_slot->pattern_extra = NULL;
if (regexp) {
if (uwsgi_regexp_build(current_slot->key, &current_slot->pattern, &current_slot->pattern_extra)) {
free(current_slot);
return NULL;
}
}
#endif
current_slot->nodes = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
current_slot->nodes->slot = current_slot;
current_slot->nodes->len = usr->address_len;
current_slot->nodes->modifier1 = usr->modifier1;
current_slot->nodes->modifier2 = usr->modifier2;
memcpy(current_slot->nodes->name, usr->address, usr->address_len);
current_slot->nodes->last_check = time(NULL);
current_slot->nodes->next = NULL;
#ifdef UWSGI_PCRE
// if key is a regexp, order it by keylen
if (regexp) {
old_slot = NULL;
a_slot = *slot;
while(a_slot) {
if (a_slot->keylen > current_slot->keylen) {
old_slot = a_slot;
break;
}
a_slot = a_slot->next;
}
if (old_slot) {
current_slot->prev = old_slot->prev;
old_slot->prev = current_slot;
if (current_slot->prev) {
old_slot->prev->next = current_slot;
}
current_slot->next = old_slot;
}
else {
a_slot = *slot;
while(a_slot) {
old_slot = a_slot;
a_slot = a_slot->next;
}
if (old_slot) {
old_slot->next = current_slot;
}
current_slot->prev = old_slot;
current_slot->next = NULL;
}
}
else {
#endif
a_slot = *slot;
while(a_slot) {
old_slot = a_slot;
a_slot = a_slot->next;
}
if (old_slot) {
old_slot->next = current_slot;
}
current_slot->prev = old_slot;
current_slot->next = NULL;
#ifdef UWSGI_PCRE
}
#endif
if (!*slot || current_slot->prev == NULL) {
*slot = current_slot;
}
uwsgi_log("[uwsgi-subscription] new pool: %.*s\n", usr->keylen, usr->key);
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
return current_slot->nodes;
}
}
+23
View File
@@ -0,0 +1,23 @@
- case 1
single static app
- case 2
single static multiapp
- case 3
multi app static mountpoint
- case 4
dynamic apps with UWSGI_APPID
- case 5
dynamic apps with SCRIPT_NAME
- case 6
dynamic apps with vhost mode

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