Compare commits

...
284 Commits
Author SHA1 Message Date
roberto@oneiric64 b0af1f800b fixed a bug in #ifdef for pump/web3 spotted by riccardo 2011-11-26 18:39:44 +01:00
roberto@oneiric64 543271e856 fixed a ksm leak 2011-11-26 13:02:47 +01:00
roberto@oneiric64 a1564a44fa added postgresql probe 2011-11-26 12:44:38 +01:00
roberto@oneiric64 571029cfd3 added probe infrastructure 2011-11-26 11:05:49 +01:00
roberto@oneiric64 579eaa630a refactored daemons and removed uwsgi.attach_daemon function 2011-11-26 09:04:19 +01:00
roberto@oneiric64 9530c8ffe0 applied riccardo's patch [2] 2011-11-26 08:10:29 +01:00
roberto@oneiric64 0d8690091b applied riccardo's patch [1] 2011-11-26 08:04:39 +01:00
roberto@goyle 5b5e3a1ec1 added delta_requests 2011-11-25 15:34:41 +01:00
roberto@centos64 869ae5e3ed allows the building of uWSGI on ancient linux kernel (like CentOS4) 2011-11-24 12:57:08 +01:00
roberto@oneiric64 d6dc8d86f8 added subscription report on startup 2011-11-24 07:42:14 +01:00
roberto@oneiric64 758745be68 closed bug #56 2011-11-24 07:35:32 +01:00
roberto@oneiric64 2adfa56d6a added threading name in python threads object 2011-11-23 17:44:41 +01:00
roberto@oneiric64 a4c728f5df added auto-patching for Rack::BodyProxy.each 2011-11-23 11:45:13 +01:00
roberto@oneiric64 5c06341b7f ready for -rc7 2011-11-23 10:08:49 +01:00
roberto@oneiric64 6f57902a9b another cron fix 2011-11-23 05:37:00 +01:00
roberto@longshot a3e118893d do not build sqlite on unbit 2011-11-22 18:52:12 +01:00
roberto@oneiric64 ff2d3c29d6 fixed a bug in cron management 2011-11-22 17:56:03 +01:00
roberto@oneiric64 59a8df85f2 added --st as a --subscribe/--subscribe-to alias 2011-11-22 11:23:10 +01:00
roberto@oneiric64 e303bd182a report subscribed nodes timeout 2011-11-22 11:15:13 +01:00
roberto@oneiric64 dcef9a497c less verbose build system 2011-11-22 09:46:16 +01:00
roberto@oneiric64 8d4fd66aaf fixed a bug in execvp() during reload on 64 bit 2011-11-22 09:16:34 +01:00
roberto@debian32 471bd23acf added --subscribe-freq and --subscription-tolerance 2011-11-21 20:22:00 +01:00
roberto@debian32 ffcef81dd0 greatly improved subscription system 2011-11-21 16:23:24 +01:00
roberto@debian32 317df5d06b added @(filename) magic var 2011-11-21 13:22:05 +01:00
roberto@debian32 ad7b5efd6f added --logfile-chmod 2011-11-21 10:32:48 +01:00
roberto@deban32 891f770724 added Lukas to CONTRIBUTORS 2011-11-21 09:55:43 +01:00
roberto@debian32.local 0b6d715982 refactored ping and nagios 2011-11-21 09:42:48 +01:00
roberto@debian32 76c2415516 moved cluster-related functions to a dedicated file 2011-11-20 11:36:42 +01:00
roberto@gambit 3260faca17 Added tag 1.0-rc6 for changeset a2b8f25fd17e 2011-11-19 08:40:45 +01:00
roberto@arch32 feb493158c a fix fir capability support on arch linux 2011-11-19 07:55:22 +01:00
roberto@debian32 a5c1556cb7 do not exit on realod if chdir() fail 2011-11-18 20:46:07 +01:00
roberto@longshot 89e640bdd9 better to not remove -g/-ggdb 2011-11-18 09:29:30 +01:00
roberto@longshot 3ade8daff8 fixed rack compilation 2011-11-18 09:23:06 +01:00
roberto@debian32 049ea3fbed added Linux KSM support 2011-11-17 11:16:48 +01:00
roberto@goyle 715d26beed added support for remote signalling in rack plugin 2011-11-16 18:30:00 +01:00
roberto@goyle 1f5064094c better signal registration reporting 2011-11-15 18:33:44 +01:00
roberto@goyle 7ed522dc29 added --signal 2011-11-15 18:18:42 +01:00
roberto@goyle 2086500405 added signal plugin 2011-11-15 18:06:37 +01:00
roberto@debian32 8f79409ed1 added uwsgi.route() 2011-11-14 15:05:23 +01:00
roberto@debian32 c2a3cd1476 added mule support to ruby DSL 2011-11-13 17:25:47 +01:00
roberto@debian32 e195a5d72c improved signal handling and rack mule_msg 2011-11-13 15:08:29 +01:00
roberto@debian32 c86b757904 use app_id in rack plugin 2011-11-12 16:24:47 +01:00
roberto@debian32 6800d2ac95 added lock/unlock to rack plugin 2011-11-12 11:31:22 +01:00
roberto@debian32 90fda2b4bb added UWSGI.mem 2011-11-12 11:18:25 +01:00
roberto@debian32 bf7ded9058 added a bunch of constant to rack plugin 2011-11-12 11:13:06 +01:00
roberto@debian32 6615dc3a62 added UWSGI.setprocname 2011-11-12 11:07:38 +01:00
roberto@debian32 c35054085c completed ruby cache support 2011-11-12 11:02:30 +01:00
roberto@debian32 fdf2bd7f96 fixed ruby 1.9 support 2011-11-12 10:53:19 +01:00
roberto@debian32 1c10b9dfe1 ported cache api to rack plugin 2011-11-12 10:44:23 +01:00
roberto@debian32 6854394e5c added rpc support to ruby 2011-11-11 12:29:04 +01:00
roberto@debian32 78a0d5f432 added postfork in uwsgidsl 2011-11-11 09:57:35 +01:00
roberto@debian32 5fe5aa70a4 added post_fork_hook to ruby 2011-11-11 09:49:17 +01:00
roberto@debian32 e9c0c6bd0b report GC frequency 2011-11-11 06:54:08 +01:00
roberto@debian32 5d12b3dc9c added --rbrequire 2011-11-11 06:51:29 +01:00
roberto@debian32 169a4b66db added UWSGI.signal_received to ruby 2011-11-10 16:32:26 +01:00
roberto@debian32 fbd6329db9 improved ruby signal handling 2011-11-10 16:11:48 +01:00
roberto@debian32 69c2e56857 ported python plugin to new signal_wait api 2011-11-10 15:36:36 +01:00
roberto@debian32 18f7d1edd3 refactored signal_wait 2011-11-10 15:34:19 +01:00
roberto@debian32 3f7cd5ff92 added rubydsl 2011-11-10 15:33:41 +01:00
roberto@debian32 785e1dbf83 re-thinked remap-modifier 2011-11-10 15:33:19 +01:00
roberto@debian32 bc6acf8d14 use SIGTSTP instead of SIGWINCH for pause/suspend/resume 2011-11-10 11:25:22 +01:00
roberto@sirius 3a099d0b2e added --pause/--suspend/--resume 2011-11-10 09:38:32 +01:00
roberto@longshot f9ad5e4144 fixed multi-option parser 2011-11-09 20:58:33 +01:00
roberto@debian32 ce9f6650a0 allows carbon-id to include dots 2011-11-09 07:08:44 +01:00
roberto@mrspurr fdeef04343 fixed a stupid bug in carbon plugin 2011-11-09 06:57:21 +01:00
roberto@debian32 fe72ec82e1 completed carbon plugin 2011-11-09 06:50:51 +01:00
roberto@debian32 fd0f308273 added carbon plugin 2011-11-09 06:25:38 +01:00
roberto@longshot f4e9ab43cb fixed rack compilation 2011-11-08 18:46:29 +01:00
roberto@debian32 3a141b523c Added tag 1.0-rc5 for changeset 043ba93dd69c 2011-11-03 09:40:07 +01:00
roberto@debian32 2d731532be various erlang fixes 2011-11-03 09:09:17 +01:00
roberto@debian32 d545cd5be0 added @erlang decorator 2011-11-02 20:48:11 +01:00
roberto@debian32 261d05d67e added @mulemsg decorator 2011-11-02 19:55:11 +01:00
roberto@debian32 639995785a fixed pyerl 2011-11-02 14:41:32 +01:00
roberto@debian32 817e076cae uwsgidecorators is installed when run under pip/easy_install 2011-11-02 14:20:51 +01:00
roberto@debian32 713370f343 completed regexp support in subscription system 2011-11-01 08:33:52 +01:00
roberto@debian32 5594503a56 pcre support in subscription system 2011-10-31 09:11:02 +01:00
roberto@debian32 d57e5d46fb fixed subscriptions removal in http plugin 2011-10-31 07:56:01 +01:00
roberto@debian32 ee2db5fabd a bunch of subscription optimizations 2011-10-30 13:10:26 +01:00
roberto@debian32 0c4cd6f378 ported http plugin to new subscription system 2011-10-30 11:36:53 +01:00
roberto@debian32 8c32b9665c re-implementation of subscription system 2011-10-30 11:30:53 +01:00
roberto@colossus 7405a01654 ready for next -rc ? 2011-10-28 17:53:16 +02:00
roberto@colossus 5d27691b4b fixed log rotation 2011-10-28 16:49:26 +02:00
roberto@debian32 19bbcfbf4c added @mule decorator 2011-10-28 16:22:39 +02:00
roberto@debian32 fa1064db87 added --umask 2011-10-28 16:10:26 +02:00
roberto@colossus 850ac69ca1 fixed master reloading 2011-10-28 11:35:18 +02:00
roberto@debian32 943edeb30c fixed a typo in subscribe-to and incresed slots to 64 2011-10-28 08:11:51 +02:00
roberto@debian32 01815a354b added a centos init script in contrib 2011-10-27 13:54:29 +02:00
roberto@debian32 2f4412aca1 allows .json as a valid vassal extension 2011-10-27 13:52:11 +02:00
roberto@oneiric64 2782bb7594 fixed 64bit support in rrdtool 2011-10-27 12:44:01 +02:00
roberto@debian32 074c1298d5 procname-prefix-spaced 2011-10-27 10:08:38 +02:00
roberto@debian32 55a7911611 added rrdtool plugin 2011-10-27 09:26:59 +02:00
roberto@debian32 013ad3044d added @mulefuc decorators 2011-10-26 10:51:03 +02:00
roberto@debian32 dcf4217b9d greatly improved uwsgi.mule_msg() 2011-10-26 10:13:20 +02:00
roberto@debian32 876dfc31a9 dynamic buffer_size and timeout for mule_get_msg 2011-10-26 06:43:07 +02:00
roberto@debian32 fd03bdbe00 improved mule and farm signal handling 2011-10-26 06:30:42 +02:00
roberto@debian32 83612649d5 mule_get_msg can manage signals 2011-10-26 06:11:07 +02:00
roberto@debian32 3c4db7e97e timerfd_create workaround 2011-10-26 05:45:06 +02:00
roberto@colossus 088c70efdc fixed locking 2011-10-25 18:05:52 +02:00
roberto@debian32 2b19029dd0 multiple mule_msg() 2011-10-25 17:46:41 +02:00
roberto@debian32 4fb5a84378 improved multi-mule support 2011-10-25 17:35:52 +02:00
roberto@debian32 b3107d9a25 another mule fix 2011-10-25 17:03:13 +02:00
roberto@debian32 bf32988f3e applied riccardo magliocchetti patch for .json support 2011-10-25 16:44:33 +02:00
roberto@debian32 1bf3dd7bf4 fixed mule patch message 2011-10-24 18:52:41 +02:00
roberto@debian32 07fd84f89f ported symimporter/symzipimporter to python3 2011-10-24 16:35:59 +02:00
roberto@debian32 3a8db4a97a fixed unlocking 2011-10-24 15:56:17 +02:00
roberto@debian32 aea30a26f5 added --mules <n> 2011-10-24 10:40:29 +02:00
roberto@gambit 8f5d1cdae7 Added tag 1.0-rc4 for changeset 24f7e260ea34 2011-10-24 10:05:02 +02:00
roberto@gambit 53913357e0 fixed strtok usage 2011-10-24 10:04:25 +02:00
roberto@debian32 098416f444 uWSGI 1.0-rc3 2011-10-24 09:42:41 +02:00
roberto@debian32 c98cb09c7c Added tag 1.0-rc3 for changeset 4e4e781ef89a 2011-10-24 09:42:27 +02:00
roberto@debian32 bb1ef28d69 updated decorators with @farm([name]) 2011-10-23 19:59:53 +02:00
roberto@debian32 1d5b05265d initial farm implementation 2011-10-23 19:18:31 +02:00
roberto@debian32 d9fef3c30e a little hack for psgi loader waiting for a truly agnostic init_uwsgi_app 2011-10-23 12:14:53 +02:00
roberto@debian32 e5dfb9efc3 improved get_memusage 2011-10-23 12:04:02 +02:00
roberto@debian32 02bab15e86 perl threading improvements 2011-10-23 11:49:25 +02:00
roberto@debian32 6f4ddead09 Added tag 1.0-rc2 for changeset 7a4e021ea7ba 2011-10-23 08:37:03 +02:00
roberto@gambit b361248ff6 fixed add_exported_opts 2011-10-23 08:35:15 +02:00
roberto@debian32 e9c42ceaa5 support for multiple values in options 2011-10-22 18:32:32 +02:00
roberto@debian32 5d7029744a PATH_INFO is correctly escaped in http modes 2011-10-22 09:35:01 +02:00
roberto@gambit 1084a3afa8 fixed mule patch loading 2011-10-20 10:38:59 +02:00
roberto@gambit ed254bffee fixed mule process name 2011-10-20 10:20:44 +02:00
roberto@djangocloud 733784d7dd another procname fix... 2011-10-19 16:13:10 +10:00
roberto@djangocloud cb5b26bcb4 another bunch of procname fixes 2011-10-19 14:26:07 +10:00
roberto@djangocloud 0065152bb1 daemons throttling subsystem 2011-10-18 18:53:22 +10:00
roberto@djangocloud 03266203fd another fix for environ 2011-10-18 18:30:13 +10:00
roberto@djangocloud 4a5f68f9d8 fixed environ 2011-10-18 18:12:39 +10:00
roberto@djangocloud 83e31a1c27 another setprocname fix 2011-10-18 16:20:33 +10:00
roberto@djangocloud 0efed5ef9c various emperor procname fixes 2011-10-18 16:15:06 +10:00
roberto@djangocloud cdfef1281d fixed another spooler compilation bug 2011-10-18 15:12:59 +10:00
roberto@debian32 e00907e142 --spooler-harakiri 2011-10-17 19:07:12 +02:00
roberto@app1 6dcbcf39e3 fixed compilation when spooler is disabled 2011-10-17 03:16:55 -05:00
roberto@debian32 044579a8e0 more verbose annihilation report 2011-10-16 11:16:13 +02:00
roberto@debian32 d2b52b4663 added uwsgi.setprocname() 2011-10-16 10:37:26 +02:00
roberto@debian32 7f75b2c02c added --procname and --procname-master 2011-10-16 10:18:45 +02:00
roberto@freebsd64 24a3f671e5 freebsd setproctitle 2011-10-16 10:06:08 +02:00
roberto@debian32 875100e3c8 check for mules before nuke 2011-10-16 09:58:37 +02:00
roberto@mrspurr 34bc7c0cfd check for procname 2011-10-16 09:54:35 +02:00
roberto@debian32 b39a10ff7c procname initial management 2011-10-16 09:45:41 +02:00
roberto@debian32 02331904de uWSGI 1.0-rc1 2011-10-15 08:47:00 +02:00
roberto@debian32 d1a4ae694e --locks 2011-10-15 08:32:32 +02:00
roberto@debian32 7a5ffc1124 --spooler-chdir 2011-10-14 19:20:05 +02:00
roberto@debian32 19c5bfb42c fixed a spooler signal bug spotted by Gabriele Giaccari 2011-10-14 18:32:17 +02:00
roberto@debian32 893bf3686b fixed a wrong typecast 2011-10-14 10:58:02 +02:00
roberto@debian32 e54fa9bcd4 added --emperor-stats 2011-10-13 07:53:32 +02:00
roberto@debian32 c1eb5ab0fe prepare for emperor-stats 2011-10-12 06:51:49 +02:00
roberto@mrspurr 461914dde4 completed --evil-reload options 2011-10-12 06:48:52 +02:00
roberto@debian32 85662578e4 implemented --mule-harakiri 2011-10-12 01:48:30 +02:00
roberto@debian32 a59c0ae795 setlinebuf in syslog mode 2011-10-12 00:54:18 +02:00
roberto@debian32 3a860155ee added --evil-reload-on-as and --evil-reload-on-rss 2011-10-11 20:39:00 +02:00
roberto@debian32 27553c2967 prepare for --evil-reload-... options 2011-10-11 20:18:31 +02:00
roberto@colossus 9a8ac9af3c added uwsgi.mule_id() 2011-10-11 07:31:41 +02:00
roberto@debian32 2f5daffe99 use hggit for better github sync 2011-10-09 09:11:54 +02:00
roberto@debian32 75cd31dce4 better spooler error reporting 2011-10-07 03:30:16 +02:00
roberto@colossus f7150d1b41 fixed mule socketpair 2011-10-06 18:37:24 +02:00
roberto@debian32 d6a6b65338 added --log-x-forwarded-for 2011-10-06 06:42:31 +02:00
roberto@freebsd64 979f6027b4 ignore SIGPIPE by default 2011-10-05 20:45:55 +02:00
roberto@freebsd64 7dc059c75b completed new freebsd64 sendfiel async support 2011-10-05 20:34:25 +02:00
roberto@freebsd64 b639b5974f better freebsd sendfile support 2011-10-05 20:19:12 +02:00
roberto@netbsd64 0de08c553c fixed a potential overflow 2011-10-05 21:16:28 +02:00
roberto@freebsd64 80788ac695 freebsd event fix 2011-10-05 19:01:29 +02:00
roberto@freebsd64 1494c621c1 non-linux fix 2011-10-05 18:43:53 +02:00
roberto@debian32 605e5b5173 export listen_queue size in stats 2011-10-05 17:24:46 +02:00
roberto@debian32 4cf2213051 added --log-truncate --log-reopen --log-maxsize --log-backupname 2011-10-05 11:58:15 +02:00
roberto@debian32 3aa36668e5 better error reporting 2011-10-04 20:28:08 +02:00
roberto@debian32 1c0b5b42e9 support for multiple --touch-reload options 2011-10-04 19:40:09 +02:00
roberto@openindiana64 702dc44fad fixed openindiana build on 64bit 2011-10-03 15:46:04 +02:00
roberto@solrisexpress 2cae07aa52 fixed 64bit compilation 2011-10-03 09:37:32 +00:00
roberto@ebian32 b5616ff25c completed mule signal handling 2011-10-03 08:36:21 +02:00
roberto@debian32 b7b7521975 refactored fds closing and socketpair 2011-10-03 08:29:19 +02:00
roberto@debian32 dce3263ee3 added mule messaging subsystem 2011-10-03 07:45:18 +02:00
roberto@debian32 9796e05ca1 added support for X_FORWARDED_SSL in http parser 2011-10-03 06:38:14 +02:00
roberto@debian32 5cc0d459ec struct uwsgi_server is becoming huge, better to add some comment 2011-10-02 20:45:03 +02:00
roberto@debian32 531a850a71 first almost-working commit for uWSGI mules 2011-10-02 20:05:31 +02:00
roberto@debian32 4c36280287 support --manage-script-name in http socket mode 2011-09-30 12:32:31 +02:00
roberto@debian32 70be8eb55e restored setup.py 2011-09-30 10:55:12 +02:00
roberto@debian32 f8b757b21e print argv in setup.py 2011-09-30 10:39:22 +02:00
roberto@debian32 3a63d352bb print envs in setup.py 2011-09-30 10:36:30 +02:00
roberto@sirius 60467705c5 fixed a stupid bug 2011-09-30 10:31:00 +02:00
roberto@debian32 eada0c09e0 refactored placeholder management 2011-09-30 10:21:26 +02:00
roberto@debian32 8e851aa6a1 fixed egg 2011-09-30 09:56:51 +02:00
roberto@debian32 eaf7bb967d added a check for http (3) 2011-09-30 09:43:42 +02:00
roberto@debian32 7be45c77b1 added a check for http (2) 2011-09-30 09:42:19 +02:00
roberto@debian32 5e2b460dc8 added a check for http (2) 2011-09-30 09:24:33 +02:00
roberto@debian32 16143e698f added a check for http 2011-09-30 09:21:12 +02:00
roberto@debian32 4259946e3b second little typecast fix 2011-09-30 08:51:18 +02:00
roberto@debian32 0a750d76ee little typecast fix 2011-09-30 08:50:00 +02:00
roberto@debian32 e4a9f5f0dd merge 2011-09-28 20:21:11 +02:00
roberto@debian32 d5b7698f89 added --stats 2011-09-28 20:20:40 +02:00
roberto@sirius a481e8508e added .gitignore 2011-09-28 17:23:22 +02:00
roberto@debian32 a53b57497b close bug #47 2011-09-28 07:27:43 +02:00
roberto@debian32 d871357b2d added uwsgi_req_error 2011-09-25 16:16:08 +02:00
roberto@debian32 2d57db55f4 removed a useless error checking 2011-09-25 14:06:06 +02:00
roberto@debian32 bae45ce03a error checking in uwsgi proto writer 2011-09-25 14:01:06 +02:00
roberto@debian32 44cc4336f1 added posix capability support 2011-09-25 13:41:10 +02:00
roberto@debian32 44f6e214fd improved uwsgi.queue_last 2011-09-25 10:44:19 +02:00
roberto@debian32 3e46f81d2b use PyLong_FromUnsignedLongLong 2011-09-25 06:42:23 +02:00
roberto@debian32 e4532b9a50 added memory usage in uwsgicc 2011-09-24 09:07:34 +02:00
roberto@debian32 2694be562c fixed respawn_count 2011-09-24 08:28:19 +02:00
roberto@debian32 fadb9edd7f added running time and avg_rt to uwsgicc 2011-09-24 08:24:51 +02:00
roberto@debian32 d85e0790de added response_time and running_time statistics 2011-09-24 06:40:30 +02:00
roberto@debian32 bc46c4d704 python3 fix 2011-09-23 08:36:28 +02:00
roberto@centos64 a73a010188 fixed build system for older gcc releases 2011-09-23 08:33:15 +02:00
roberto@debian3 4e8c8ef317 improved screen support 2011-09-21 06:09:05 +02:00
roberto@debian32 e402e7805d no need to set pty, screen is much metter 2011-09-21 05:27:58 +02:00
roberto@debian32 302b8f026b --cheaper improvement 2011-09-19 10:15:24 +02:00
roberto@debian32 630054b72a better wakeup of workers 2011-09-19 07:53:51 +02:00
roberto@debian32 a05f459b2b preliminary cheaper implementation 2011-09-19 07:13:45 +02:00
roberto@debian32 207979580a added uwsgi.extract 2011-09-18 07:04:36 +02:00
roberto@debian32 f69526f8bf parse plugin-specific options 2011-09-18 06:57:19 +02:00
roberto@debian32 e249d567a1 --fastrouter-cheap 2011-09-16 15:14:08 +02:00
roberto@debian32 a23ba653da better shared sockets support 2011-09-16 07:46:45 +02:00
roberto@debian32 0644d53572 set pty to raw mode 2011-09-13 08:35:50 +02:00
roberto@debian32 f58f51294d fixed sendfile typecasting 2011-09-11 07:41:42 +02:00
roberto@debian32 86194eb93e GC in symzipimporter is useless 2011-09-11 07:33:23 +02:00
roberto@debian32 0a89f375e6 added charles as contributor 2011-09-11 06:55:27 +02:00
roberto@debian32 6282178b3c fixed python optimize flag 2011-09-11 06:42:45 +02:00
roberto@debian32 8e14d68022 merge 2011-09-10 17:28:40 +02:00
roberto@debian32 e86bd0c070 preliminary support for detachable pyshell 2011-09-10 17:28:01 +02:00
roberto@mrspurr bf991f8892 report gb objects in welcome.py 2011-09-10 11:03:39 +02:00
roberto@mrspurr b341678d20 another symzip fix 2011-09-10 10:58:37 +02:00
roberto@mrspurr 5f59365d88 symzip GC fix 2011-09-10 10:54:27 +02:00
roberto@debian32 5130a7bb33 moved the old 'j' to 'J' option 2011-09-09 20:36:00 +02:00
roberto@dexter cc84a596d6 better iso99 check 2011-09-09 18:44:18 +02:00
roberto@longshot e67bed431a a fix for older gcc 2011-09-09 18:43:08 +02:00
roberto@dexter 72613a9f48 mime type optimization 2011-09-09 18:35:29 +02:00
roberto@sirius c048ea0615 better mimetype file check 2011-09-09 18:14:53 +02:00
roberto@dexter 957ca1b7ed added mime types support in static file serving 2011-09-09 17:06:35 +02:00
roberto@ebian32 d80a6df039 fixed a threading bug 2011-09-09 10:00:09 +02:00
roberto@mrspurr 94f9bd9d91 added Corey as contributor 2011-09-09 08:53:37 +02:00
roberto@mrspurr b480efe672 fixed script_name handling 2011-09-09 08:42:31 +02:00
roberto@mrspurr 4fc306d979 added a new debug entry 2011-09-09 08:32:20 +02:00
roberto@mrspurr 56abccbdeb another fix for urack.rb 2011-09-08 19:59:37 +02:00
roberto@mrspuur f218af0735 clang fixes 2011-09-08 19:45:46 +02:00
roberto@mrspurr 9b69c62780 automagic bundler in urack.rb 2011-09-08 13:44:50 +02:00
roberto@dexter eb5d67e07f 1.0 is better than 1.0.0 2011-09-07 16:09:45 +02:00
roberto@sirius e7391987b1 fixed sandboxviolation on osx 2011-09-07 12:33:12 +02:00
roberto@sirius 02cbe15575 test3 2011-09-07 12:32:02 +02:00
roberto@sirius a5a657f0d4 a second test 2011-09-07 12:29:24 +02:00
roberto@sirius 67567c86e0 a test 2011-09-07 12:27:47 +02:00
roberto@dexter 445d02da45 make easy_install happy 2011-09-06 17:58:02 +02:00
roberto@debian32 4a05df41ce subscription logging 2011-09-05 16:26:25 +02:00
roberto@debian32 5c0c2f6b45 yaml fix 2011-09-05 08:12:12 +02:00
roberto@debian32 0ab55fef46 added support for regexp in UWSGI_APPID 2011-09-04 21:33:30 +02:00
roberto@debian32 dd344bfe38 fixed a bug in multiapp mode 2011-09-04 18:01:04 +02:00
roberto@debian32 e92a889bcc refactored UWSGI_PY_READLINE_BUFSIZE 2011-09-03 07:15:51 +02:00
roberto@debian32 419d656a83 1.0.0-dev cycle started 2011-08-31 14:27:21 +02:00
roberto@debian32 3c3d58bfe9 pypyuwsgi.py 2011-08-31 14:01:46 +02:00
roberto@debian32 1989099cc5 preliminary pypy support 2011-08-31 13:18:32 +02:00
roberto@sirius 1446e3f0a9 allows pyuwsgi in osx 2011-08-31 12:09:56 +02:00
roberto@debian32 00fc31289d a pyuwsgi fix 2011-08-31 12:06:26 +02:00
roberto@sirius 2c463ad6af a test for libless pyuwsgi 2011-08-31 12:02:19 +02:00
roberto@sirius e641ae05c4 pyuwsgi 2011-08-31 11:42:22 +02:00
roberto@debian32 a13e0075ee fixed virtualhosting in fully-dynamic mode 2011-08-31 07:55:34 +02:00
roberto@debian32 e617a7b88e added an example for the new fd-based config 2011-08-30 12:08:22 +02:00
roberto@debian32 cbdeb4caad --stop and --reload, open by fifo and fd 2011-08-30 10:51:50 +02:00
roberto@sirius 59314d692f uWSGI 0.9.9 2011-08-29 17:32:08 +02:00
roberto@sirius 3dfa56b279 Added tag 0.9.9 for changeset 376ffd8f1906 2011-08-29 17:26:31 +02:00
roberto@dexter 920d5d7416 Changelog for 0.9.9 2011-08-29 11:32:27 +02:00
roberto@dexter dcb654d7fb spooler reload fix 2011-08-29 10:50:09 +02:00
roberto@solarisexpress a563da1223 solaris fix for lockf() 2011-08-29 10:34:46 +00:00
roberto@sirius 1e26cda615 fixed a race condition 2011-08-29 10:30:01 +02:00
roberto@dexter 97133b27ce the decoratortest is fully working, ready for release 2011-08-29 09:54:07 +02:00
roberto@sirius b428bd3b87 another bunch of build fixes 2011-08-29 08:02:37 +02:00
roberto@dexter 05136e74b4 fixed build system 2011-08-29 07:55:46 +02:00
roberto@mrspurr 9f28a8bdf1 improved upload progress 2011-08-28 20:53:46 +02:00
roberta@mrspurr d9361f1fee added test for upload progress 2011-08-28 19:13:56 +02:00
roberto@debian32 835230b1a4 emperor-tyrant 2011-08-28 09:15:13 +02:00
roberto@debian32 f88f51c553 added welcome.ini 2011-08-28 08:33:49 +02:00
roberto@debian32 1996305eb1 allows multiple --ini options 2011-08-28 07:55:54 +02:00
roberto@solrisexpress c7ad50e950 do not free getexecname() ret value 2011-08-28 07:37:21 +00:00
roberto@debian32 0ec0c29d67 fixed an indentation 2011-08-28 07:21:49 +02:00
roberto@solarisexpress 75af117e8a better magic plugin loading on binary_path 2011-08-28 07:14:42 +00:00
roberto@debian32 2b04cefe4e added help for a bunch of options 2011-08-27 19:37:34 +02:00
roberto@debian32 0e41c4111a fixed upstart 2011-08-27 18:46:53 +02:00
roberto@debian32 5f5d382c64 signal framework ported to gevent 2011-08-27 07:15:44 +02:00
roberto@dexter 3e867fe401 resolve domain names in socket logging 2011-08-26 16:20:14 +02:00
roberto@dexter 153142b8b0 fixed django uwsgi_admin without spooler 2011-08-26 15:02:02 +02:00
roberto@dexter 5562c0c047 use hub.join() instead of hub.switch() 2011-08-26 14:05:03 +02:00
roberto@debian32 f4a1f800ba timeout handling in gevent plugin 2011-08-26 12:34:12 +02:00
roberto@debian32 bdbc5e5605 another gevent improvement suggested by denis 2011-08-26 11:35:32 +02:00
roberto@debian32 4104f825ff another improvement for sys.executable in python3 2011-08-26 10:28:34 +02:00
roberto@longshot efa01ea404 better sys.executable and sys.argv values 2011-08-26 10:08:01 +02:00
roberto@debian32 982559ae66 snmp fixes 2011-08-26 09:54:11 +02:00
roberto@gambit 60002e8de8 Added tag 0.9.9-rc2 for changeset 6aa667612019 2011-08-26 08:17:20 +02:00
103 changed files with 9057 additions and 2430 deletions
+8
View File
@@ -30,3 +30,11 @@ fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
+3
View File
@@ -12,3 +12,6 @@ Marco Beri, Link I.T. S.p.a.
Leonid Borisenko
Cal Leeming, Simplicity Media Ltd
Luigi Scarso
Corey Farwell
Charles Duffy
Lukas Lalinsky
+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]
+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())
+3
View File
@@ -0,0 +1,3 @@
import uwsgi
print uwsgi.extract("data://0")
+2 -2
View File
@@ -3,7 +3,7 @@ xml = true
ini = true
yaml = true
json = auto
sqlite3 = auto
sqlite3 = false
zeromq = auto
snmp = true
sctp = false
@@ -27,7 +27,7 @@ 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, carbon, rpc, fastrouter, http, ugreen, signal
as_shared_library = false
locking = auto
+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
@@ -3,7 +3,7 @@ xml = true
ini = true
yaml = true
json = true
sqlite3 = true
sqlite3 = false
zeromq = false
snmp = false
sctp = false
+1 -294
View File
@@ -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,7 +284,7 @@ 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) {
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = &uwsgi.cache_items[index] ;
if (expires) {
expires += time(NULL);
@@ -528,71 +300,6 @@ end:
}
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) {
+355
View File
@@ -0,0 +1,355 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_UDP
void cluster_setup() {
int rlen;
// get cluster configuration
if (uwsgi.cluster != NULL) {
// get multicast socket
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
// ask for cluster options only if bot pre-existent options are set
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
// now wait max 60 seconds and resend multicast request every 10 seconds
for (;;) {
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
continue;
}
waitfd:
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
if (rlen < 0) {
break;
}
else if (rlen > 0) {
// receive the packet
char clusterbuf[4096];
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, manage_string_opt, NULL)) {
uwsgi_configure();
goto options_parsed;
}
else {
goto waitfd;
}
}
}
}
options_parsed:
if (!uwsgi.cluster_nodes)
uwsgi_cluster_add_me();
}
}
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
int i;
struct uwsgi_cluster_node *ucn;
char *tcp_port;
#ifdef UWSGI_DEBUG
uwsgi_log("adding node\n");
#endif
tcp_port = strchr(nucn->name, ':');
#ifndef UWSGI_ZEROMQ
if (tcp_port == NULL) {
#else
char *zmq_dash = strchr(nucn->name, '-');
if (tcp_port == NULL && zmq_dash == NULL) {
#endif
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
return;
}
// first check for already present node
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0) {
if (!strcmp(ucn->name, nucn->name)) {
ucn->status = UWSGI_NODE_OK;
ucn->last_seen = time(NULL);
// update requests
ucn->requests = nucn->requests;
return;
}
}
}
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] == 0) {
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
ucn->workers = nucn->workers;
ucn->ucn_addr.sin_family = AF_INET;
if (tcp_port) {
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
tcp_port[0] = 0;
}
if (nucn->name[0] == 0) {
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", nucn->name);
#endif
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
}
ucn->type = type;
// here memory can be freed, as it is allocated by uwsgi_concat2n
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
tcp_port[0] = ':';
}
ucn->last_seen = time(NULL);
ucn->requests = nucn->requests;
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
return;
}
}
uwsgi_log("unable to add node %s\n", nucn->name);
}
int uwsgi_cluster_add_me() {
const char *key1 = "hostname";
const char *key2 = "address";
const char *key3 = "workers";
const char *key4 = "requests";
char *ptrbuf;
uint16_t ustrlen;
char numproc[6];
#ifdef UWSGI_ZEROMQ
char uuid_zmq_str[37];
uuid_t uuid_zmq;
if (!uwsgi.sockets && !uwsgi.zeromq) {
#else
if (!uwsgi.sockets) {
#endif
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
exit(1);
}
snprintf(numproc, 6, "%d", uwsgi.numproc);
size_t len;
if (uwsgi.sockets) {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
uuid_generate(uuid_zmq);
uuid_unparse(uuid_zmq, uuid_zmq_str);
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#endif
else {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
char *buf = uwsgi_malloc(len);
ptrbuf = buf;
ustrlen = strlen(key1);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key1, strlen(key1));
ptrbuf += strlen(key1);
ustrlen = strlen(uwsgi.hostname);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
ptrbuf += strlen(uwsgi.hostname);
if (uwsgi.sockets && uwsgi.sockets->name) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uwsgi.sockets->name);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
ptrbuf += strlen(uwsgi.sockets->name);
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uuid_zmq_str);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
ptrbuf += strlen(uuid_zmq_str);
}
#endif
ustrlen = strlen(key3);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key3, strlen(key3));
ptrbuf += strlen(key3);
ustrlen = strlen(numproc);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, numproc, strlen(numproc));
ptrbuf += strlen(numproc);
ustrlen = strlen(key4);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key4, strlen(key4));
ptrbuf += strlen(key4);
ustrlen = 1;
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, "0", 1);
ptrbuf += 1;
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
free(buf);
#ifdef UWSGI_DEBUG
uwsgi_log("add_me() successfull\n");
#endif
return 0;
}
int uwsgi_cluster_join(char *name) {
int fd;
char *cp;
int broadcast = 0;
if (name[0] == ':') {
fd = bind_to_udp(name, 0, 1);
broadcast = 1;
}
else {
fd = bind_to_udp(name, 1, 0);
}
if (fd >= 0) {
cp = strchr(name, ':');
cp[0] = 0;
uwsgi.mc_cluster_addr.sin_family = AF_INET;
if (broadcast) {
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
}
else {
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
}
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
cp[0] = ':';
// announce my presence to all the nodes
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
}
else {
exit(1);
}
return fd;
}
char *uwsgi_cluster_best_node() {
int i;
int best_node = -1;
struct uwsgi_cluster_node *ucn;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
if (best_node == -1) {
best_node = i;
}
else {
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
best_node = i;
}
}
}
}
if (best_node == -1) {
return NULL;
}
uwsgi.shared->nodes[best_node].last_choosen = time(NULL);
return uwsgi.shared->nodes[best_node].name;
}
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
}
if (!uwsgi_strncmp("address", 7, key, keylen)) {
strncpy(ucn->name, val, UMIN(vallen, 100));
}
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->workers = atoi(tmpstr);
free(tmpstr);
}
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->requests = strtoul(tmpstr, NULL, 0);
free(tmpstr);
}
}
#endif
+68
View File
@@ -0,0 +1,68 @@
require 'stringio'
require 'uwsgidsl'
signal 17,'mule5' do |signum|
end
puts UWSGI::VERSION
puts UWSGI::NUMPROC
puts UWSGI::HOSTNAME
puts UWSGI::OPT.inspect
timer 2 do |signum|
puts "ciao sono un dsl ruby: #{signum} #{UWSGI::OPT.inspect}"
end
timer 1,'mule1' do |signum|
puts "1 second elapsed (signum #{signum})"
end
filemon '/tmp' do |signum|
puts "/tmp has been modified"
end
cron 5,-1,-1,-1,-1 do |signum|
puts "cron ready #{signum}"
end
cron 58,-1,-1,-1,-1 do |signum|
puts "cron ready #{signum}"
end
postfork do
puts "fork() called"
end
rpc 'pippo' do
"i am an rpc function"
end
rpc 'pluto' do |x,y|
"i am another rpc function #{x} #{y}"
end
begin
foo_func
rescue
end
puts UWSGI.cache_exists('nilkey')
puts UWSGI.cache_exists?('nilkey')
UWSGI.cache_set!('foobar_key?a=1', UWSGI::OPT.inspect)
begin
puts UWSGI.cache_get(nil)
rescue
end
puts UWSGI.cache_get('foobar_key?a=1')
run lambda { |env|
puts env.inspect
UWSGI.setprocname("i am the uWSGI rack plugin")
UWSGI.signal(17)
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World! #{UWSGI.mem.inspect}\n")]
}
+99
View File
@@ -0,0 +1,99 @@
#!/bin/bash
# uwsgi - Use uwsgi to run python and wsgi web apps.
#
# chkconfig: - 85 15
# description: Use uwsgi to run python and wsgi web apps.
# processname: uwsgi
# author: Roman Vasilyev
# Source function library.
. /etc/rc.d/init.d/functions
PATH=/opt/uwsgi:/sbin:/bin:/usr/sbin:/usr/bin
prog=/usr/sbin/uwsgi
OWNER=nginx
NAME=uwsgi
DESC=uwsgi
#DAEMON_OPTS="-s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 4 -d /var/log/uwsgi.log --pidfile /var/run/$NAME.pid --pythonpath $PYTHONPATH --module $MODULE"
DAEMON_OPTS="-s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 16 -b 32768 -d /var/log/$NAME.log --pidfile /var/run/$NAME.pid --uid $OWNER"
[ -f /etc/sysconfig/uwsgi ] && . /etc/sysconfig/uwsgi
lockfile=/var/lock/subsys/uwsgi
start () {
echo -n "Starting $DESC: "
daemon $prog $DAEMON_OPTS
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop () {
echo -n "Stopping $DESC: "
killproc $prog
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
reload () {
echo "Reloading $NAME"
killproc $prog -HUP
RETVAL=$?
echo
}
force-reload () {
echo "Reloading $NAME"
killproc $prog -TERM
RETVAL=$?
echo
}
restart () {
stop
start
}
rh_status () {
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|force-reload)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
status)
rh_status
;;
*)
echo "Usage: $0 {start|stop|restart|reload|force-reload|status}" >&2
exit 2
;;
esac
exit 0
+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),
+166 -21
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,12 +174,12 @@ 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;
@@ -183,6 +188,13 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
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);
}
+29 -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;
}
@@ -565,6 +567,16 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifdef OBSOLETE_LINUX_KERNEL
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
return -1;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#else
#include <sys/inotify.h>
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
@@ -657,6 +669,8 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#endif
#endif
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
@@ -687,13 +701,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 +789,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';
+5 -5
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;
@@ -90,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++;
@@ -103,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;
@@ -124,10 +124,10 @@ void gateway_respawn(int id) {
ug->pid = gw_pid;
ug->respawns++;
if (ug->respawns == 1) {
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
else {
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
uwsgi_log( "respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
}
+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) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6) ) {
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
+5 -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) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6)) {
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
@@ -77,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);
@@ -92,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);
+15
View File
@@ -1,5 +1,20 @@
#include "../uwsgi.h"
#ifdef OBSOLETE_LINUX_KERNEL
#ifndef __u16
#define __u16 u_int16_t
#endif
#ifndef __u32
#define __u32 u_int32_t
#endif
#ifndef __s32
#define __s32 int32_t
#endif
#ifndef __u8
#define __u8 u_int8_t
#endif
#endif
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
+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
*/
+22
View File
@@ -4,7 +4,12 @@
#ifdef UWSGI_LOCK_USE_MUTEX
#define UWSGI_LOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
#ifdef OBSOLETE_LINUX_KERNEL
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
#else
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
#endif
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
void uwsgi_lock_init(void *lock) {
@@ -27,15 +32,27 @@ void uwsgi_lock_init(void *lock) {
}
void uwsgi_rlock(void *lock) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock(lock);
#else
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
#endif
}
void uwsgi_wlock(void *lock) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock(lock);
#else
pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
#endif
}
void uwsgi_rwunlock(void *lock) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_unlock(lock);
#else
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
#endif
}
void uwsgi_lock(void *lock) {
@@ -46,10 +63,14 @@ 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) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock_init(lock);
#else
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
uwsgi_log("unable to allocate rwlock structure\n");
exit(1);
@@ -63,6 +84,7 @@ void uwsgi_rwlock_init(void *lock) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
#endif
}
+24 -17
View File
@@ -44,6 +44,7 @@ void log_request(struct wsgi_request *wsgi_req) {
#ifdef UWSGI_SENDFILE
char *msg1 = " via sendfile() ";
#endif
char *msg3 = " via route() ";
struct uwsgi_app *wi;
@@ -62,6 +63,11 @@ void log_request(struct wsgi_request *wsgi_req) {
}
#endif
// mark route() requests
if (wsgi_req->status == -1) {
via = msg3;
}
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
@@ -129,22 +135,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 +158,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 +170,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 +190,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 +199,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 +213,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
}
+415 -149
View File
@@ -13,6 +13,31 @@ void uwsgi_restore_auto_snapshot(int signum) {
}
void suspend_resume_them_all(int signum) {
int i;
int suspend = 0;
if (uwsgi.workers[0].suspended == 1) {
uwsgi_log_verbose("*** (SIGTSTP received) resuming workers ***\n");
uwsgi.workers[0].suspended = 0;
}
else {
uwsgi_log_verbose("*** PAUSE (press start to resume, if you do not have a joypad send SIGTSTP) ***\n");
suspend = 1;
uwsgi.workers[0].suspended = 1;
}
for(i=1;i<=uwsgi.numproc;i++) {
uwsgi.workers[i].suspended = suspend;
if (uwsgi.workers[i].pid > 0) {
if (kill(uwsgi.workers[i].pid, SIGTSTP)) {
uwsgi_error("kill()");
}
}
}
}
void expire_rb_timeouts(struct rb_root *root) {
time_t current = time(NULL);
@@ -42,56 +67,7 @@ void expire_rb_timeouts(struct rb_root *root) {
}
}
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, char *modifier1, size_t modifier1_len) {
char *ssb;
char subscrbuf[4096];
uint16_t ustrlen;
ssb = subscrbuf;
ustrlen = 3;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "key", ustrlen);
ssb+=ustrlen;
ustrlen = keysize;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, key, ustrlen);
ssb+=ustrlen;
ustrlen = 7;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "address", ustrlen);
ssb+=ustrlen;
ustrlen = strlen(uwsgi.sockets->name);
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, uwsgi.sockets->name, ustrlen);
ssb+=ustrlen;
if (modifier1) {
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "modifier1", ustrlen);
ssb+=ustrlen;
ustrlen = modifier1_len;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, modifier1, ustrlen);
ssb+=ustrlen;
}
send_udp_message(224, udp_address, subscrbuf, ssb-subscrbuf);
}
void uwsgi_subscribe(char *subscription) {
void uwsgi_subscribe(char *subscription, uint8_t cmd) {
int subfile_size;
int i;
@@ -124,7 +100,7 @@ void uwsgi_subscribe(char *subscription) {
modifier1_len = strlen(modifier1);
keysize = strlen(key);
}
uwsgi_send_subscription(udp_address, key, keysize, modifier1, modifier1_len);
uwsgi_send_subscription(udp_address, key, keysize, modifier1, modifier1_len, cmd);
modifier1 = NULL;
modifier1_len = 0;
}
@@ -142,7 +118,7 @@ void uwsgi_subscribe(char *subscription) {
modifier1_len = strlen(modifier1);
keysize = strlen(key);
}
uwsgi_send_subscription(udp_address, key, keysize, modifier1, modifier1_len);
uwsgi_send_subscription(udp_address, key, keysize, modifier1, modifier1_len, cmd);
modifier1 = NULL;
modifier1_len = 0;
lines[i] = '\n';
@@ -166,7 +142,7 @@ void uwsgi_subscribe(char *subscription) {
modifier1_len = strlen(modifier1);
}
uwsgi_send_subscription(udp_address, subscription_key+1, strlen(subscription_key+1), modifier1, modifier1_len);
uwsgi_send_subscription(udp_address, subscription_key+1, strlen(subscription_key+1), modifier1, modifier1_len, cmd);
if (modifier1)
modifier1[-1] = ',';
}
@@ -208,37 +184,8 @@ void get_linux_tcp_info(int fd) {
}
#endif
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
}
if (!uwsgi_strncmp("address", 7, key, keylen)) {
strncpy(ucn->name, val, UMIN(vallen, 100));
}
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->workers = atoi(tmpstr);
free(tmpstr);
}
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->requests = strtoul(tmpstr, NULL, 0);
free(tmpstr);
}
}
void master_loop(char **argv, char **environ) {
int master_loop(char **argv, char **environ) {
uint64_t tmp_counter;
@@ -284,17 +231,31 @@ 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(SIGTSTP, suspend_resume_them_all);
uwsgi_unix_signal(SIGHUP, grace_them_all);
if (uwsgi.die_on_term) {
uwsgi_unix_signal(SIGTERM, kill_them_all);
@@ -318,6 +279,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 +307,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 +338,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 +440,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++) {
@@ -462,10 +454,22 @@ void master_loop(char **argv, char **environ) {
}
}
// spawn daemons
struct uwsgi_daemon *ud = uwsgi.daemons;
while(ud) {
if (!ud->registered) {
spawn_daemon(ud);
ud->registered = 1;
}
ud = ud->next;
}
// 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, 0);
subscriptions = subscriptions->next;
}
// sync the cache store if needed
@@ -481,21 +485,34 @@ void master_loop(char **argv, char **environ) {
}
}
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) {
@@ -504,6 +521,7 @@ void master_loop(char **argv, char **environ) {
uwsgi.lazy_respawned = 0;
}
}
if (uwsgi.master_mercy) {
if (uwsgi.master_mercy < time(NULL)) {
for(i=1;i<=uwsgi.numproc;i++) {
@@ -519,7 +537,7 @@ void master_loop(char **argv, char **environ) {
else if (uwsgi.to_heaven) { ready_to_reload++;}
else if (uwsgi.to_outworld) {
uwsgi.lazy_respawned++;
if (uwsgi_respawn_worker(i)) return;
if (uwsgi_respawn_worker(i)) return 0;
}
}
else {
@@ -532,7 +550,7 @@ void master_loop(char **argv, char **environ) {
}
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;
@@ -560,9 +578,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+uwsgi.daemons_cnt+uwsgi.mules_cnt);i++) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
@@ -570,8 +653,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+uwsgi.daemons_cnt+uwsgi.mules_cnt);i++) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
@@ -581,15 +664,16 @@ void master_loop(char **argv, char **environ) {
}
uwsgi_log( "binary reloading uWSGI...\n");
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
if (chdir(uwsgi.cwd)) {
uwsgi_error("chdir()");
exit(1);
}
/* check fd table (a module can obviosly open some fd on initialization...) */
uwsgi_log( "closing all non-uwsgi socket fds > 2 (_SC_OPEN_MAX = %ld)...\n", sysconf(_SC_OPEN_MAX));
for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) {
int found = 0;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (i == uwsgi_sock->fd) {
@@ -607,6 +691,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);
@@ -616,6 +707,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);
@@ -623,11 +717,12 @@ void master_loop(char **argv, char **environ) {
uwsgi_error("execvp()");
// never here
exit(1);
#endif
}
if (!uwsgi.cheap) {
if (uwsgi.numproc > 0 || uwsgi.gateways_cnt > 0 || ushared->daemons_cnt > 0) {
if (uwsgi.numproc > 0 || uwsgi.gateways_cnt > 0 || uwsgi.daemons_cnt > 0) {
master_has_children = 1;
}
#ifdef UWSGI_SPOOLER
@@ -643,6 +738,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");
@@ -668,16 +773,6 @@ void master_loop(char **argv, char **environ) {
}
}
// add unregistered daemons
// locking is not needed as daemons can only increase (for now)
for(i=0;i<ushared->daemons_cnt;i++) {
if (!ushared->daemons[i].registered) {
uwsgi_log("spawning daemon %s\n", ushared->daemons[i].command);
spawn_daemon(&ushared->daemons[i]);
ushared->daemons[i].registered = 1;
}
}
// add unregistered timers
// locking is not needed as timers can only increase
@@ -730,6 +825,22 @@ void master_loop(char **argv, char **environ) {
uwsgi_manage_command_cron(time(NULL));
}
// check for probes
if (ushared->probes_cnt > 0) {
uwsgi_lock(uwsgi.probe_table_lock);
for(i=0;i<ushared->probes_cnt;i++) {
if (interesting_fd == -1) {
// increment cycles
ushared->probes[i].cycles++;
}
if (ushared->probes[i].func(interesting_fd, &ushared->probes[i])) {
uwsgi_route_signal(ushared->probes[i].sig);
}
}
uwsgi_unlock(uwsgi.probe_table_lock);
}
if (rlen > 0) {
if (uwsgi.log_master) {
@@ -760,6 +871,12 @@ void master_loop(char **argv, char **environ) {
}
}
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;
@@ -846,7 +963,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;
}
@@ -985,6 +1102,7 @@ void master_loop(char **argv, char **environ) {
next_iteration = 0;
uwsgi_lock(uwsgi.timer_table_lock);
for(i=0;i<ushared->timers_cnt;i++) {
if (ushared->timers[i].registered) {
if (interesting_fd == ushared->timers[i].fd) {
@@ -995,6 +1113,7 @@ void master_loop(char **argv, char **environ) {
}
}
}
uwsgi_unlock(uwsgi.timer_table_lock);
if (next_iteration) continue;
@@ -1016,23 +1135,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);
}
*/
}
@@ -1164,10 +1335,51 @@ 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 __linux__
#ifdef MADV_MERGEABLE
if (uwsgi.linux_ksm > 0 && (uwsgi.master_cycles % uwsgi.linux_ksm) == 0) {
uwsgi_linux_ksm_map();
}
#endif
#endif
#ifdef UWSGI_UDP
// check for cluster nodes
@@ -1178,10 +1390,12 @@ void master_loop(char **argv, char **environ) {
uwsgi_cluster_add_me();
}
// 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]);
// resubscribe every 10 cycles by default
if (uwsgi.subscriptions && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) {
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while(subscriptions) {
uwsgi_subscribe(subscriptions->value, 0);
subscriptions = subscriptions->next;
}
}
@@ -1200,19 +1414,20 @@ void master_loop(char **argv, char **environ) {
}
// 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;
}
@@ -1230,12 +1445,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;
@@ -1252,12 +1482,14 @@ void master_loop(char **argv, char **environ) {
/* reload the daemons */
// TODO reload_gateway(diedpid);
pid_found = 0;
for(i=0;i<uwsgi.shared->daemons_cnt;i++) {
if (uwsgi.shared->daemons[i].pid == diedpid) {
spawn_daemon(&uwsgi.shared->daemons[i]);
struct uwsgi_daemon *ud = uwsgi.daemons;
while(ud) {
if (ud->pid == diedpid) {
spawn_daemon(ud);
pid_found = 1;
break;
}
ud = ud->next;
}
if (pid_found) continue;
@@ -1276,6 +1508,39 @@ 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;
}
}
struct uwsgi_daemon *ud = uwsgi.daemons;
while(ud) {
if (ud->pid == diedpid) {
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
goto next;
}
ud = ud->next;
}
if (WIFEXITED(waitpid_status)) {
uwsgi_log("subprocess %d exited with code %d\n", (int) diedpid, WEXITSTATUS(waitpid_status));
}
@@ -1285,10 +1550,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;
@@ -1315,6 +1582,12 @@ void master_loop(char **argv, char **environ) {
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++;
@@ -1330,15 +1603,8 @@ void master_loop(char **argv, char **environ) {
}
gettimeofday(&last_respawn, NULL);
uwsgi.respawn_delta = last_respawn.tv_sec;
// close the communication pipe
/*
close(uwsgi.workers[uwsgi.mywid].pipe[0]);
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.workers[uwsgi.mywid].pipe)) {
uwsgi_error("socketpair()\n");
continue;
}
*/
if (uwsgi_respawn_worker(uwsgi.mywid)) return;
if (uwsgi_respawn_worker(uwsgi.mywid)) return 0;
}
}
+226 -79
View File
@@ -2,6 +2,8 @@
extern struct uwsgi_server uwsgi;
void worker_wakeup() {}
void master_check_cluster_nodes() {
int i;
@@ -31,71 +33,111 @@ 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);
signal(SIGTSTP, worker_wakeup);
uwsgi.mywid = wid;
uwsgi.mypid = getpid();
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].requests = 0;
uwsgi.workers[uwsgi.mywid].failed_requests = 0;
// do not reset worker counters on reload !!!
//uwsgi.workers[uwsgi.mywid].requests = 0;
// ...but maintain a delta counter (yes this is racy in multithread)
uwsgi.workers[uwsgi.mywid].delta_requests = 0;
//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
uwsgi.workers[uwsgi.mywid].cheaped = 0;
uwsgi.workers[uwsgi.mywid].busy = 0;
uwsgi.workers[uwsgi.mywid].suspended = 0;
uwsgi.workers[uwsgi.mywid].sig = 0;
// 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);
}
@@ -139,32 +181,26 @@ void uwsgi_manage_signal_cron(time_t now) {
uc_hour = uwsgi_cron_delta->tm_hour;
if (ucron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (ucron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
int run_task = 0;
// mday and wday are ORed
if (ucron->day == -1 && ucron->week == -1) {
if (ucron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
}
else if (ucron->day == -1) {
ucron->day = uwsgi_cron_delta->tm_mday;
}
else if (ucron->week == -1) {
ucron->week = uwsgi_cron_delta->tm_wday;
if (ucron->day != -1 && ucron->week != -1) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (ucron->day == uwsgi_cron_delta->tm_mday) {
ucron->week = uwsgi_cron_delta->tm_wday;
}
else if (ucron->week == uwsgi_cron_delta->tm_wday) {
ucron->day = uwsgi_cron_delta->tm_mday;
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
if (run_task == 1) {
// date match, signal it ?
if (uwsgi.current_time - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
@@ -212,31 +248,26 @@ void uwsgi_manage_command_cron(time_t now) {
uc_hour = uwsgi_cron_delta->tm_hour;
if (current_cron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (current_cron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (current_cron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
// mday and wday are ORed
if (current_cron->day == -1 && current_cron->week == -1) {
if (current_cron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (current_cron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
}
else if (current_cron->day == -1) {
current_cron->day = uwsgi_cron_delta->tm_mday;
}
else if (current_cron->week == -1) {
current_cron->week = uwsgi_cron_delta->tm_wday;
}
else {
if (current_cron->day == uwsgi_cron_delta->tm_mday) {
current_cron->week = uwsgi_cron_delta->tm_wday;
}
else if (current_cron->week == uwsgi_cron_delta->tm_wday) {
current_cron->day = uwsgi_cron_delta->tm_mday;
}
}
int run_task = 0;
// mday and wday are ORed
if (current_cron->day != -1 && current_cron->week != -1) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
if (run_task == 1) {
// date match, run command ?
if (uwsgi.current_time - current_cron->last_job > 60) {
@@ -257,3 +288,119 @@ 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("\"delta_requests\": %llu, ", uwsgi.workers[i+1].delta_requests);
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i+1].exceptions);
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i+1].signals);
if (uwsgi.workers[i + 1].cheaped) {
fprintf(output,"\"status\": \"cheap\", ");
}
else if (uwsgi.workers[i + 1].suspended) {
fprintf(output,"\"status\": \"pause\", ");
}
else {
if (uwsgi.workers[i + 1].sig) {
fprintf(output,"\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
}
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);
}
+358
View File
@@ -0,0 +1,358 @@
/*
uWSGI mules are very simple workers only managing signals or running custom code in background.
By default they born in signal-only mode, but if you patch them (passing the script/code to run) they will became fully customized daemons.
*/
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_mule_handler(void);
void mule_send_msg(int fd, char *message, size_t len) {
socklen_t so_bufsize_len = sizeof(int);
int so_bufsize = 0;
if (write(fd, message, len) != (ssize_t) len) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** MULE MSG QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
}
else {
uwsgi_error("mule_send_msg()");
}
}
}
void uwsgi_mule(int id) {
int i;
pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
if (pid == 0) {
uwsgi.muleid = id;
// avoid race conditions
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = getpid();
uwsgi_fixup_fds(0, id);
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;
}
ssize_t uwsgi_mule_get_msg(int manage_signals, int manage_farms, char *message, size_t buffer_size, int timeout) {
ssize_t len = 0;
struct pollfd *mulepoll;
int count = 4;
int farms_count = 0;
uint8_t uwsgi_signal;
int i;
if (uwsgi.muleid == 0) return -1;
if (manage_signals) count = 2;
if (!manage_farms) goto next;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) farms_count++;
}
next:
if (timeout > -1) timeout = timeout*1000;
mulepoll = uwsgi_malloc(sizeof(struct pollfd) * (count+farms_count));
mulepoll[0].fd = uwsgi.mules[uwsgi.muleid-1].queue_pipe[1];
mulepoll[0].events = POLLIN;
mulepoll[1].fd = uwsgi.shared->mule_queue_pipe[1];
mulepoll[1].events = POLLIN;
if (count > 2) {
mulepoll[2].fd = uwsgi.signal_socket;
mulepoll[2].events = POLLIN;
mulepoll[3].fd = uwsgi.my_signal_socket;
mulepoll[3].events = POLLIN;
}
if (farms_count > 0) {
int tmp_cnt = 0;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
mulepoll[count+tmp_cnt].fd = uwsgi.farms[i].queue_pipe[1];
mulepoll[count+tmp_cnt].events = POLLIN;
tmp_cnt++;
}
}
}
int ret = poll(mulepoll, count+farms_count, timeout);
if (ret <= 0) {
uwsgi_error("poll");
}
else {
if (mulepoll[0].revents & POLLIN) {
len = read(uwsgi.mules[uwsgi.muleid-1].queue_pipe[1], message, buffer_size);
}
else if (mulepoll[1].revents & POLLIN) {
len = read(uwsgi.shared->mule_queue_pipe[1], message, buffer_size);
}
else {
if (count > 2) {
int interesting_fd = -1;
if (mulepoll[2].revents & POLLIN) {
interesting_fd = mulepoll[2].fd;
}
else if (mulepoll[3].revents & POLLIN) {
interesting_fd = mulepoll[3].fd;
}
if (interesting_fd > -1) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
}
// set the error condition
len = -1;
goto clear;
}
}
// read messages in the farm
for(i=0;i<farms_count;i++) {
if (mulepoll[count+i].revents & POLLIN) {
len = read(mulepoll[count+i].fd, message, buffer_size);
break;
}
}
}
}
if (len < 0) {
uwsgi_error("read()");
goto clear;
}
clear:
free(mulepoll);
return len;
}
+27
View File
@@ -0,0 +1,27 @@
from uwsgidecorators import *
@timer(3, target='mule1')
def hello_timer(signum):
print "3 seconds elapsed"
@mulefunc
def conto_fino_a_dieci(uno, due, tre):
print "MULE ID %d: conto_fino_a_dieci" % uwsgi.mule_id(),uno,due,tre
@mulefunc(2)
def conto_fino_a_venti(uno, due, tre):
print "MULE ID %d: conto_fino_a_venti" % uwsgi.mule_id(),uno,due,tre
@mulefunc('topogigio')
def conto_fino_a_trenta(uno, due, tre):
print "MULE ID %d: conto_fino_a_trenta" % uwsgi.mule_id(),uno,due,tre
def application(e, sr):
conto_fino_a_dieci(1,2,3)
conto_fino_a_venti(4,5,6)
conto_fino_a_trenta(7,8,9)
sr('200 OK', [('Content-Type','text/html')])
return "MULE !!!"
+123
View File
@@ -0,0 +1,123 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
#define CARBON_OPT_BASE 178000
#define CARBON_OPT_CARBON CARBON_OPT_BASE+1
#define CARBON_OPT_CARBON_ID CARBON_OPT_BASE+2
#define CARBON_OPT_CARBON_FREQ CARBON_OPT_BASE+3
#define CARBON_OPT_CARBON_TIMEOUT CARBON_OPT_BASE+4
struct uwsgi_carbon {
struct uwsgi_string_list *servers;
int freq;
int timeout;
char *id;
} u_carbon;
struct option carbon_options[] = {
{"carbon", required_argument, 0, CARBON_OPT_CARBON},
{"carbon-timeout", required_argument, 0, CARBON_OPT_CARBON_TIMEOUT},
{"carbon-freq", required_argument, 0, CARBON_OPT_CARBON_FREQ},
{"carbon-id", required_argument, 0, CARBON_OPT_CARBON_ID},
{0, 0, 0, 0},
};
int carbon_init() {
return 0;
}
int carbon_opt(int i, char *optarg) {
switch(i) {
case CARBON_OPT_CARBON:
uwsgi.master_process = 1;
uwsgi_string_new_list(&u_carbon.servers, optarg);
return 1;
case CARBON_OPT_CARBON_ID:
u_carbon.id = optarg;
return 1;
case CARBON_OPT_CARBON_FREQ:
u_carbon.freq = atoi(optarg);
return 1;
case CARBON_OPT_CARBON_TIMEOUT:
u_carbon.timeout = atoi(optarg);
return 1;
}
return 0;
}
void carbon_post_init() {
int i;
struct uwsgi_string_list *usl = u_carbon.servers;
if (!uwsgi.sockets) return;
if (!u_carbon.servers) return;
while(usl) {
uwsgi_log("added carbon server %s\n", usl->value);
usl = usl->next;
}
if (u_carbon.freq < 1) u_carbon.freq = 60;
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
if (!u_carbon.id) {
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
for(i=0;i<(int)strlen(u_carbon.id);i++) {
if (u_carbon.id[i] == '.') u_carbon.id[i] = '_';
}
}
}
void carbon_master_cycle() {
static time_t last_update = 0;
char ptr[4096];
int rlen, i;
int fd;
struct uwsgi_string_list *usl = u_carbon.servers;
if (!u_carbon.servers) return ;
if (last_update == 0) last_update = time(NULL);
// update
if (uwsgi.current_time - last_update >= u_carbon.freq) {
while(usl) {
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
if (fd < 0) goto nxt;
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.workers[0].requests, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
for(i=1;i<=uwsgi.numproc;i++) {
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].requests, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
}
clear:
close(fd);
nxt:
usl = usl->next;
}
}
}
struct uwsgi_plugin carbon_plugin = {
.options = carbon_options,
.manage_opt = carbon_opt,
.master_cycle = carbon_master_cycle,
.post_init = carbon_post_init,
.init = carbon_init,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='carbon'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['carbon']
+50 -6
View File
@@ -6,7 +6,7 @@ extern struct uwsgi_server uwsgi;
char *cgi_docroot;
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 100)
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 1000)
#define LONG_ARGS_CGI LONG_ARGS_CGI_BASE + 1
struct option uwsgi_cgi_options[] = {
@@ -32,6 +32,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
int waitpid_status;
char *argv[2];
char full_path[PATH_MAX];
int cgi_pipe[2];
ssize_t len;
/* Standard CGI request */
if (!wsgi_req->uh.pktsize) {
@@ -47,6 +49,26 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
// check for file availability (and 'runnability')
char *path_info = uwsgi_concat4n(cgi_docroot, strlen(cgi_docroot), "/", 1,wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
uwsgi_log("requested %s %s\n", path_info, realpath(path_info, full_path));
if (access(full_path, R_OK)) {
wsgi_req->status = 404;
wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 404 Not Found\r\n\r\n", 26);
return UWSGI_OK;
}
if (access(full_path, X_OK)) {
wsgi_req->status = 500;
wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 500 Internal Server Error\r\n\r\n", 26);
return UWSGI_OK;
}
if (pipe(cgi_pipe)) {
uwsgi_error("pipe()");
return UWSGI_OK;
}
cgi_pid = fork();
if (cgi_pid < 0) {
@@ -59,6 +81,29 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
close(wsgi_req->poll.fd);
wsgi_req->fd_closed = 1;
// wait for data
char startbuf[8];
char *ptr = startbuf;
int remains = 8;
while(remains > 0) {
uwsgi_log("waiting for fd\n");
int ret = uwsgi_waitfd(cgi_pipe[0], 10);
uwsgi_log("data available\n");
if (ret > 0) {
len = read(cgi_pipe[0], ptr, remains);
if (len > 0) {
ptr+=len;
remains -= len;
}
}
}
uwsgi_log("STARTBUF %.*s\n", 8, startbuf);
if (!memcmp(startbuf, "Status: ", 8)) {
wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 "
}
// now wait for fd
if (waitpid(cgi_pid, &waitpid_status ,0) > 0) {
uwsgi_log("CGI FINISHED\n");
@@ -69,18 +114,19 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
// close all the fd except wsgi_req->poll.fd and 2;
for(i=0;i< (int)uwsgi.max_fd;i++) {
if (i != wsgi_req->poll.fd && i != 2) {
if (i != wsgi_req->poll.fd && i != 2 && i != cgi_pipe[0] && i != cgi_pipe[1]) {
close(i);
}
}
// now map wsgi_req->poll.fd to 0 && 1
// now map wsgi_req->poll.fd to 0 & cgi_pipe[1] to 1
if (wsgi_req->poll.fd != 0) {
dup2(wsgi_req->poll.fd, 0);
close(wsgi_req->poll.fd);
}
dup2(0,1);
uwsgi_log("mapping cgi_pipe %d to 1\n", cgi_pipe[1]);
dup2(cgi_pipe[1],1);
// fill cgi env
@@ -92,8 +138,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
i++;
}
char *path_info = uwsgi_concat4n(cgi_docroot, strlen(cgi_docroot), "/", 1,wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
uwsgi_log("requested %s %s\n", path_info, realpath(path_info, full_path));
argv[0] = full_path;
argv[1] = NULL;
+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;
};
+110 -29
View File
@@ -20,6 +20,7 @@
#define LONG_ARGS_FASTROUTER_TIMEOUT 150006
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT 150007
#define LONG_ARGS_FASTROUTER_USE_CODE_STRING 150008
#define LONG_ARGS_FASTROUTER_TOLERANCE 150009
#define FASTROUTER_STATUS_FREE 0
#define FASTROUTER_STATUS_CONNECTING 1
@@ -28,6 +29,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 {
@@ -43,6 +46,8 @@ struct uwsgi_fastrouter {
int use_cache;
int nevents;
int queue;
int subscription_slot;
char *pattern;
@@ -52,7 +57,8 @@ 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;
@@ -61,8 +67,26 @@ struct uwsgi_fastrouter {
char *code_string_function;
struct rb_root *timeouts;
struct uwsgi_rb_timer *subscriptions_check;
int cheap;
int i_am_cheap;
int tolerance;
} ufr;
static void fastrouter_go_cheap(void) {
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;
}
static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name) {
@@ -97,8 +121,10 @@ struct option fastrouter_options[] = {
{"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},
};
@@ -130,7 +156,6 @@ struct fastrouter_session {
int status;
struct uwsgi_header uh;
uint8_t h_pos;
char buffer[0xffff];
uint16_t pos;
char *hostname;
@@ -141,13 +166,15 @@ 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) {
@@ -155,9 +182,28 @@ static void close_session(struct fastrouter_session **fr_table, struct fastroute
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->un && fr_session->un->len > 0) {
// decrease reference count
#ifdef UWSGI_DEBUG
uwsgi_log("[1] node %.*s refcnt: %llu\n", fr_session->un->len, fr_session->un->name, fr_session->un->reference);
#endif
fr_session->un->reference--;
#ifdef UWSGI_DEBUG
uwsgi_log("[2] node %.*s refcnt: %llu\n", fr_session->un->len, fr_session->un->name, fr_session->un->reference);
#endif
if (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING) {
if (fr_session->un->death_mark == 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);
fr_session->un->death_mark = 1;
// check if i can remove the node
if (fr_session->un->reference == 0) {
uwsgi_remove_subscribe_node(&ufr.subscriptions, fr_session->un);
}
if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
fastrouter_go_cheap();
}
}
}
close(fr_session->instance_fd);
fr_table[fr_session->instance_fd] = NULL;
@@ -182,7 +228,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;
}
@@ -222,7 +267,6 @@ struct fastrouter_session *alloc_fr_session() {
void fastrouter_loop() {
int fr_queue;
int nevents;
int interesting_fd;
int new_connection;
@@ -269,7 +313,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;
@@ -295,27 +339,35 @@ void fastrouter_loop() {
uwsgi_log("uwsgi fastrouter/proxy bound on %s\n", ufr_sock->name);
event_queue_add_fd_read(fr_queue, ufr_sock->fd);
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 (;;) {
@@ -331,7 +383,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);
@@ -361,10 +413,12 @@ void fastrouter_loop() {
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;
}
@@ -379,12 +433,39 @@ 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);
// subscribe request ?
if (bbuf[3] == 0) {
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");
}
}
//unsubscribe
else {
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(&ufr.subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, ufr.subscription_regexp);
if (node && node->len) {
if (node->death_mark == 0)
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
node->death_mark = 1;
// check if i can remove the node
if (node->reference == 0) {
uwsgi_remove_subscribe_node(&ufr.subscriptions, node);
}
if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
fastrouter_go_cheap();
}
}
}
}
}
else {
@@ -439,7 +520,7 @@ 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);
@@ -457,12 +538,15 @@ 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;
fr_session->modifier1 = fr_session->un->modifier1;
}
else if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
fastrouter_go_cheap();
}
}
else if (ufr.base) {
tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
@@ -497,10 +581,7 @@ 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;
}
fr_session->instance_failed = 1;
close_session(fr_table, fr_session);
break;
}
@@ -508,7 +589,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;
@@ -574,7 +655,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;
}
@@ -630,7 +711,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;
@@ -653,13 +734,13 @@ int fastrouter_init() {
if (!ufr.nevents) ufr.nevents = 64;
if (ufr.code_string_code && ufr.code_string_function) {
if (register_fat_gateway("fastrouter", fastrouter_loop) == NULL) {
if (register_fat_gateway("uWSGI fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
}
}
else {
if (register_gateway("fastrouter", fastrouter_loop) == NULL) {
if (register_gateway("uWSGI fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
}
+189 -73
View File
@@ -10,34 +10,82 @@ struct option gevent_options[] = {
#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* gevent_wait_io_and_switch(int fd, PyObject *greenlet_switch) {
PyObject *py_uwsgi_gevent_signal_handler(PyObject * self, PyObject * args) {
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", fd, 1);
if (!watcher) {
PyErr_Print();
return NULL;
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);
}
}
PyObject *ret = PyObject_CallMethod(watcher, "start", "O", greenlet_switch);
Py_DECREF(ret);
return watcher;
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_gevent_callback(PyObject * self, PyObject * args) {
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();
@@ -48,21 +96,30 @@ PyObject *py_uwsgi_gevent_callback(PyObject * self, PyObject * args) {
}
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);
@@ -71,8 +128,27 @@ clear:
return Py_None;
}
PyObject *py_uwsgi_gevent_greenlet(PyObject * self, PyObject * args) {
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 ;
@@ -80,24 +156,47 @@ PyObject *py_uwsgi_gevent_greenlet(PyObject * self, PyObject * args) {
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;
PyObject *watcher = gevent_wait_io_and_switch(wsgi_req->poll.fd, greenlet_switch);
if (!watcher) {
goto clear;
}
uwsgi.wsgi_req = wsgi_req;
status = wsgi_req->socket->proto(wsgi_req);
PyObject *ret = PyObject_CallMethod(watcher, "stop", NULL);
// we can safely decref here as watcher and timer has got a +1 for start() method
Py_DECREF(ret);
Py_DECREF(watcher);
if (status < 0) {
goto clear;
if (ret == timer) {
uwsgi_log( "timeout. skip request.\n");
goto clear_and_stop;
}
else if (status == 0) {
break;
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(;;) {
@@ -106,10 +205,21 @@ PyObject *py_uwsgi_gevent_greenlet(PyObject * self, PyObject * args) {
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);
@@ -124,8 +234,11 @@ clear:
}
PyMethodDef uwsgi_gevent_callback_method[] = { {"uwsgi_gevent_callback", py_uwsgi_gevent_callback, METH_VARARGS, ""} };
PyMethodDef uwsgi_gevent_greenlet_method[] = { {"uwsgi_gevent_greenlet", py_uwsgi_gevent_greenlet, METH_VARARGS, ""} };
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() {
@@ -139,16 +252,10 @@ void gevent_loop() {
PyObject *gevent_dict = get_uwsgi_pydict("gevent");
if (!gevent_dict) {
PyErr_Print();
exit(1);
}
if (!gevent_dict) uwsgi_pyexit;
PyObject *gevent_version = PyDict_GetItemString(gevent_dict, "version_info");
if (!gevent_version) {
PyErr_Print();
exit(1);
}
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");
@@ -156,16 +263,10 @@ void gevent_loop() {
}
ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn");
if (!ugevent.spawn) {
PyErr_Print();
exit(1);
}
if (!ugevent.spawn) uwsgi_pyexit;
ugevent.greenlet_switch = PyDict_GetItemString(gevent_dict, "sleep");
if (!ugevent.greenlet_switch) {
PyErr_Print();
exit(1);
}
if (!ugevent.greenlet_switch) uwsgi_pyexit;
ugevent.greenlet_switch_args = PyTuple_New(0);
Py_INCREF(ugevent.greenlet_switch_args);
@@ -173,52 +274,67 @@ void gevent_loop() {
PyObject *gevent_get_hub = PyDict_GetItemString(gevent_dict, "get_hub");
PyObject *gevent_hub = python_call(gevent_get_hub, PyTuple_New(0), 0, NULL);
if (!gevent_hub) {
PyErr_Print();
exit(1);
}
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) {
PyErr_Print();
exit(1);
}
if (!ugevent.get_current) uwsgi_pyexit;
ugevent.get_current_args = PyTuple_New(0);
Py_INCREF(ugevent.get_current_args);
ugevent.hub_loop = PyObject_GetAttrString(gevent_hub, "loop");
if (!ugevent.hub_loop) {
PyErr_Print();
exit(1);
}
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) {
PyErr_Print();
exit(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);
PyObject *uwsgi_gevent_callback = PyCFunction_New(uwsgi_gevent_callback_method, NULL);
Py_INCREF(uwsgi_gevent_callback);
PyObject *uwsgi_gevent_greenlet = PyCFunction_New(uwsgi_gevent_greenlet_method, NULL);
Py_INCREF(uwsgi_gevent_greenlet);
// 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_gevent_greenlet);
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_CallMethod(watcher, "start", "O", uwsgi_gevent_callback);
PyObject *my_signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.my_signal_socket, 1);
if (!my_signal_watcher) uwsgi_pyexit;
if (PyObject_CallMethod(gevent_hub, "switch", NULL)) {
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();
exit(1);
}
uwsgi_log("the gevent Hub is no more :(\n");
+21 -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 {
@@ -474,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) {
@@ -550,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 {
@@ -630,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;
@@ -647,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);
@@ -660,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;
}
@@ -882,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);
}
+18 -19
View File
@@ -15,49 +15,48 @@ struct option nagios_options[] = {
int nagios() {
char *tcp_port;
struct wsgi_request nagios_req;
// connect and send
struct uwsgi_header uh;
char *buf = NULL;
if (!use_nagios) {
return 1;
}
if (!uwsgi.sockets) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port = strchr(uwsgi.sockets->name, ':');
if (tcp_port == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port[0] = 0;
int fd = connect_to_tcp(uwsgi.sockets->name, atoi(tcp_port + 1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
int fd = uwsgi_connect(uwsgi.sockets->name, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) {
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
exit(2);
}
nagios_req.uh.modifier1 = UWSGI_MODIFIER_PING;
nagios_req.uh.pktsize = 0;
nagios_req.uh.modifier2 = 0;
if (write(fd, &nagios_req.uh, 4) != 4) {
uh.modifier1 = UWSGI_MODIFIER_PING;
uh.pktsize = 0;
uh.modifier2 = 0;
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
fprintf(stdout, "UWSGI CRITICAL: could not send ping packet to workers\n");
exit(2);
}
nagios_req.poll.fd = fd;
nagios_req.poll.events = POLLIN;
if (!uwsgi_parse_packet(&nagios_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buf);
if (ret == -2) {
fprintf(stdout, "UWSGI CRITICAL: timed out waiting for response\n");
exit(2);
}
else if (ret == -1) {
fprintf(stdout, "UWSGI CRITICAL: error reading response\n");
exit(2);
}
else {
if (nagios_req.uh.pktsize > 0) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", nagios_req.uh.pktsize, nagios_req.buffer);
if (uh.pktsize > 0 && buf) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", uh.pktsize, buf);
exit(1);
}
else {
+12 -14
View File
@@ -15,8 +15,8 @@ struct option uwsgi_ping_options[] = {
static void ping() {
struct wsgi_request ping_req;
char *buf = uwsgi_malloc(uwsgi.buffer_size);
struct uwsgi_header uh;
char *buf = NULL;
// use a 3 secs timeout by default
if (!uping.ping_timeout) uping.ping_timeout = 3;
@@ -28,25 +28,22 @@ static void ping() {
exit(1);
}
memset(&ping_req, 0, sizeof(struct wsgi_request));
ping_req.uh.modifier1 = UWSGI_MODIFIER_PING;
ping_req.uh.pktsize = 0;
ping_req.uh.modifier2 = 0;
if (write(fd, &ping_req.uh, 4) != 4) {
uh.modifier1 = UWSGI_MODIFIER_PING;
uh.pktsize = 0;
uh.modifier2 = 0;
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
exit(2);
}
ping_req.poll.fd = fd;
ping_req.poll.events = POLLIN;
ping_req.buffer = buf;
if (!uwsgi_parse_packet(&ping_req, uping.ping_timeout)) {
int ret = uwsgi_read_response(fd, &uh, uping.ping_timeout, &buf);
if (ret < 0) {
exit(1);
}
else {
if (ping_req.uh.pktsize > 0) {
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, ping_req.uh.pktsize, buf);
if (uh.pktsize > 0) {
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, uh.pktsize, buf);
exit(2);
}
else {
@@ -98,6 +95,7 @@ int uwsgi_ping_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PING:
uwsgi.no_initial_output = 1;
uwsgi.no_server = 1;
uping.ping = optarg;
return 1;
+90
View File
@@ -0,0 +1,90 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
int connect_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
// is this a timeout event ?
if (interesting_fd == -1) {
// am i wating for something ?
if (up->fd != -1) {
if (up->cycles > (uint64_t) up->timeout) {
// reset the cycle
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
// avoid duplicated events
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
// ok register a new event
else {
if ((up->cycles % up->freq) == 0) {
up->fd = uwsgi_connect(up->args, -1, 1);
if (up->fd != -1) {
// status = CONNECTING
up->state = 1;
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
return 0;
}
// signal the bad event (if not already bad)
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
}
else if (up->fd != -1) {
// is this event for me ?
if (interesting_fd == up->fd) {
// uselsess here (we have only one state), only to show a good practice
// check the state
if (up->state == 1) {
if (uwsgi_is_bad_connection(up->fd)) {
// signal the bad connection (if needed)
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
if (!up->bad) {
up->bad = 1;
return 1;
}
return 0;
}
// this is a good connection
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
if (up->bad) {
up->bad = 0;
return 1;
}
}
}
}
// default action
return 0;
}
int probeconnect_init() {
uwsgi_probe_register(&uwsgi.probes, "connect", connect_prober_callback);
return 0;
}
struct uwsgi_plugin probeconnect_plugin = {
.init = probeconnect_init,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='probeconnect'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['connectprobe']
+132
View File
@@ -0,0 +1,132 @@
#include "../../uwsgi.h"
#include <libpq-fe.h>
extern struct uwsgi_server uwsgi;
int pg_prober_callback(int, struct uwsgi_signal_probe *);
int probepg_init(void);
int pg_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
// is this a timeout event ?
if (interesting_fd == -1) {
// am i wating for something ?
if (up->fd != -1) {
if (up->cycles > (uint64_t) up->timeout) {
// reset the cycle
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
// state = NOOP
up->state = 0;
// avoid duplicated events
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
// ok register a new event
else {
if ((up->cycles % up->freq) == 0) {
up->last_event = event_queue_write();
up->data = (void *) PQconnectStart(up->args);
if (up->data) {
// status = CONNECTING
up->state = PQstatus((PGconn *) up->data);
if (up->state == CONNECTION_BAD)
goto bad;
up->fd = PQsocket((PGconn *) up->data);
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
return 0;
}
bad:
// signal the bad event (if not already bad)
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
}
else if (up->fd != -1) {
// is this event for me ?
if (interesting_fd == up->fd) {
// check the state
up->state = PQstatus((PGconn *) up->data);
if (up->state == CONNECTION_BAD) {
// signal the bad connection (if needed)
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
up->state = 0;
if (!up->bad) {
up->bad = 1;
return 1;
}
return 0;
}
else if (up->state == CONNECTION_OK) {
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
// state = NOOP
up->state = 0;
if (up->bad) {
up->bad = 0;
return 1;
}
}
// still wait...
else {
PostgresPollingStatusType wait_type = PQconnectPoll((PGconn *) up->data);
// the connection is good
if (wait_type == PGRES_POLLING_ACTIVE || wait_type == PGRES_POLLING_FAILED || wait_type == PGRES_POLLING_OK) {
if (wait_type == PGRES_POLLING_ACTIVE)
wait_type = PQconnectPoll((PGconn *) up->data);
up->cycles = 0;
up->fd = -1;
// state = NOOP
up->state = 0;
PQfinish((PGconn *) up->data);
if (wait_type == PGRES_POLLING_FAILED) {
if (!up->bad) {
up->bad = 1;
return 1;
}
}
else {
if (up->bad) {
up->bad = 0;
return 1;
}
}
}
else if (wait_type == PGRES_POLLING_READING) {
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
event_queue_add_fd_read(uwsgi.master_queue, up->fd);
up->last_event = event_queue_read();
}
else if (wait_type == PGRES_POLLING_WRITING) {
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
up->last_event = event_queue_write();
}
}
}
}
// default action
return 0;
}
int probepg_init() {
uwsgi_probe_register(&uwsgi.probes, "pg", pg_prober_callback);
return 0;
}
struct uwsgi_plugin probepg_plugin = {
.init = probepg_init,
};
+9
View File
@@ -0,0 +1,9 @@
import os
NAME='probepg'
CFLAGS = os.popen('pg_config --cflags').read().rstrip().split()
CFLAGS.append('-I' + os.popen('pg_config --includedir').read().rstrip())
LDFLAGS = os.popen('pg_config --ldflags').read().rstrip().split()
LIBS = ['-L' + os.popen('pg_config --libdir').read().rstrip(), '-lpq']
GCC_LIST = ['pgprobe']
+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)
+9 -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,14 @@ void uwsgi_psgi_app() {
exit(1);
}
if (uwsgi.threads < 2) {
free(uperl.psgibuffer);
close(uperl.fd);
}
}
uwsgi_add_app(id, 5, "", 0);
uwsgi_log("PSGI app %d (%s) loaded at %p\n", id, uperl.psgi, uperl.psgi_main);
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,
+1 -1
View File
@@ -4,7 +4,7 @@ extern struct uwsgi_server uwsgi;
extern struct http_status_codes hsc[];
int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *response) {
int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
SV **status_code, **hitem ;
AV *headers, *body =NULL;
+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;
}
+5 -1
View File
@@ -257,7 +257,11 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
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;
@@ -338,12 +342,12 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
#endif
}
else {
uwsgi_log("invalid Pump response.\n");
goto clear;
}
#endif
}
+77 -4
View File
@@ -22,6 +22,57 @@ 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
#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 *app_list = NULL, *applications = NULL;
@@ -94,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();
@@ -109,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");
@@ -132,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);
@@ -144,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 mountpoint=%s\n", mountpoint);
uwsgi_log("unable to load app %d (mountpoint='%s') (callable not found or import error)\n", id, mountpoint);
goto doh;
}
@@ -309,13 +371,13 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
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());
uwsgi_log( "WSGI 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_WEB3) {
uwsgi_log( "Web3 application %d (mountpoint=%.*s) ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
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());
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->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
@@ -366,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) {
@@ -375,6 +438,7 @@ doh:
PyThreadState_Swap(up.main_thread);
}
}
#endif
return -1;
}
@@ -419,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;
@@ -442,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");
@@ -614,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;
@@ -669,6 +739,9 @@ PyObject *uwsgi_eval_loader(void *arg1) {
}
return wsgi_eval_callable;
#else
return NULL;
#endif
}
+174 -62
View File
@@ -16,7 +16,7 @@ struct option uwsgi_python_options[] = {
{"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'},
@@ -47,8 +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},
};
@@ -71,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},
@@ -99,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);
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
#else
uwsgi_log_initial("PyPy version: %s\n", PYPY_VERSION);
#endif
#ifndef UWSGI_PYPY
if (up.home != NULL) {
#ifdef PYTHREE
wchar_t *wpyhome;
@@ -130,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);
@@ -147,7 +160,7 @@ int uwsgi_python_init() {
up.reset_ts = simple_reset_ts;
uwsgi_log("Python main interpreter initialized at %p\n", up.main_thread);
uwsgi_log_initial("Python main interpreter initialized at %p\n", up.main_thread);
return 1;
@@ -155,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)
@@ -174,6 +188,7 @@ void uwsgi_python_reset_random_seed() {
}
}
}
#endif
}
void uwsgi_python_post_fork() {
@@ -188,6 +203,7 @@ void uwsgi_python_post_fork() {
uwsgi_python_reset_random_seed();
#ifndef UWSGI_PYPY
#ifdef UWSGI_EMBEDDED
// call the post_fork_hook
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
@@ -199,6 +215,7 @@ void uwsgi_python_post_fork() {
}
PyErr_Clear();
#endif
#endif
UWSGI_RELEASE_GIL
@@ -206,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;
@@ -214,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) && strncmp(filename, "data://", 7)) {
if (!uwsgi_check_scheme(filename)) {
pyfile = fopen(filename, "r");
if (!pyfile) {
@@ -235,7 +253,6 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
if (!pyfile) {
uwsgi_error_open(real_filename);
free(real_filename);
fclose(pyfile);
return NULL;
}
}
@@ -291,10 +308,12 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
}
return py_file_module;
#else
return NULL;
#endif
}
void init_uwsgi_vars() {
int i;
@@ -303,11 +322,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) {
@@ -330,39 +344,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();
}
@@ -548,7 +529,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);
@@ -681,9 +667,11 @@ void init_uwsgi_embedded_module() {
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();
@@ -750,7 +738,6 @@ int uwsgi_python_manage_options(int i, char *optarg) {
case LONG_ARGS_PYSHELL:
uwsgi.honour_stdin = 1;
up.pyshell = 1;
uwsgi.to_hell = 1;
return 1;
case LONG_ARGS_PYIMPORT:
uwsgi_string_new_list(&up.import_list, optarg);
@@ -774,7 +761,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':
@@ -790,12 +777,12 @@ 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
@@ -819,14 +806,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) {
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, PYTHON_APP_TYPE_WSGI);
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, PYTHON_APP_TYPE_WSGI);
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;
}
@@ -852,7 +856,7 @@ char *uwsgi_pythonize(char *orig) {
name[i] = '_';
}
else if (name[i] == '/') {
name[i] = '.';
name[i] = '_';
}
}
@@ -869,7 +873,6 @@ void uwsgi_python_spooler_init(void) {
struct uwsgi_string_list *upli = up.spooler_import_list;
UWSGI_GET_GIL
while(upli) {
@@ -896,19 +899,26 @@ void uwsgi_python_init_apps() {
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) {
@@ -1011,9 +1021,11 @@ void uwsgi_python_init_apps() {
}
if (uwsgi.profiler) {
#ifndef UWSGI_PYPY
if (!strcmp(uwsgi.profiler, "pycall")) {
PyEval_SetProfile(uwsgi_python_profiler_call, NULL);
}
#endif
}
}
@@ -1064,7 +1076,9 @@ void uwsgi_python_enable_threads() {
up.swap_ts = threaded_swap_ts;
up.reset_ts = threaded_reset_ts;
}
uwsgi_log("threads support enabled\n");
}
@@ -1075,6 +1089,35 @@ 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("python ThreadState %d = %p\n", core_id, pts);
#endif
UWSGI_GET_GIL;
// call threading.currentThread (taken from mod_wsgi, but removes DECREFs as thread in uWSGI are fixed)
PyObject *threading_module = PyImport_ImportModule("threading");
if (threading_module) {
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
if (threading_module_dict) {
#ifdef PYTHREE
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
#else
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
#endif
if (threading_current) {
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
if (!current_thread) {
// ignore the error
PyErr_Clear();
}
else {
PyObject_SetAttrString(current_thread, "name", PyString_FromFormat("uWSGIWorker%dCore%d", uwsgi.mywid, core_id));
Py_INCREF(current_thread);
}
}
}
}
UWSGI_RELEASE_GIL;
}
@@ -1128,6 +1171,7 @@ int uwsgi_python_xml(char *node, char *content) {
return 0;
}
#ifndef UWSGI_PYPY
void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
PyThreadState *tstate = PyThreadState_GET();
@@ -1142,6 +1186,7 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
}
}
#endif
char *uwsgi_python_code_string(char *id, char *code, char *function, char *key, uint16_t keylen) {
@@ -1211,6 +1256,7 @@ int uwsgi_python_signal_handler(uint8_t sig, void *handler) {
ret = python_call(handler, args, 0, NULL);
Py_DECREF(args);
if (ret) {
Py_DECREF(ret);
UWSGI_RELEASE_GIL;
return 0;
}
@@ -1222,6 +1268,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;
@@ -1240,10 +1288,11 @@ uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
if (ret) {
if (PyString_Check(ret)) {
rv = PyString_AsString(ret);
rl = strlen(rv);
rl = PyString_Size(ret);
if (rl <= 0xffff) {
memcpy(buffer, rv, rl);
Py_DECREF(ret);
UWSGI_RELEASE_GIL;
return rl;
}
}
@@ -1252,6 +1301,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;
@@ -1329,6 +1379,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();
@@ -1343,21 +1394,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 = {
@@ -1369,7 +1476,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,
@@ -1385,8 +1492,10 @@ 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,
@@ -1394,6 +1503,9 @@ struct uwsgi_plugin python_plugin = {
.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,
+16 -2
View File
@@ -72,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) {
@@ -104,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
}
+59 -8
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;
@@ -201,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;
@@ -231,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;
@@ -306,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);
@@ -334,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);
@@ -363,7 +383,7 @@ static PyMethodDef symzipimporter_methods[] = {
};
static void uwsgi_symimporter_free(struct _symimporter *self) {
PyObject_Del(self);
PyObject_Del(self);
}
@@ -406,7 +426,7 @@ 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
@@ -424,7 +444,7 @@ zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
// avoid GC !!!
name = uwsgi_concat2(name, "");
if (!uwsgi_startswith(name, "http://", 7) || !uwsgi_startswith(name, "data://", 7) || !uwsgi_startswith(name, "sym://", 6) ) {
if (uwsgi_check_scheme(name)) {
prefix = uwsgi_get_last_char(name, '/');
prefix = uwsgi_get_last_char(prefix, ':');
}
@@ -442,35 +462,53 @@ zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
return -1;
}
PyObject *stringio = PyImport_ImportModule("StringIO");
if (!stringio) {
return -1;
}
PyObject *stringio_dict = PyModule_GetDict(stringio);
#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;
}
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
#ifdef PYTHREE
self->zip = PyObject_CallMethodObjArgs(zipfile, PyString_FromString("ZipFile"), source_code);
#else
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
if (!zipfile_dict) {
return -1;
}
@@ -480,10 +518,13 @@ zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
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;
}
@@ -545,6 +586,9 @@ symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds
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) {
return -1;
@@ -558,7 +602,9 @@ symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds
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) {
return -1;
}
@@ -568,6 +614,9 @@ symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds
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;
@@ -581,7 +630,9 @@ symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds
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;
}
@@ -644,7 +695,7 @@ 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 = {
@@ -686,7 +737,7 @@ static PyTypeObject ZipImporter_Type = {
(initproc) zipimporter_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
PyObject_GC_Del, /* tp_free */
0, /* tp_free */
};
File diff suppressed because it is too large Load Diff
+11 -3
View File
@@ -20,6 +20,7 @@
#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
@@ -29,6 +30,7 @@
#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
@@ -94,9 +96,11 @@ 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[1024];
char readline[UWSGI_PY_READLINE_BUFSIZE];
size_t readline_size;
size_t readline_max_size;
size_t readline_pos;
@@ -264,8 +268,12 @@ 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
+24 -16
View File
@@ -4,28 +4,36 @@ from distutils import sysconfig
NAME='python'
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)
+1 -1
View File
@@ -192,12 +192,12 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
#endif
}
else {
uwsgi_log("invalid Web3 response.\n");
goto clear;
}
#endif
}
+2 -2
View File
@@ -46,11 +46,11 @@ 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) {
UWSGI_GET_GIL
-6
View File
@@ -191,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;
@@ -202,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);
+20 -2
View File
@@ -22,12 +22,15 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
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
#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");
@@ -44,6 +47,8 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
}
}
#ifndef UWSGI_PYPY
// if async_post is mapped as a file, directly use it as wsgi.input
if (wsgi_req->async_post) {
#ifdef PYTHREE
@@ -62,7 +67,9 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
}
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input);
#endif
#ifdef UWSGI_SENDFILE
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->sendfile);
@@ -78,12 +85,16 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
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);
}
@@ -117,10 +128,13 @@ 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
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
@@ -180,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;
+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']
+777
View File
@@ -0,0 +1,777 @@
#include "uwsgi_rack.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_rack ur;
#define uwsgi_rack_api(x, y, z) rb_define_module_function(rb_uwsgi_embedded, x, y, z)
VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
Check_Type(rbmessage, T_STRING);
char *message = RSTRING_PTR(rbmessage);
size_t len = RSTRING_LEN(rbmessage);
if (len > 80) {
uwsgi_log("- warning message must be max 80 chars, it will be truncated -");
memcpy(uwsgi.shared->warning_message, message, 80);
uwsgi.shared->warning_message[80] = 0;
}
else {
memcpy(uwsgi.shared->warning_message, message, len);
uwsgi.shared->warning_message[len] = 0;
}
return Qnil;
}
VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
Check_Type(rbname, T_STRING);
char *name = RSTRING_PTR(rbname);
uwsgi_set_processname(name);
return Qnil;
}
VALUE rack_uwsgi_mem(VALUE *class) {
uint64_t rss=0, vsz = 0;
VALUE ml = rb_ary_new2(2);
get_memusage(&rss, &vsz);
rb_ary_store(ml, 0, LONG2NUM(rss));
rb_ary_store(ml, 1, LONG2NUM(vsz));
return ml;
}
VALUE rack_uwsgi_request_id(VALUE *class) {
return ULONG2NUM(uwsgi.workers[uwsgi.mywid].requests);
}
VALUE rack_uwsgi_worker_id(VALUE *class) {
return INT2NUM(uwsgi.mywid);
}
VALUE rack_uwsgi_mule_id(VALUE *class) {
return INT2NUM(uwsgi.muleid);
}
VALUE rack_uwsgi_logsize(VALUE *class) {
return ULONG2NUM(uwsgi.shared->logsize);
}
VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
int fd = -1;
int mule_id = -1;
if (argc == 0) return Qnil;
Check_Type(argv[0], T_STRING);
char *message = RSTRING_PTR(argv[0]);
size_t message_len = RSTRING_LEN(argv[0]);
if (uwsgi.mules_cnt < 1) {
rb_raise(rb_eRuntimeError, "no mule configured");
return Qnil;
}
if (argc == 1) {
mule_send_msg(uwsgi.shared->mule_queue_pipe[0], message, message_len);
}
else {
if (TYPE(argv[1]) == T_STRING) {
struct uwsgi_farm *uf = get_farm_by_name(RSTRING_PTR(argv[1]));
if (uf == NULL) {
rb_raise(rb_eRuntimeError, "unknown farm");
return Qnil;
}
fd = uf->queue_pipe[0];
}
else if (TYPE(argv[1]) == T_FIXNUM) {
mule_id = NUM2INT(argv[1]);
if (mule_id < 0 && mule_id > uwsgi.mules_cnt) {
rb_raise(rb_eRuntimeError, "invalid mule number");
return Qnil;
}
if (mule_id == 0) {
fd = uwsgi.shared->mule_queue_pipe[0];
}
else {
fd = uwsgi.mules[mule_id-1].queue_pipe[0];
}
}
else {
rb_raise(rb_eRuntimeError, "invalid mule");
return Qnil;
}
if (fd > -1) {
mule_send_msg(fd, message, message_len);
}
}
return Qnil;
}
int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
Check_Type(key, T_SYMBOL);
ID key_id = SYM2ID(key);
const char *key_name = rb_id2name(key_id);
if (!strcmp(key_name, "signals")) {
rb_ary_store(arg_array, 0, val);
}
else if (!strcmp(key_name, "farms")) {
rb_ary_store(arg_array, 1, val);
}
else if (!strcmp(key_name, "timeout")) {
rb_ary_store(arg_array, 2, val);
}
else if (!strcmp(key_name, "buffer_size")) {
rb_ary_store(arg_array, 3, val);
}
return 0;
}
VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
int manage_signals = 1;
int manage_farms = 1;
int timeout = -1;
size_t buffer_size = 65536;
ssize_t len = 0;
char *message;
if (uwsgi.muleid == 0) {
rb_raise(rb_eRuntimeError, "you can receive mule messages only in a mule !!!");
return Qnil;
}
if (argc > 0) {
// 0 = manage_signals
// 1 = manage_farms
// 2 = timeout
// 3 = buffer_size
VALUE arg_array = rb_ary_new2(4);
Check_Type(argv[0], T_HASH);
rb_hash_foreach(argv[0], uwsgi_ruby_hash_mule_callback, arg_array);
if (rb_ary_entry(arg_array, 0) == Qfalse) {
manage_signals = 0;
}
if (rb_ary_entry(arg_array, 1) == Qfalse) {
manage_farms = 0;
}
if (TYPE(rb_ary_entry(arg_array,2)) == T_FIXNUM) {
timeout = NUM2INT(rb_ary_entry(arg_array,2));
}
if (TYPE(rb_ary_entry(arg_array,3)) == T_FIXNUM || TYPE(rb_ary_entry(arg_array,3)) == T_BIGNUM) {
buffer_size = NUM2ULONG(rb_ary_entry(arg_array,3));
}
}
message = uwsgi_malloc(buffer_size);
len = uwsgi_mule_get_msg(manage_signals, manage_farms, message, buffer_size, timeout) ;
if (len < 0) {
free(message);
return Qnil;
}
VALUE msg = rb_str_new(message, len);
free(message);
return msg;
}
VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
int lock_num = 0;
if (argc > 0) {
Check_Type(argv[0], T_FIXNUM);
lock_num = NUM2INT(argv[0]);
}
if (lock_num < 0 || lock_num > uwsgi.locks) {
rb_raise(rb_eRuntimeError, "Invalid lock number");
return Qnil;
}
uwsgi_lock(uwsgi.user_lock[lock_num]);
return Qnil;
}
VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
int lock_num = 0;
if (argc > 0) {
Check_Type(argv[0], T_FIXNUM);
lock_num = NUM2INT(argv[0]);
}
if (lock_num < 0 || lock_num > uwsgi.locks) {
rb_raise(rb_eRuntimeError, "Invalid lock number");
return Qnil;
}
uwsgi_unlock(uwsgi.user_lock[lock_num]);
return Qnil;
}
VALUE rack_uwsgi_cache_set(VALUE *class, VALUE rbkey, VALUE rbvalue) {
Check_Type(rbkey, T_STRING);
Check_Type(rbvalue, T_STRING);
char *key = RSTRING_PTR(rbkey);
uint64_t keylen = RSTRING_LEN(rbkey);
char *value = RSTRING_PTR(rbvalue);
uint64_t vallen = RSTRING_LEN(rbvalue);
uint64_t expires = 0;
if (vallen > uwsgi.cache_blocksize) {
rb_raise(rb_eRuntimeError, "uWSGI cache items size must be < %llu, requested %llu bytes", (unsigned long long)uwsgi.cache_blocksize, (unsigned long long) vallen);
return Qnil;
}
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_set(key, keylen, value, vallen, expires, 0)) {
uwsgi_rwunlock(uwsgi.cache_lock);
return Qnil;
}
uwsgi_rwunlock(uwsgi.cache_lock);
return Qtrue;
}
VALUE rack_uwsgi_cache_update(VALUE *class, VALUE rbkey, VALUE rbvalue) {
Check_Type(rbkey, T_STRING);
Check_Type(rbvalue, T_STRING);
char *key = RSTRING_PTR(rbkey);
uint64_t keylen = RSTRING_LEN(rbkey);
char *value = RSTRING_PTR(rbvalue);
uint64_t vallen = RSTRING_LEN(rbvalue);
uint64_t expires = 0;
if (vallen > uwsgi.cache_blocksize) {
rb_raise(rb_eRuntimeError, "uWSGI cache items size must be < %llu, requested %llu bytes", (unsigned long long)uwsgi.cache_blocksize, (unsigned long long) vallen);
return Qnil;
}
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
uwsgi_rwunlock(uwsgi.cache_lock);
return Qnil;
}
uwsgi_rwunlock(uwsgi.cache_lock);
return Qtrue;
}
VALUE rack_uwsgi_cache_set_exc(VALUE *class, VALUE rbkey, VALUE rbvalue) {
VALUE ret;
ret = rack_uwsgi_cache_set(class, rbkey, rbvalue);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to set value in uWSGI cache");
}
return ret;
}
VALUE rack_uwsgi_cache_update_exc(VALUE *class, VALUE rbkey, VALUE rbvalue) {
VALUE ret;
ret = rack_uwsgi_cache_update(class, rbkey, rbvalue);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to update value in uWSGI cache");
}
return ret;
}
VALUE rack_uwsgi_cache_del(VALUE *class, VALUE rbkey) {
Check_Type(rbkey, T_STRING);
char *key = RSTRING_PTR(rbkey);
size_t keylen = RSTRING_LEN(rbkey);
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_del(key, keylen)) {
uwsgi_rwunlock(uwsgi.cache_lock);
return Qfalse;
}
uwsgi_rwunlock(uwsgi.cache_lock);
return Qtrue;
}
VALUE rack_uwsgi_cache_exists(VALUE *class, VALUE rbkey) {
Check_Type(rbkey, T_STRING);
char *key = RSTRING_PTR(rbkey);
size_t keylen = RSTRING_LEN(rbkey);
if (uwsgi_cache_exists(key, keylen)) {
return Qtrue;
}
return Qfalse;
}
VALUE rack_uwsgi_cache_get(VALUE *class, VALUE rbkey) {
Check_Type(rbkey, T_STRING);
char *key = RSTRING_PTR(rbkey);
size_t keylen = RSTRING_LEN(rbkey);
uint64_t valsize;
char *value = NULL;
uwsgi_rlock(uwsgi.cache_lock);
value = uwsgi_cache_get(key, keylen, &valsize);
if (!value) {
uwsgi_rwunlock(uwsgi.cache_lock);
return Qnil;
}
VALUE res = rb_str_new(value, valsize);
uwsgi_rwunlock(uwsgi.cache_lock);
return res;
}
VALUE rack_uwsgi_cache_get_exc(VALUE *class, VALUE rbkey) {
VALUE ret;
ret = rack_uwsgi_cache_get(class, rbkey);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to get value from uWSGI cache");
}
return ret;
}
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(rbmin, T_FIXNUM);
Check_Type(rbhour, T_FIXNUM);
Check_Type(rbday, T_FIXNUM);
Check_Type(rbmon, T_FIXNUM);
Check_Type(rbweek, T_FIXNUM);
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) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(secs, T_FIXNUM);
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) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(secs, T_FIXNUM);
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) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(rbfilename, T_STRING);
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) {
Check_Type(arg1, T_FIXNUM);
Check_Type(arg2, T_FIXNUM);
struct wsgi_request *wsgi_req = current_wsgi_req();
int fd = NUM2INT(arg1);
int timeout = NUM2INT(arg2);
if (fd >= 0) {
async_add_fd_read(wsgi_req, fd, timeout);
}
return Qtrue;
}
VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
Check_Type(arg1, T_FIXNUM);
Check_Type(arg2, T_FIXNUM);
struct wsgi_request *wsgi_req = current_wsgi_req();
int fd = NUM2INT(arg1);
int timeout = NUM2INT(arg2);
if (fd >= 0) {
async_add_fd_write(wsgi_req, fd, timeout);
}
return Qtrue;
}
VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
Check_Type(arg, T_STRING);
int fd = uwsgi_connect(RSTRING_PTR(arg), 0, 1);
return INT2FIX(fd);
}
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
Check_Type(arg, T_FIXNUM);
struct wsgi_request *wsgi_req = current_wsgi_req();
int timeout = NUM2INT(arg);
if (timeout >= 0) {
async_add_timeout(wsgi_req, timeout);
}
return Qtrue;
}
VALUE uwsgi_ruby_masterpid(VALUE *class) {
if (uwsgi.master_process) {
return INT2NUM(uwsgi.workers[0].pid);
}
return INT2NUM(0);
}
VALUE uwsgi_ruby_suspend(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
uwsgi.schedule_to_main(wsgi_req);
return Qtrue;
}
VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
uint8_t received_signal;
wsgi_req->signal_received = -1;
if (argc > 0) {
Check_Type(argv[0], T_FIXNUM);
uwsgi_signal = NUM2INT(argv[0]);
wait_for_specific_signal = 1;
}
if (wait_for_specific_signal) {
received_signal = uwsgi_signal_wait(uwsgi_signal);
}
else {
received_signal = uwsgi_signal_wait(-1);
}
wsgi_req->signal_received = received_signal;
return Qnil;
}
VALUE uwsgi_ruby_signal_received(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
return INT2NUM(wsgi_req->signal_received);
}
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
Check_Type(signum, T_FIXNUM);
uint8_t uwsgi_signal = NUM2INT(signum);
if (uwsgi_signal_registered(uwsgi_signal)) {
return Qtrue;
}
return Qfalse;
}
VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
int rb_argc = 0;
if (argc < 2) goto clear;
if (argc > 2) {
Check_Type(argv[2], T_FIXNUM);
rb_argc = NUM2INT(argv[2]);
}
Check_Type(argv[0], T_STRING);
char *name = RSTRING_PTR(argv[0]);
void *func = (void *) argv[1];
if (uwsgi_register_rpc(name, 7, rb_argc, func)) {
clear:
rb_raise(rb_eRuntimeError, "unable to register rpc function");
return Qnil;
}
rb_gc_register_address(&argv[1]);
rb_ary_push(ur.rpc_protector, argv[1]);
return Qtrue;
}
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
Check_Type(signum, T_FIXNUM);
Check_Type(sigkind, T_STRING);
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);
rb_ary_push(ur.signals_protector, rbhandler);
return Qtrue;
}
VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
if (argc < 1) {
rb_raise(rb_eRuntimeError, "you have to specify a signum");
return Qnil;
}
Check_Type(argv[0], T_FIXNUM);
uint8_t uwsgi_signal = NUM2INT(argv[0]);
if (argc > 1) {
Check_Type(argv[1], T_STRING);
char *remote = RSTRING_PTR(argv[1]);
int ret = uwsgi_remote_signal_send(remote, uwsgi_signal);
if (ret == 1) return Qtrue;
if (ret == -1) {
rb_raise(rb_eRuntimeError, "unable to deliver signal %d to node %s", uwsgi_signal, remote);
return Qnil;
}
if (ret == 0) {
rb_raise(rb_eRuntimeError, "node %s rejected signal %d", remote, uwsgi_signal);
return Qnil;
}
}
else {
uwsgi_signal_send(uwsgi.signal_socket, uwsgi_signal);
}
return Qtrue;
}
void uwsgi_rack_init_api() {
VALUE rb_uwsgi_embedded = rb_define_module("UWSGI");
uwsgi_rack_api("suspend", uwsgi_ruby_suspend, 0);
uwsgi_rack_api("masterpid", uwsgi_ruby_masterpid, 0);
uwsgi_rack_api("async_sleep", uwsgi_ruby_async_sleep, 1);
uwsgi_rack_api("wait_fd_read", uwsgi_ruby_wait_fd_read, 2);
uwsgi_rack_api("wait_fd_write", uwsgi_ruby_wait_fd_write, 2);
uwsgi_rack_api("async_connect", uwsgi_ruby_async_connect, 1);
uwsgi_rack_api("signal", uwsgi_ruby_signal, -1);
uwsgi_rack_api("register_signal", uwsgi_ruby_register_signal, 3);
uwsgi_rack_api("register_rpc", uwsgi_ruby_register_rpc, -1);
uwsgi_rack_api("signal_registered", uwsgi_ruby_signal_registered, 1);
uwsgi_rack_api("signal_wait", uwsgi_ruby_signal_wait, -1);
uwsgi_rack_api("signal_received", uwsgi_ruby_signal_received, 0);
uwsgi_rack_api("add_cron", rack_uwsgi_add_cron, 6);
uwsgi_rack_api("add_timer", rack_uwsgi_add_timer, 2);
uwsgi_rack_api("add_rb_timer", rack_uwsgi_add_rb_timer, 2);
uwsgi_rack_api("add_file_monitor", rack_uwsgi_add_file_monitor, 2);
uwsgi_rack_api("setprocname", rack_uwsgi_setprocname, 1);
uwsgi_rack_api("mem", rack_uwsgi_mem, 0);
uwsgi_rack_api("lock", rack_uwsgi_lock, -1);
uwsgi_rack_api("unlock", rack_uwsgi_unlock, -1);
uwsgi_rack_api("mule_get_msg", rack_uwsgi_mule_get_msg, -1);
uwsgi_rack_api("mule_msg", rack_uwsgi_mule_msg, -1);
uwsgi_rack_api("request_id", rack_uwsgi_request_id, 0);
uwsgi_rack_api("worker_id", rack_uwsgi_worker_id, 0);
uwsgi_rack_api("mule_id", rack_uwsgi_mule_id, 0);
uwsgi_rack_api("logsize", rack_uwsgi_logsize, 0);
uwsgi_rack_api("set_warning_message", rack_uwsgi_warning, 1);
if (uwsgi.cache_max_items > 0) {
uwsgi_rack_api("cache_get", rack_uwsgi_cache_get, 1);
uwsgi_rack_api("cache_get!", rack_uwsgi_cache_get_exc, 1);
uwsgi_rack_api("cache_exists", rack_uwsgi_cache_exists, 1);
uwsgi_rack_api("cache_exists?", rack_uwsgi_cache_exists, 1);
uwsgi_rack_api("cache_del", rack_uwsgi_cache_del, 1);
uwsgi_rack_api("cache_set", rack_uwsgi_cache_set, 2);
uwsgi_rack_api("cache_set!", rack_uwsgi_cache_set_exc, 2);
uwsgi_rack_api("cache_update", rack_uwsgi_cache_update, 2);
uwsgi_rack_api("cache_update!", rack_uwsgi_cache_update_exc, 2);
}
VALUE uwsgi_rb_opt_hash = rb_hash_new();
int i;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
VALUE rb_uwsgi_opt_key = rb_str_new2(uwsgi.exported_opts[i]->key);
if ( rb_funcall(uwsgi_rb_opt_hash, rb_intern("has_key?"), 1, rb_uwsgi_opt_key) == Qtrue) {
VALUE rb_uwsgi_opt_item = rb_hash_aref(uwsgi_rb_opt_hash, rb_uwsgi_opt_key);
if (TYPE(rb_uwsgi_opt_item) == T_ARRAY) {
if (uwsgi.exported_opts[i]->value == NULL) {
rb_ary_push(rb_uwsgi_opt_item, Qtrue);
}
else {
rb_ary_push(rb_uwsgi_opt_item, rb_str_new2(uwsgi.exported_opts[i]->value));
}
}
else {
VALUE rb_uwsgi_opt_list = rb_ary_new();
rb_ary_push(rb_uwsgi_opt_list, rb_uwsgi_opt_item);
if (uwsgi.exported_opts[i]->value == NULL) {
rb_ary_push(rb_uwsgi_opt_list, Qtrue);
}
else {
rb_ary_push(rb_uwsgi_opt_list, rb_str_new2(uwsgi.exported_opts[i]->value));
}
rb_hash_aset(uwsgi_rb_opt_hash, rb_uwsgi_opt_key, rb_uwsgi_opt_list);
}
}
else {
if (uwsgi.exported_opts[i]->value == NULL) {
rb_hash_aset(uwsgi_rb_opt_hash, rb_uwsgi_opt_key, Qtrue);
}
else {
rb_hash_aset(uwsgi_rb_opt_hash, rb_uwsgi_opt_key, rb_str_new2(uwsgi.exported_opts[i]->value));
}
}
}
rb_const_set(rb_uwsgi_embedded, rb_intern("OPT"), uwsgi_rb_opt_hash);
rb_const_set(rb_uwsgi_embedded, rb_intern("VERSION"), rb_str_new2(UWSGI_VERSION));
rb_const_set(rb_uwsgi_embedded, rb_intern("HOSTNAME"), rb_str_new(uwsgi.hostname, uwsgi.hostname_len));
if (uwsgi.pidfile) {
rb_const_set(rb_uwsgi_embedded, rb_intern("PIDFILE"), rb_str_new2(uwsgi.pidfile));
}
rb_const_set(rb_uwsgi_embedded, rb_intern("NUMPROC"), INT2NUM(uwsgi.numproc));
}
+278 -252
View File
@@ -9,6 +9,13 @@ 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},
{"rb-gc-freq", required_argument, 0, LONG_ARGS_RUBY_GC_FREQ},
{"rb-require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
{"ruby-require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
{"rbrequire", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
{"rubyrequire", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
{"require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
{"rbshell", optional_argument, 0, LONG_ARGS_RUBY_SHELL},
{0, 0, 0, 0},
@@ -126,6 +133,10 @@ VALUE rb_uwsgi_io_rewind(VALUE obj, VALUE args) {
RUBY_GLOBAL_SETUP
#endif
VALUE uwsgi_require_file(VALUE arg) {
return rb_funcall(rb_cObject, rb_intern("require"), 1, arg);
}
VALUE require_rack(VALUE arg) {
return rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("rack"));
}
@@ -140,200 +151,51 @@ 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 rack_call_rpc_handler(VALUE args) {
VALUE rpc_args = rb_ary_entry(args, 1);
return rb_funcall2(rb_ary_entry(args, 0), rb_intern("call"), RARRAY_LEN(rpc_args), RARRAY_PTR(rpc_args));
}
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) {
uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
uint8_t i;
VALUE rb_args = rb_ary_new2(2);
VALUE rb_rpc_args = rb_ary_new2(argc);
VALUE ret;
int error = 0;
char *rv;
size_t rl;
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;
rb_ary_store(rb_args, 0, (VALUE) func);
for (i = 0; i < argc; i++) {
rb_ary_store(rb_rpc_args, i, rb_str_new2(argv[i]));
}
rb_ary_store(rb_args, 1, rb_rpc_args);
ret = rb_protect(rack_call_rpc_handler, rb_args, &error);
if (error) {
uwsgi_ruby_exception();
return 0;
}
// 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;
if (TYPE(ret) == T_STRING) {
rv = RSTRING_PTR(ret);
rl = RSTRING_LEN(ret);
if (rl <= 0xffff) {
memcpy(buffer, rv, rl);
return rl;
}
}
return Qtrue;
return 0;
}
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();
int fd = NUM2INT(arg1);
int timeout = NUM2INT(arg2);
if (fd >= 0) {
async_add_fd_read(wsgi_req, fd, timeout);
}
return Qtrue;
}
VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
struct wsgi_request *wsgi_req = current_wsgi_req();
int fd = NUM2INT(arg1);
int timeout = NUM2INT(arg2);
if (fd >= 0) {
async_add_fd_write(wsgi_req, fd, timeout);
}
return Qtrue;
}
VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
int fd = uwsgi_connect(RSTRING_PTR(arg), 0, 1);
return INT2FIX(fd);
}
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
struct wsgi_request *wsgi_req = current_wsgi_req();
int timeout = NUM2INT(arg);
if (timeout >= 0) {
async_add_timeout(wsgi_req, timeout);
}
return Qtrue;
}
VALUE uwsgi_ruby_suspend(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
uwsgi.schedule_to_main(wsgi_req);
return Qtrue;
}
int uwsgi_rack_init(){
struct http_status_codes *http_sc;
@@ -349,15 +211,12 @@ int uwsgi_rack_init(){
http_sc->message_size = (int) strlen(http_sc->message);
}
ur.unprotected = 0;
#ifdef RUBY19
ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK
ruby_init();
ruby_process_options(argc, argv);
#else
ruby_init();
ruby_init_loadpath();
#endif
@@ -365,19 +224,14 @@ int uwsgi_rack_init(){
ruby_script("uwsgi");
VALUE rb_uwsgi_embedded = rb_define_module("UWSGI");
rb_define_module_function(rb_uwsgi_embedded, "suspend", uwsgi_ruby_suspend, 0);
rb_define_module_function(rb_uwsgi_embedded, "async_sleep", uwsgi_ruby_async_sleep, 1);
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);
ur.signals_protector = rb_ary_new();
ur.rpc_protector = rb_ary_new();
rb_gc_register_address(&ur.signals_protector);
rb_gc_register_address(&ur.rpc_protector);
#ifdef UWSGI_EMBEDDED
uwsgi_rack_init_api();
#endif
return 0;
}
@@ -385,6 +239,17 @@ int uwsgi_rack_init(){
void uwsgi_rack_init_apps(void) {
int error;
ur.app_id = uwsgi_apps_cnt;
struct uwsgi_string_list *usl = ur.rbrequire;
while(usl) {
error = 0;
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
if (error) {
uwsgi_ruby_exception();
}
usl = usl->next;
}
if (ur.rack) {
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error);
@@ -447,6 +312,14 @@ ready:
rb_define_method(ur.rb_uwsgi_io_class, "read", rb_uwsgi_io_read, -2);
rb_define_method(ur.rb_uwsgi_io_class, "rewind", rb_uwsgi_io_rewind, 0);
uwsgi_add_app(ur.app_id, 7, (char*)"", 0);
if (ur.gc_freq <= 1) {
uwsgi_log("RACK app %d loaded at %p (GC frequency: AGGRESSIVE)\n", ur.app_id, ur.call);
}
else {
uwsgi_log("RACK app %d loaded at %p (GC frequency: %d)\n", ur.app_id, ur.call, ur.gc_freq);
}
}
VALUE call_dispatch(VALUE env) {
@@ -455,7 +328,7 @@ VALUE call_dispatch(VALUE env) {
}
VALUE send_body(VALUE obj) {
static VALUE send_body(VALUE obj) {
struct wsgi_request *wsgi_req = current_wsgi_req();
ssize_t len = 0;
@@ -473,6 +346,15 @@ VALUE send_body(VALUE obj) {
return Qnil;
}
VALUE body_to_path(VALUE body) {
return rb_funcall( body, rb_intern("to_path"), 0);
}
VALUE close_body(VALUE body) {
return rb_funcall( body, rb_intern("close"), 0);
}
VALUE iterate_body(VALUE body) {
#ifdef RUBY19
@@ -480,7 +362,6 @@ VALUE iterate_body(VALUE body) {
#else
return rb_iterate(rb_each, body, send_body, 0);
#endif
}
VALUE send_header(VALUE obj, VALUE headers) {
@@ -522,7 +403,7 @@ VALUE send_header(VALUE obj, VALUE headers) {
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, ": ", 2);
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
char *header_value = RSTRING_PTR(hval);
@@ -533,7 +414,7 @@ VALUE send_header(VALUE obj, VALUE headers) {
if (!header_value_splitted) {
len = wsgi_req->socket->proto_write_header( wsgi_req, header_value, header_value_len);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, "\r\n", 2);
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
wsgi_req->header_cnt++;
}
@@ -541,7 +422,7 @@ VALUE send_header(VALUE obj, VALUE headers) {
header_value_splitted[0] = 0;
len = wsgi_req->socket->proto_write_header( wsgi_req, header_value, header_value_splitted-header_value);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, "\r\n", 2);
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
wsgi_req->header_cnt++;
@@ -553,12 +434,12 @@ VALUE send_header(VALUE obj, VALUE headers) {
len = wsgi_req->socket->proto_write( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write( wsgi_req, ": ", 2);
len = wsgi_req->socket->proto_write( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write( wsgi_req, header_value, header_value_splitted-header_value);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write( wsgi_req, "\r\n", 2);
len = wsgi_req->socket->proto_write( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
wsgi_req->header_cnt++;
@@ -607,6 +488,9 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
return -1;
}
wsgi_req->app_id = ur.app_id;
uwsgi_apps[wsgi_req->app_id].requests++;
env = rb_hash_new();
@@ -666,13 +550,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
rb_hash_aset(env, rb_str_new2("rack.errors"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(2), rb_str_new("w",1) ));
if (ur.unprotected) {
ret = rb_funcall(ur.dispatcher, ur.call, 1, env);
}
else {
ret = rb_protect( call_dispatch, env, &error);
}
ret = rb_protect( call_dispatch, env, &error);
if (error) {
uwsgi_ruby_exception();
//return -1;
@@ -722,62 +600,53 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
headers = RARRAY_PTR(ret)[1] ;
if (rb_respond_to( headers, rb_intern("each") )) {
if (ur.unprotected) {
#ifdef RUBY19
rb_block_call(headers, rb_intern("each"), 0, 0, send_header, headers);
#else
rb_iterate(rb_each, headers, send_header, headers);
#endif
}
else {
rb_protect( iterate_headers, headers, &error);
if (error) {
uwsgi_ruby_exception();
rb_gc_unregister_address(&status);
rb_gc_unregister_address(&headers);
goto clear;
}
rb_protect( iterate_headers, headers, &error);
if (error) {
uwsgi_ruby_exception();
rb_gc_unregister_address(&status);
rb_gc_unregister_address(&headers);
goto clear;
}
}
if (wsgi_req->socket->proto_write(wsgi_req, "\r\n", 2) != 2) {
if (wsgi_req->socket->proto_write(wsgi_req, (char *)"\r\n", 2) != 2) {
uwsgi_error("write()");
}
body = RARRAY_PTR(ret)[2] ;
if (rb_respond_to( body, rb_intern("to_path") )) {
VALUE sendfile_path = rb_funcall( body, rb_intern("to_path"), 0);
wsgi_req->sendfile_fd = open(RSTRING_PTR(sendfile_path), O_RDONLY);
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);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
}
}
rb_gc_unregister_address(&sendfile_path);
// TODO protect to_path
}
else if (rb_respond_to( body, rb_intern("each") )) {
if (ur.unprotected) {
#ifdef RUBY19
rb_block_call(body, rb_intern("each"), 0, 0, send_body, 0);
#else
rb_iterate(rb_each, body, send_body, 0);
#endif
if (rb_respond_to( body, rb_intern("to_path") )) {
VALUE sendfile_path = rb_protect( body_to_path, body, &error);
if (error) {
uwsgi_ruby_exception();
}
else {
rb_protect( iterate_body, body, &error);
if (error) {
uwsgi_ruby_exception();
wsgi_req->sendfile_fd = open(RSTRING_PTR(sendfile_path), O_RDONLY);
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);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
}
}
rb_gc_unregister_address(&sendfile_path);
}
}
else if (rb_respond_to( body, rb_intern("each") )) {
rb_protect( iterate_body, body, &error);
if (error) {
uwsgi_ruby_exception();
}
}
if (rb_respond_to( body, rb_intern("close") )) {
//uwsgi_log("calling close\n");
rb_funcall( body, rb_intern("close"), 0);
rb_protect( close_body, body, &error);
if (error) {
uwsgi_ruby_exception();
}
}
//fine:
@@ -790,7 +659,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
}
else {
internal_server_error(wsgi_req, "Invalid RACK response");
internal_server_error(wsgi_req, (char *)"Invalid RACK response");
}
clear:
@@ -800,7 +669,9 @@ clear:
rb_gc_unregister_address(&env);
if (ur.gc_freq <= 1 || ur.cycles%ur.gc_freq == 0) {
//uwsgi_log("calling ruby GC\n");
#ifdef UWSGI_DEBUG
uwsgi_log("calling ruby GC\n");
#endif
rb_gc();
}
@@ -834,6 +705,9 @@ int uwsgi_rack_manage_options(int i, char *optarg) {
case LONG_ARGS_RUBY_GC_FREQ:
ur.gc_freq = atoi(optarg);
return 1;
case LONG_ARGS_RUBY_REQUIRE:
uwsgi_string_new_list(&ur.rbrequire, optarg);
return 1;
}
return 0;
@@ -849,6 +723,44 @@ void uwsgi_rack_resume(struct wsgi_request *wsgi_req) {
uwsgi_log("RESUMING RUBY\n");
}
#ifdef RUBY19
VALUE uwsgi_call_block(VALUE body, VALUE block) {
return rb_funcall(block, rb_intern("call"), 1, body );
}
VALUE uwsgi_rack_patch_body_proxy_each(int argc, VALUE *argv, VALUE self) {
VALUE block = Qnil;
rb_scan_args(argc, argv, "0&", &block);
if(!RTEST(block)) {
rb_raise(rb_eArgError, "a block is required");
return Qnil;
}
VALUE original_body = rb_iv_get(self, "@body");
if (original_body != Qnil) {
return rb_block_call(original_body, rb_intern("each"), 0, 0, uwsgi_call_block, block);
}
return Qnil;
}
VALUE uwsgi_rack_patch_body_proxy(VALUE foo) {
VALUE rack = rb_const_get(rb_cObject, rb_intern("Rack"));
VALUE rack_body_proxy = rb_const_get(rack, rb_intern("BodyProxy"));
if (!rb_respond_to(rack_body_proxy, rb_intern("each"))) {
rb_define_method(rack_body_proxy, "each", uwsgi_rack_patch_body_proxy_each, -1);
return Qtrue;
}
return Qnil;
}
#endif
VALUE init_rack_app( VALUE script ) {
int error;
@@ -863,6 +775,14 @@ VALUE init_rack_app( VALUE script ) {
}
VALUE rack = rb_const_get(rb_cObject, rb_intern("Rack"));
#ifdef RUBY19
VALUE ret = rb_protect(uwsgi_rack_patch_body_proxy, rack, &error);
if (!error && ret != Qnil) {
uwsgi_log("Rack::BodyProxy successfully patched for ruby 1.9.x\n");
}
#endif
VALUE rackup = rb_funcall( rb_const_get(rack, rb_intern("Builder")), rb_intern("parse_file"), 1, script);
if (TYPE(rackup) != T_ARRAY) {
uwsgi_log("unable to parse %s file\n", RSTRING_PTR(script));
@@ -920,6 +840,105 @@ int uwsgi_rack_mount_app(char *mountpoint, char *app) {
}
*/
void uwsgi_rack_hijack(void) {
}
int uwsgi_rack_mule(char *opt) {
int error = 0;
if (uwsgi_endswith(opt, (char *)".rb")) {
rb_protect( uwsgi_require_file, rb_str_new2(opt), &error ) ;
if (error) {
uwsgi_ruby_exception();
return 0;
}
return 1;
}
return 0;
}
VALUE uwsgi_rb_pfh(VALUE args) {
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
if (rb_respond_to(uwsgi_rb_embedded, rb_intern("post_fork_hook"))) {
return rb_funcall(uwsgi_rb_embedded, rb_intern("post_fork_hook"), 0);
}
return Qnil;
}
void uwsgi_rb_post_fork() {
int error = 0;
// call the post_fork_hook
rb_protect(uwsgi_rb_pfh, 0, &error);
if (error) {
uwsgi_ruby_exception();
}
}
VALUE uwsgi_rb_mmh(VALUE args) {
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
return rb_funcall(uwsgi_rb_embedded, rb_intern("mule_msg_hook"), 1, args);
}
int uwsgi_rack_mule_msg(char *message, size_t len) {
int error = 0;
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
if (rb_respond_to(uwsgi_rb_embedded, rb_intern("mule_msg_hook"))) {
VALUE arg = rb_str_new(message, len);
rb_protect(uwsgi_rb_mmh, arg, &error);
if (error) {
uwsgi_ruby_exception();
}
return 1;
}
return 0;
}
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);
rb_gc();
return -1;
}
// free resources (useless ?)
rb_gc_unregister_address(&args);
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&rbsig);
rb_gc();
return 0;
}
struct uwsgi_plugin rack_plugin = {
.name = "rack",
@@ -932,12 +951,19 @@ struct uwsgi_plugin rack_plugin = {
.signal_handler = uwsgi_rack_signal_handler,
.hijack_worker = uwsgi_rack_hijack,
.post_fork = uwsgi_rb_post_fork,
.init_apps = uwsgi_rack_init_apps,
//.mount_app = uwsgi_rack_mount_app,
.manage_xml = uwsgi_rack_xml,
.magic = uwsgi_rack_magic,
.mule = uwsgi_rack_mule,
.mule_msg = uwsgi_rack_mule_msg,
.rpc = uwsgi_ruby_rpc,
.suspend = uwsgi_rack_suspend,
.resume = uwsgi_rack_resume,
};
+13 -1
View File
@@ -6,6 +6,8 @@
#define LONG_ARGS_RAILS LONG_ARGS_RACK_BASE + 1
#define LONG_ARGS_RUBY_GC_FREQ LONG_ARGS_RACK_BASE + 2
#define LONG_ARGS_RACK LONG_ARGS_RACK_BASE + 3
#define LONG_ARGS_RUBY_SHELL LONG_ARGS_RACK_BASE + 4
#define LONG_ARGS_RUBY_REQUIRE LONG_ARGS_RACK_BASE + 5
#ifndef RUBY19
#define rb_errinfo() ruby_errinfo
@@ -51,14 +53,24 @@ struct uwsgi_rack {
uint64_t cycles;
int call_gc;
// why why why !!!!????!!!???
VALUE signals_protector;
VALUE rpc_protector;
VALUE dispatcher;
VALUE rb_uwsgi_io_class;
ID call;
VALUE fibers[200];
int unprotected;
pthread_mutex_t gvl;
int rb_shell;
int app_id;
struct uwsgi_string_list *rbrequire;
};
void uwsgi_ruby_exception(void);
void uwsgi_rack_init_api(void);
+22 -18
View File
@@ -7,33 +7,37 @@ try:
except:
RUBYPATH = 'ruby'
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
rbconfig = 'Config'
version = os.popen(RUBYPATH + " -e \"print RUBY_VERSION\"").read().rstrip()
v = version.split('.')
GCC_LIST = ['rack_plugin']
GCC_LIST = ['rack_plugin', 'rack_api']
if v[0] == '1' and v[1] == '9':
CFLAGS.append('-DRUBY19')
CFLAGS.append('-Wno-unused-parameter')
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
if includedir == 'nil':
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
CFLAGS.append('-I' + includedir)
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-DRUBY19')
CFLAGS.append('-Wno-unused-parameter')
rbconfig = 'RbConfig'
else:
CFLAGS.append('-I' + includedir)
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['arch']\"").read().rstrip()
CFLAGS.append('-I' + archdir)
CFLAGS.append('-I' + archdir + '/' + arch)
CFLAGS.append('-I' + includedir + '/' + arch)
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['CFLAGS']\"" % rbconfig).read().rstrip().split()
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['LDFLAGS']\"").read().rstrip().split()
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyhdrdir']\"" % rbconfig).read().rstrip()
if includedir == 'nil':
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + includedir)
else:
CFLAGS.append('-I' + includedir)
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + archdir)
CFLAGS.append('-I' + archdir + '/' + arch)
CFLAGS.append('-I' + includedir + '/' + arch)
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['libdir']\"").read().rstrip()
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LDFLAGS']\"" % rbconfig).read().rstrip().split()
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['libdir']\"" % rbconfig).read().rstrip()
LDFLAGS.append('-L' + libpath )
os.environ['LD_RUN_PATH'] = libpath
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + Config::CONFIG['RUBY_SO_NAME']\"").read().rstrip().split()
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + %s::CONFIG['RUBY_SO_NAME']\"" % rbconfig).read().rstrip().split()
+196
View File
@@ -0,0 +1,196 @@
#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
#define RRDTOOL_OPT_RRDTOOL_FREQ RRDTOOL_OPT_BASE+3
struct uwsgi_rrdtool {
void *lib;
int (*create)(int, char **);
int (*update)(int, char **);
struct uwsgi_string_list *rrd;
int max_ds;
int freq;
char *update_area;
} u_rrd;
struct option rrdtool_options[] = {
{"rrdtool", required_argument, 0, RRDTOOL_OPT_RRDTOOL},
{"rrdtool-freq", required_argument, 0, RRDTOOL_OPT_RRDTOOL_FREQ},
{"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_initial("*** 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;
case RRDTOOL_OPT_RRDTOOL_FREQ:
u_rrd.freq = 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';
if (u_rrd.freq < 1) u_rrd.freq = 300;
}
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
if (uwsgi.current_time - last_update >= u_rrd.freq) {
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']
+28 -19
View File
@@ -3,34 +3,43 @@ import os,sys
NAME='ruby19'
try:
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
except:
RUBYPATH = 'ruby'
RUBYPATH = 'ruby'
GCC_LIST = ['../rack/rack_plugin']
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
rbconfig = 'Config'
version = os.popen(RUBYPATH + " -e \"print RUBY_VERSION\"").read().rstrip()
v = version.split('.')
if v[0] == '1' and v[1] == '9':
CFLAGS.append('-DRUBY19')
GCC_LIST = ['../rack/rack_plugin', '../rack/rack_api']
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
if includedir == 'nil':
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
CFLAGS.append('-I' + includedir)
if v[0] == '1' and v[1] == '9':
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-DRUBY19')
CFLAGS.append('-Wno-unused-parameter')
rbconfig = 'RbConfig'
else:
CFLAGS.append('-I' + includedir)
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['arch']\"").read().rstrip()
CFLAGS.append('-I' + archdir)
CFLAGS.append('-I' + archdir + '/' + arch)
CFLAGS.append('-I' + includedir + '/' + arch)
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['CFLAGS']\"" % rbconfig).read().rstrip().split()
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyhdrdir']\"" % rbconfig).read().rstrip()
if includedir == 'nil':
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + includedir)
else:
CFLAGS.append('-I' + includedir)
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + archdir)
CFLAGS.append('-I' + archdir + '/' + arch)
CFLAGS.append('-I' + includedir + '/' + arch)
CFLAGS.append('-Drack_plugin=ruby19_plugin')
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['LDFLAGS']\"").read().rstrip().split()
LDFLAGS.append('-L' + os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['libdir']\"").read().rstrip() )
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + Config::CONFIG['RUBY_SO_NAME']\"").read().rstrip().split()
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LDFLAGS']\"" % rbconfig).read().rstrip().split()
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['libdir']\"" % rbconfig).read().rstrip()
LDFLAGS.append('-L' + libpath )
os.environ['LD_RUN_PATH'] = libpath
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + %s::CONFIG['RUBY_SO_NAME']\"" % rbconfig).read().rstrip().split()
+32
View File
@@ -0,0 +1,32 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
/* request 110 */
int uwsgi_request_signal(struct wsgi_request *wsgi_req) {
ssize_t len;
uint8_t ret_status = 1;
if (uwsgi_signal_send(uwsgi.signal_socket, wsgi_req->uh.modifier2) < 0) {
ret_status = 0;
}
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = ret_status;
len = write(wsgi_req->poll.fd, wsgi_req, 4);
if (len != 4) {
uwsgi_error("write()");
}
return UWSGI_OK;
}
struct uwsgi_plugin signal_plugin = {
.name = "signal",
.modifier1 = 110,
.request = uwsgi_request_signal,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='signal'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['signal_plugin']
+43 -8
View File
@@ -46,6 +46,12 @@ static uint16_t http_add_uwsgi_header(struct wsgi_request *wsgi_req, char *hh, i
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;
@@ -100,6 +106,8 @@ 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 == ' ') {
@@ -116,9 +124,19 @@ 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);
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->path_info_len = 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 == ' ') {
@@ -127,9 +145,19 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
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);
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
wsgi_req->path_info_len = 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 {
@@ -161,7 +189,10 @@ 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);
@@ -261,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;
}
+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;
}
+187 -43
View File
@@ -123,16 +123,21 @@ time_t parse_http_date(char *date, uint16_t len) {
}
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char *message, uint16_t message_size) {
int fd;
struct sockaddr_in udp_addr;
char *udp_port;
ssize_t ret;
char udpbuff[1024];
if (message_size + 4 > 1024)
return -1;
struct uwsgi_header *uh;
if (message) {
uh = (struct uwsgi_header *) message;
}
else {
uh = (struct uwsgi_header *) uwsgi_malloc(4);
}
udp_port = strchr(host, ':');
if (udp_port == NULL) {
@@ -152,22 +157,15 @@ ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t
udp_addr.sin_port = htons(atoi(udp_port+1));
udp_addr.sin_addr.s_addr = inet_addr(host);
udpbuff[0] = modifier1;
uh->modifier1 = modifier1;
#ifdef __BIG_ENDIAN__
message_size = uwsgi_swap16(message_size);
uh->pktsize = uwsgi_swap16(message_size);
#else
uh->pktsize = message_size;
#endif
uh->modifier2 = modifier2;
memcpy(udpbuff+1, &message_size, 2);
udpbuff[3] = 0;
#ifdef __BIG_ENDIAN__
message_size = uwsgi_swap16(message_size);
#endif
memcpy(udpbuff+4, message, message_size);
ret = sendto(fd, udpbuff, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
ret = sendto(fd, (char *) uh, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
if (ret < 0) {
uwsgi_error("sendto()");
}
@@ -175,6 +173,10 @@ ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t
udp_port[0] = ':';
if ((char *)uh != message) {
free(uh);
}
return ret;
}
@@ -280,7 +282,9 @@ ssize_t uwsgi_send_message(int fd, uint8_t modifier1, uint8_t modifier2, char *m
memcpy(CMSG_DATA(cmsg), &pfd, sizeof(int));
#ifdef UWSGI_DEBUG
uwsgi_log("passing fd\n");
#endif
cnt = sendmsg(fd, &msg, 0);
}
else {
@@ -340,6 +344,58 @@ ssize_t uwsgi_send_message(int fd, uint8_t modifier1, uint8_t modifier2, char *m
return ret;
}
int uwsgi_read_response(int fd, struct uwsgi_header *uh, int timeout, char **buf) {
char *ptr = (char *) uh;
size_t remains = 4;
int ret = -1;
int rlen;
ssize_t len;
while(remains > 0) {
rlen = uwsgi_waitfd(fd, timeout);
if (rlen > 0) {
len = read(fd, ptr, remains);
if (len <= 0) break;
remains -= len;
ptr += len;
if (remains == 0) {
ret = uh->modifier2;
break;
}
continue;
}
// timed out ?
else if (ret == 0) ret = -2;
break;
}
if (buf && uh->pktsize > 0) {
*buf = uwsgi_malloc(uh->pktsize);
remains = uh->pktsize;
ptr = *buf;
ret = -1;
while(remains > 0) {
rlen = uwsgi_waitfd(fd, timeout);
if (rlen > 0) {
len = read(fd, ptr, remains);
if (len <= 0) break;
remains -= len;
ptr += len;
if (remains == 0) {
ret = uh->modifier2;
break;
}
continue;
}
// timed out ?
else if (ret == 0) ret = -2;
break;
}
}
return ret;
}
int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
int rlen;
@@ -355,7 +411,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 +422,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;
}
@@ -400,7 +459,9 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
if (ptrbuf + strsize <= bufferend) {
// item
argv[*argc] = uwsgi_cheap_string(ptrbuf, strsize);
#ifdef UWSGI_DEBUG
uwsgi_log("arg %s\n", argv[*argc]);
#endif
ptrbuf += strsize;
*argc = *argc + 1;
}
@@ -493,10 +554,11 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
char *ptrbuf, *bufferend;
uint16_t strsize = 0;
struct uwsgi_dyn_dict *udd;
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;
@@ -508,6 +570,8 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
return i;
}
wsgi_req->path_info_pos = -1;
while (ptrbuf < bufferend) {
if (ptrbuf + 2 < bufferend) {
memcpy(&strsize, ptrbuf, 2);
@@ -546,7 +610,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
@@ -567,7 +631,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;
}
@@ -652,6 +716,10 @@ 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;
@@ -749,7 +817,7 @@ next:
}
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;
@@ -760,12 +828,15 @@ next:
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) {
@@ -779,8 +850,8 @@ next:
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
@@ -791,25 +862,46 @@ next:
}
// check if a file named uwsgi.check_static+env['PATH_INFO'] exists
if (uwsgi.check_static && wsgi_req->path_info_len > 1) {
if (!uwsgi_file_serve(wsgi_req, uwsgi.check_static, uwsgi.check_static_len, wsgi_req->path_info, wsgi_req->path_info_len, uwsgi.check_static, uwsgi.check_static_len)) {
return -1;
if (wsgi_req->path_info_len > 1) {
udd = uwsgi.check_static;
while(udd) {
// need to build the path ?
if (udd->value == NULL) {
udd->value = realpath(udd->key, NULL);
if (!udd->value) goto nextcs;
udd->vallen = strlen(udd->value);
}
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len)) {
return -1;
}
nextcs:
udd = udd->next;
}
}
// check static-map
struct uwsgi_static_map *usm = uwsgi.static_maps;
while(usm) {
udd = uwsgi.static_maps;
while(udd) {
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, usm->mountpoint_len, usm->mountpoint);
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, udd->keylen, udd->key);
#endif
if (udd->status == 0) {
char *real_docroot = realpath(udd->value, NULL);
if (!real_docroot) goto nextsm;
udd->value = real_docroot;
udd->vallen = strlen(udd->value);
udd->status = 1;
}
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, usm->mountpoint, usm->mountpoint_len)) {
if (!uwsgi_file_serve(wsgi_req, usm->document_root, usm->document_root_len, wsgi_req->path_info+usm->mountpoint_len, wsgi_req->path_info_len-usm->mountpoint_len, usm->orig_document_root, usm->orig_document_root_len)) {
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info+udd->keylen, wsgi_req->path_info_len-udd->keylen)) {
return -1;
}
}
usm = usm->next;
nextsm:
udd = udd->next;
}
return 0;
@@ -1324,8 +1416,50 @@ 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 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) {
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) {
struct stat st;
char real_filename[PATH_MAX];
@@ -1348,6 +1482,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) {
@@ -1380,14 +1516,22 @@ 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] != '/') {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, document_root, document_root_len);
if (document_root[document_root_len-1] != '/') {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "/", 1);
}
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, path_info, path_info_len);
@@ -1396,10 +1540,10 @@ 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] != '/') {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, document_root, document_root_len);
if (document_root[document_root_len-1] != '/') {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "/", 1);
}
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, path_info, path_info_len);
@@ -1408,7 +1552,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)
+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;
+32 -10
View File
@@ -6,8 +6,15 @@ 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'):
@@ -34,30 +41,44 @@ def patch_bin_path(cmd, conf):
class uWSGIBuilder(build_ext):
def run(self):
conf = uc.uConf(get_profile())
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(get_profile())
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',
@@ -65,6 +86,7 @@ setup(name='uWSGI',
author_email='info@unbit.it',
url='http://projects.unbit.it/uwsgi/',
license='GPL2',
py_modules = ['uwsgidecorators'],
distclass = uWSGIDistribution,
)
+309 -12
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) {
@@ -36,8 +84,13 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
strcpy(use->receiver, receiver);
use->handler = handler;
use->modifier1 = modifier1;
uwsgi_log("registered signal %d\n", sig);
if (use->receiver[0] == 0) {
uwsgi_log("[uwsgi-signal] signum %d registered (modifier1: %d target: default, any worker)\n", sig, modifier1);
}
else {
uwsgi_log("[uwsgi-signal] signum %d registered (modifier1: %d target: %s)\n", sig, modifier1, receiver);
}
uwsgi_unlock(uwsgi.signal_table_lock);
@@ -75,6 +128,87 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
}
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func)(int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_up = *up, *old_up;
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while(uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
return uwsgi_up;
}
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
uwsgi_lock(uwsgi.probe_table_lock);
if (ushared->probes_cnt < MAX_PROBES) {
struct uwsgi_probe *up = uwsgi.probes;
while(up) {
if (!strcmp(up->name, kind)) {
break;
}
up = up->next;
}
if (!up) {
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024-1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
ushared->probes[ushared->probes_cnt].fd = -1;
ushared->probes[ushared->probes_cnt].state = 0;
ushared->probes[ushared->probes_cnt].last_event = 0;
ushared->probes[ushared->probes_cnt].data = NULL;
ushared->probes[ushared->probes_cnt].cycles = 0;
ushared->probes[ushared->probes_cnt].bad = 0;
if (!timeout) {
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
ushared->probes[ushared->probes_cnt].timeout = timeout;
if (!freq) {
freq = 1;
}
ushared->probes[ushared->probes_cnt].freq = freq;
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.probe_table_lock);
return 0;
}
int uwsgi_add_timer(uint8_t sig, int secs) {
uwsgi_lock(uwsgi.timer_table_lock);
@@ -150,24 +284,92 @@ int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
}
void create_signal_pipe(int *sigpipe) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sigpipe)) {
uwsgi_error("socketpair()\n");
exit(1);
}
uwsgi_socket_nb(sigpipe[0]);
uwsgi_socket_nb(sigpipe[1]);
if (uwsgi.signal_bufsize) {
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
}
}
int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
struct uwsgi_header uh;
uh.modifier1 = 110;
uh.pktsize = 0;
uh.modifier2 = sig;
int fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) return -1;
if (write(fd, (char *) &uh, 4) != 4) {
uwsgi_error("uwsgi_remote_signal_send()");
close(fd);
return -1;
}
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL);
close(fd);
return ret;
}
int uwsgi_signal_send(int fd, uint8_t sig) {
socklen_t so_bufsize_len = sizeof(int);
int so_bufsize = 0;
if (write(fd, &sig, 1) != 1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** SIGNAL QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
}
else {
uwsgi_error("uwsgi_signal_send()");
}
return -1;
}
return 0;
}
void uwsgi_route_signal(uint8_t sig) {
int i;
struct uwsgi_signal_entry *use = &ushared->signal_table[sig];
int i;
// send to first available worker
if (use->receiver[0] == 0 || !strcmp(use->receiver, "worker") || !strcmp(use->receiver, "worker0")) {
if (write(ushared->worker_signal_pipe[0], &sig, 1) != 1) {
uwsgi_error("write()");
if (uwsgi_signal_send(ushared->worker_signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to workers pool\n", 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) {
uwsgi_error("write()");
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
}
@@ -178,8 +380,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) {
uwsgi_error("write()");
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
}
@@ -187,16 +388,112 @@ 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) {
uwsgi_error("write()");
if (uwsgi_signal_send(ushared->spooler_signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to the spooler\n", sig);
}
}
}
#endif
else if (!strcmp(use->receiver, "mules")) {
for(i=0;i<uwsgi.mules_cnt;i++) {
if (uwsgi_signal_send(uwsgi.mules[i].signal_pipe[0], sig)) {
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 (uwsgi_signal_send(ushared->mule_signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to a mule\n", sig);
}
}
else {
if (uwsgi_signal_send(uwsgi.mules[i-1].signal_pipe[0], sig)) {
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 (uwsgi_signal_send(uf->signal_pipe[0], sig)) {
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 (uwsgi_signal_send(uwsgi.farms[i-1].signal_pipe[0], sig)) {
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);
}
}
uint8_t uwsgi_signal_wait(int signum) {
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
uint8_t received_signal;
int ret;
struct pollfd pfd[2];
if (signum > -1) {
wait_for_specific_signal = 1;
}
pfd[0].fd = uwsgi.signal_socket;
pfd[0].events = POLLIN;
pfd[1].fd = uwsgi.my_signal_socket;
pfd[1].events = POLLIN;
cycle:
ret = poll(pfd, 2, -1);
if (ret > 0) {
if (pfd[0].revents == POLLIN) {
if (read(uwsgi.signal_socket, &received_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void)uwsgi_signal_handler(received_signal);
if (wait_for_specific_signal) {
if (received_signal != uwsgi_signal) goto cycle;
}
}
}
if (pfd[1].revents == POLLIN) {
if (read(uwsgi.my_signal_socket, &received_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void)uwsgi_signal_handler(received_signal);
if (wait_for_specific_signal) {
if (received_signal != uwsgi_signal) goto cycle;
}
}
}
}
return received_signal;
}
+58 -2
View File
@@ -412,7 +412,7 @@ char *generate_socket_name(char *socket_name) {
if (!strncmp(socket_name, new_addr, strlen(socket_name))) {
asterisk[0] = '*';
new_socket = uwsgi_concat3(new_addr, ":", tcp_port + 1);
uwsgi_log("found %s for %s on interface %s\n", new_socket, socket_name, ifa->ifa_name);
uwsgi_log("[uwsgi-autoip] found %s for %s on interface %s\n", new_socket, socket_name, ifa->ifa_name);
freeifaddrs(ifap);
return new_socket;
}
@@ -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;
@@ -971,3 +1014,16 @@ void uwsgi_del_sockets_from_queue(int queue) {
}
int uwsgi_is_bad_connection(int fd) {
int soopt = 0;
socklen_t solen = sizeof(int) ;
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
return -1;
}
// will be 0 if all ok
return soopt;
}
+33 -25
View File
@@ -16,18 +16,7 @@ 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);
@@ -36,23 +25,21 @@ pid_t spooler_start() {
// USR1 will be used to wake up the spooler
signal(SIGUSR1, spooler_wakeup);
uwsgi.mywid = -1;
uwsgi.mypid = pid;
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();
@@ -64,12 +51,10 @@ pid_t spooler_start() {
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);
}
@@ -251,6 +236,8 @@ void spooler() {
if (uwsgi.spooler_ordered) {
#ifdef __linux__
spooler_scandir(uwsgi.spool_dir);
#else
spooler_readdir(uwsgi.spool_dir);
#endif
}
else {
@@ -362,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;
@@ -411,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);
}
@@ -428,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");
}
}
}
+383
View File
@@ -0,0 +1,383 @@
#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.
To avoid removal of already using nodes, a reference count system has been implemented
*/
extern struct uwsgi_server uwsgi;
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++;
time_t current = time(NULL);
struct uwsgi_subscribe_node *node = current_slot->nodes;
while(node) {
// is the node alive ?
if (current - node->last_check > uwsgi.subscription_tolerance) {
if (node->death_mark == 0)
uwsgi_log("[uwsgi-subscription] %.*s => marking %.*s as failed (no announce received in %d seconds)\n", (int) keylen, key, (int) node->len, node->name, uwsgi.subscription_tolerance);
node->death_mark = 1;
}
if (node->death_mark && node->reference == 0) {
// remove the node and move to next
struct uwsgi_subscribe_node *dead_node = node;
node = node->next;
// if the slot has been removed, return NULL;
if (uwsgi_remove_subscribe_node(slot, dead_node) == 1) {
return NULL;
}
continue;
}
if (rr_pos == current_slot->rr) {
current_slot->rr++;
node->reference++;
return node;
}
node = node->next;
rr_pos++;
}
current_slot->rr = 0;
if (current_slot->nodes) {
current_slot->nodes->reference++;
}
return current_slot->nodes;
}
return NULL;
}
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, char *val, uint16_t vallen, int regexp) {
if (keylen > 0xff) return NULL;
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen, regexp);
if (current_slot) {
struct uwsgi_subscribe_node *node = current_slot->nodes;
while(node) {
if (!uwsgi_strncmp(val, vallen, node->name, node->len)) {
return node;
}
node = node->next;
}
}
return NULL;
}
int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_node *node) {
int ret = 0;
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
ret = 1;
free(node_slot);
// am i the only slot ?
if (!prev_slot && !next_slot) {
*slot = NULL;
}
}
return ret;
}
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)) {
// remove death mark
node->death_mark = 0;
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->reference = 0;
node->death_mark = 0;
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->reference = 0;
current_slot->nodes->death_mark = 0;
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;
}
}
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, char *modifier1, size_t modifier1_len, uint8_t cmd) {
size_t ssb_size = 4 + (2 + 3) + (2 + keysize) + (2 + 7) + (2 + strlen(uwsgi.sockets->name));
if (modifier1) {
ssb_size += (2 + 9) + (2 + modifier1_len);
}
char *subscrbuf = uwsgi_malloc(ssb_size);
// leave space for uwsgi header
char *ssb = subscrbuf+4;
// key = "domain"
uint16_t ustrlen = 3;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "key", ustrlen);
ssb+=ustrlen;
ustrlen = keysize;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, key, ustrlen);
ssb+=ustrlen;
// address = "first uwsgi socket"
ustrlen = 7;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "address", ustrlen);
ssb+=ustrlen;
ustrlen = strlen(uwsgi.sockets->name);
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, uwsgi.sockets->name, ustrlen);
ssb+=ustrlen;
// modifier1 = "modifier1"
if (modifier1) {
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "modifier1", ustrlen);
ssb+=ustrlen;
ustrlen = modifier1_len;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, modifier1, ustrlen);
ssb+=ustrlen;
}
send_udp_message(224, cmd, udp_address, subscrbuf, ssb_size-4);
}
+24 -1
View File
@@ -1,17 +1,39 @@
import gevent
import gevent.socket
import sys
import uwsgi
from uwsgidecorators import *
if 'gettotalrefcount' in sys.__dict__:
REFCNT = True
else:
REFCNT = False
@signal(17)
def hello(signum):
print "hello i am signal %d, i am here because the background job is finished" % signum
if REFCNT:
print sys.gettotalrefcount()
@timer(10)
def ten_seconds(signum):
print "10 seconds elapsed, signal %d raised" % signum
if REFCNT:
print sys.gettotalrefcount()
@filemon('/tmp')
def tmp_modified(signum):
print "/tmp has been touched, i am the greenlet %s running on worker %d" % (gevent.getcurrent(), uwsgi.worker_id())
if REFCNT:
print sys.gettotalrefcount()
def bg_task():
for i in range(1,10):
print "background task", i
gevent.sleep(2)
gevent.sleep(1)
# task ended raise a signal !!!
uwsgi.signal(17)
def long_task():
for i in range(1,10):
@@ -43,6 +65,7 @@ def application(e, sr):
if REFCNT:
print sys.gettotalrefcount()
yield "%d" % sys.gettotalrefcount()
# this task will goes on after request end
gevent.spawn(bg_task)
+5
View File
@@ -0,0 +1,5 @@
import uwsgi
print(uwsgi.opt)
print(uwsgi.magic_table)
from werkzeug.testapp import test_app as application
+48 -2
View File
@@ -1,5 +1,19 @@
import uuid
import uwsgi
import os
def application(env, start_response):
if env['PATH_INFO'].startswith('/progress/'):
start_response('200 Ok', [('Content-type', 'application/json')])
filename = 'foobar/' + env['PATH_INFO'][10:]
print filename
if os.path.exists(filename):
return uwsgi.sendfile(filename)
else:
return "{ 'state': 'done' }"
if env['REQUEST_METHOD'] == 'POST':
start_response('200 Ok', [('Content-type', 'text/plain')])
@@ -14,12 +28,44 @@ def application(env, start_response):
return body
else:
start_response('200 Ok', [('Content-type', 'text/html')])
x_progress_id = str(uuid.uuid4())
return """
<form method="POST" enctype="multipart/form-data">
<html>
<head>
<script src="/static/jquery-1.5.1.min.js" /></script>
<script language="Javascript">
var interval;
function redrawProgressBar() {
interval = setInterval(getData, 1000);
}
function getData() {
var jsr = $.getJSON("/progress/%s.js",
function(data) {
if (data) {
if (data.state == 'uploading') {
$('#progress').html(data.received + '/' + data.size);
return;
}
}
alert("fine");
clearInterval(interval);
}
);
jsr.error(function() { clearInterval(interval); });
}
</script>
</head>
<body>
upload progress: <div id="progress"> 0%%</div>
<form method="POST" enctype="multipart/form-data" action="?X-Progress-ID=%s" onsubmit="redrawProgressBar(); return true;">
<textarea name="pluto">
</textarea>
<input type="file" name="pippo" />
<input type="submit" value="invia" />
</form>
"""
</body>
</html>
""" % (x_progress_id, x_progress_id)
+920 -209
View File
File diff suppressed because it is too large Load Diff
+802 -593
View File
File diff suppressed because it is too large Load Diff
+451 -82
View File
@@ -8,9 +8,14 @@ extern "C" {
#define UMAX16 65536
#define UMAX64_STR "18446744073709551616"
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_log_initial if (!uwsgi.no_initial_output) uwsgi_log
#define uwsgi_fatal_error(x) uwsgi_error(x); exit(1);
#define uwsgi_error_open(x) uwsgi_log("open(\"%s\"): %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_req_error(x) if (wsgi_req->uri_len > 0 && wsgi_req->method_len > 0 && wsgi_req->remote_addr_len > 0) uwsgi_log_verbose("%s: %s [%s line %d] during %.*s %.*s (%.*s)\n", x, strerror(errno), __FILE__, __LINE__,\
wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr); else uwsgi_log_verbose("%s %s [%s line %d] \n",x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_debug(x, ...) uwsgi_log("[uWSGI DEBUG] " x, __VA_ARGS__);
#define uwsgi_rawlog(x) if (write(2, x, strlen(x)) != strlen(x)) uwsgi_error("write()")
#define uwsgi_str(x) uwsgi_concat2(x, "")
@@ -26,14 +31,16 @@ extern "C" {
#define thunder_lock if (uwsgi.threads > 1) {pthread_mutex_lock(&uwsgi.thunder_mutex);}
#define thunder_unlock if (uwsgi.threads > 1) {pthread_mutex_unlock(&uwsgi.thunder_mutex);}
#define uwsgi_check_scheme(file) (!uwsgi_startswith(file, "http://", 7) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6) || !uwsgi_startswith(file, "fd://", 5))
#define ushared uwsgi.shared
#define MAX_APPS 64
#define MAX_GENERIC_PLUGINS 64
#define MAX_RPC 64
#define MAX_GATEWAYS 64
#define MAX_DAEMONS 8
#define MAX_SUBSCRIPTIONS 8
#define MAX_TIMERS 64
#define MAX_PROBES 64
#define MAX_CRONS 64
#ifndef UWSGI_LOAD_EMBEDDED_PLUGINS
@@ -112,6 +119,9 @@ extern char UWSGI_EMBED_CONFIG_END;
#include <stdarg.h>
#include <errno.h>
#ifndef __USE_ISOC99
#define __USE_ISOC99
#endif
#include <ctype.h>
#include <sys/time.h>
#include <unistd.h>
@@ -145,10 +155,10 @@ extern char UWSGI_EMBED_CONFIG_END;
#include <sys/reg.h>
#endif
extern int pivot_root(const char *new_root, const char *put_old);
#else
#include <limits.h>
#endif
#include <limits.h>
#include <dirent.h>
#ifdef UWSGI_SCTP
@@ -222,6 +232,10 @@ extern int pivot_root(const char *new_root, const char *put_old);
#include <sys/event.h>
#endif
#ifdef UWSGI_CAP
#include <sys/capability.h>
#endif
#ifdef __HAIKU__
#include <kernel/OS.h>
#endif
@@ -260,27 +274,28 @@ struct uwsgi_config_template {
struct uwsgi_config_template *next;
};
struct uwsgi_static_map {
char *mountpoint;
int mountpoint_len;
char *document_root;
int document_root_len;
char *orig_document_root;
int orig_document_root_len;
struct uwsgi_static_map *next;
};
struct uwsgi_string_list {
char *value;
size_t len;
uint64_t custom;
struct uwsgi_string_list *next;
};
struct uwsgi_dyn_dict {
char *key;
int keylen;
char *value;
int vallen;
uint64_t hits;
int status;
struct uwsgi_dyn_dict *prev;
struct uwsgi_dyn_dict *next;
};
union uwsgi_sockaddr {
struct sockaddr sa;
@@ -312,8 +327,8 @@ struct uwsgi_gateway {
// Daemons are external processes maintained by the master
struct uwsgi_daemon {
char command[0xff];
char tmp_command[0xff];
char *command;
char *tmp_command;
pid_t pid;
uint64_t respawns;
time_t born;
@@ -321,6 +336,8 @@ struct uwsgi_daemon {
int status;
int registered;
//int pipe[2];
struct uwsgi_daemon *next;
};
struct uwsgi_queue_header {
@@ -486,6 +503,38 @@ struct uwsgi_opt {
#define LONG_ARGS_FASTCGI_SOCKET 17133
#define LONG_ARGS_THREADS_STACKSIZE 17134
#define LONG_ARGS_EMPEROR_THROTTLE 17135
#define LONG_ARGS_STOP 17136
#define LONG_ARGS_RELOAD 17137
#define LONG_ARGS_REGEXP_MOUNT 17138
#define LONG_ARGS_MIMEFILE 17139
#define LONG_ARGS_CHEAPER 17140
#define LONG_ARGS_CAP 17141
#define LONG_ARGS_STATS 17142
#define LONG_ARGS_MULE 17143
#define LONG_ARGS_LOG_MAXSIZE 17144
#define LONG_ARGS_LOG_BACKUPNAME 17145
#define LONG_ARGS_EVIL_RELOAD_ON_AS 17146
#define LONG_ARGS_EVIL_RELOAD_ON_RSS 17147
#define LONG_ARGS_SPOOLER_HARAKIRI 17148
#define LONG_ARGS_MULE_HARAKIRI 17149
#define LONG_ARGS_EMPEROR_STATS 17150
#define LONG_ARGS_SPOOLER_CHDIR 17151
#define LONG_ARGS_LOCKS 17152
#define LONG_ARGS_PROCNAME_PREFIX 17153
#define LONG_ARGS_PROCNAME_APPEND 17154
#define LONG_ARGS_PROCNAME 17155
#define LONG_ARGS_PROCNAME_MASTER 17156
#define LONG_ARGS_FARM 17157
#define LONG_ARGS_MULES 17158
#define LONG_ARGS_PROCNAME_PREFIX_SP 17159
#define LONG_ARGS_UMASK 17160
#define LONG_ARGS_PAUSE 17161
#define LONG_ARGS_SIGNAL_BUFSIZE 17162
#define LONG_ARGS_SIGNAL 17163
#define LONG_ARGS_KSM 17164
#define LONG_ARGS_LOGFILE_CHMOD 17165
#define LONG_ARGS_SUBSCRIBE_FREQ 17166
#define LONG_ARGS_SUBSCR_TOLERANCE 17167
#define UWSGI_OK 0
@@ -524,6 +573,8 @@ struct uwsgi_opt {
#define UWSGI_OPTION_LOG_SENDFILE 14
#define UWSGI_OPTION_BACKLOG_STATUS 15
#define UWSGI_OPTION_BACKLOG_ERRORS 16
#define UWSGI_OPTION_SPOOLER_HARAKIRI 17
#define UWSGI_OPTION_MULE_HARAKIRI 18
#define UWSGI_MODIFIER_ADMIN_REQUEST 10
#define UWSGI_MODIFIER_SPOOL_REQUEST 17
@@ -582,6 +633,8 @@ struct uwsgi_socket {
int disabled;
struct uwsgi_socket *next;
int shared;
int from_shared;
};
struct uwsgi_server;
@@ -605,7 +658,8 @@ struct uwsgi_plugin {
void (*init_apps) (void);
void (*fixup) (void);
void (*master_fixup) (int);
int (*mount_app) (char *, char *);
void (*master_cycle) (void);
int (*mount_app) (char *, char *, int);
int (*manage_udp) (char *, int, char *, int);
int (*manage_xml) (char *, char *);
void (*suspend) (struct wsgi_request *);
@@ -623,14 +677,23 @@ struct uwsgi_plugin {
int (*spooler) (char *, char *, uint16_t, char *, size_t);
uint16_t(*rpc) (void *, uint8_t, char **, char *);
uint16_t(*rpc) (void *, uint8_t, char **, char *);
void (*jail) (int (*)(void *), char **);
int (*mule)(char *);
int (*mule_msg)(char *, size_t);
struct uwsgi_help_item *help;
};
#ifdef UWSGI_PCRE
#include <pcre.h>
int uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra);
int uwsgi_regexp_match(pcre *pattern, pcre_extra *pattern_extra, char *subject, int length);
#endif
struct uwsgi_app {
@@ -639,6 +702,11 @@ struct uwsgi_app {
char *mountpoint;
int mountpoint_len;
#ifdef UWSGI_PCRE
pcre *pattern;
pcre_extra *pattern_extra;
#endif
void *interpreter;
void *callable;
@@ -673,6 +741,7 @@ struct uwsgi_app {
void *uwsgi_version;
void *uwsgi_node;
uint64_t avg_response_time;
};
@@ -763,6 +832,7 @@ struct wsgi_request {
char *path_info;
uint16_t path_info_len;
int path_info_pos;
char *script;
uint16_t script_len;
@@ -898,42 +968,112 @@ struct uwsgi_signal_rb_timer {
struct uwsgi_rb_timer *uwsgi_rb_timer;
};
struct uwsgi_signal_probe {
int (*func)(int, struct uwsgi_signal_probe *);
char args[1024];
int fd;
int state;
int bad;
int last_event;
void *data;
uint64_t cycles;
int timeout;
int freq;
int registered;
uint8_t sig;
};
struct uwsgi_probe {
char *name;
int (*func)(int, struct uwsgi_signal_probe *);
struct uwsgi_probe *next;
};
struct uwsgi_server {
// store the machine hostname
char hostname[256];
int hostname_len;
char **orig_argv;
char **argv;
int argc;
int max_procname;
int auto_procname;
char **environ;
char *procname_prefix;
char *procname_append;
char *procname_master;
char *procname;
// quiet startup
int no_initial_output;
// enable threads
int has_threads;
// default app id
int default_app;
char *logto2;
// autoload plugins
int autoload;
int snapshot;
// enable auto-snapshotting
int auto_snapshot;
pid_t restore_snapshot;
int respawn_workers;
unsigned int reloads;
// leave master running as root
int master_as_root;
// kill the stack on SIGTERM (instead of brutal reloading)
int die_on_term;
// disable fd passing on unix socket
int no_fd_passing;
// store the current time
time_t current_time;
uint64_t master_cycles;
int reuse_port;
// enable lazy mode
int lazy;
// enable cheap mode
int cheap;
// enable cheaper mode
int cheaper;
// minimal number of running workers in cheaper mode
int cheaper_count;
// enable idle mode
int idle;
// destroy the stack when idle
int die_on_idle;
// store the screen session
char *screen_session;
// true if run under the emperor
int has_emperor;
int emperor_fd;
int emperor_tyrant;
int emperor_fd_config;
int early_emperor;
int emperor_throttle;
@@ -941,50 +1081,77 @@ struct uwsgi_server {
pid_t emperor_pid;
int emperor_broodlord;
int emperor_broodlord_count;
char *emperor_stats;
int emperor_stats_fd;
struct uwsgi_config_template *vassals_templates;
// true if loyal to the emperor
int loyal;
// amqp support
char *emperor_amqp_vhost;
char *emperor_amqp_username;
char *emperor_amqp_password;
// emperor hook (still in development)
char *vassals_start_hook;
char *vassals_stop_hook;
struct uwsgi_string_list *additional_headers;
// maximum time to wait after a reload
time_t master_mercy;
// set cpu affinity
int cpu_affinity;
int reload_mercy;
// map reloads to death
int exit_on_reload;
// store options
int option_index;
struct option *long_options;
struct uwsgi_opt **exported_opts;
int exported_opts_cnt;
// dump the whole set of options
int dump_options;
// show ini representation of the current config
int show_config;
//base for all the requests(even on async mode)
struct wsgi_request **wsgi_requests;
struct wsgi_request *wsgi_req;
char *remap_modifier;
// enable zerg mode
int *zerg;
char *zerg_server;
int zerg_server_fd;
// security
char *chroot;
gid_t gid;
uid_t uid;
char *uidname;
char *gidname;
#ifdef UWSGI_CAP
cap_value_t *cap;
int cap_count;
#endif
// still working on it
char *profiler;
// mostly useless
char *mode;
// binary path the worker image
char *worker_exec;
// gateways
struct uwsgi_gateway gateways[MAX_GATEWAYS];
int gateways_cnt;
@@ -992,13 +1159,22 @@ struct uwsgi_server {
int ignore_script_name;
int manage_script_name;
int no_default_app;
int logdate;
int log_micros;
char *log_strftime;
int log_x_forwarded_for;
int honour_stdin;
// route all of the logs to the master process
int log_master;
int log_reopen;
int log_truncate;
off_t log_maxsize;
char *log_backupname;
int log_syslog;
int original_log_fd;
@@ -1007,15 +1183,25 @@ struct uwsgi_server {
union uwsgi_sockaddr *log_socket_addr;
socklen_t log_socket_size;
char *check_static;
size_t check_static_len;
int file_serve_mode;
struct uwsgi_static_map *static_maps;
// static file serving
int file_serve_mode;
int build_mime_dict;
char *mime_file;
struct uwsgi_probe *probes;
struct uwsgi_daemon *daemons;
int daemons_cnt;
struct uwsgi_dyn_dict *static_maps;
struct uwsgi_dyn_dict *check_static;
struct uwsgi_dyn_dict *mimetypes;
char *logfile;
int logfile_chown;
// enable vhost mode
int vhost;
int vhost_host;
@@ -1023,6 +1209,7 @@ struct uwsgi_server {
char **async_buf;
char **async_post_buf;
// async commodity
struct wsgi_request **async_waiting_fd_table;
struct wsgi_request **async_proto_fd_table;
struct uwsgi_async_request *async_runqueue;
@@ -1039,19 +1226,27 @@ struct uwsgi_server {
int **async_ovector;
#endif
// store rlimit
struct rlimit rl;
size_t limit_post;
// set process priority
int prio;
int reload_on_as;
int reload_on_rss;
char *touch_reload;
time_t last_touch_reload_mtime;
// funny reload systems
int force_get_memusage;
rlim_t reload_on_as;
rlim_t reload_on_rss;
rlim_t evil_reload_on_as;
rlim_t evil_reload_on_rss;
struct uwsgi_string_list *touch_reload;
int propagate_touch;
// enable grunt mode
int grunt;
// store the binary path
char *binary_path;
int is_a_reload;
@@ -1067,7 +1262,9 @@ struct uwsgi_server {
#ifdef UWSGI_SPOOLER
char *spool_dir;
char *spooler_chdir;
int spooler_ordered;
uint64_t spooler_respawned;
#endif
#ifdef UWSGI_SNMP
@@ -1084,7 +1281,9 @@ struct uwsgi_server {
int lazy_respawned;
int buffer_size;
int signal_bufsize;
// post buffering
int post_buffering;
int post_buffering_harakiri;
int post_buffering_bufsize;
@@ -1092,6 +1291,7 @@ struct uwsgi_server {
int master_process;
int master_queue;
// mainly iseful for broodlord mode
int vassal_sos_backlog;
int no_defer_accept;
@@ -1116,10 +1316,12 @@ struct uwsgi_server {
int max_vars;
int vec_size;
// shared area
char *sharedarea;
uint64_t sharedareasize;
#ifdef UWSGI_THREADING
// avoid thundering herd in threaded modes
pthread_mutex_t six_feet_under_lock;
#endif
@@ -1127,12 +1329,19 @@ struct uwsgi_server {
/* the list of workers */
struct uwsgi_worker *workers;
/* the dedicated signal_pipe */
int **signal_pipe;
/* the list of mules */
struct uwsgi_string_list *mules_patches;
struct uwsgi_mule *mules;
struct uwsgi_string_list *farms_list;
struct uwsgi_farm *farms;
pid_t mypid;
int mywid;
int muleid;
int mules_cnt;
int farms_cnt;
rlim_t max_fd;
struct timeval start_tv;
@@ -1145,6 +1354,7 @@ struct uwsgi_server {
int chmod_socket;
char *chown_socket;
mode_t chmod_socket_value;
mode_t chmod_logfile_value;
int listen_queue;
#ifdef UWSGI_XML
@@ -1172,7 +1382,7 @@ struct uwsgi_server {
#endif
#ifdef UWSGI_INI
char *ini;
struct uwsgi_string_list *ini;
#endif
#ifdef UWSGI_SQLITE3
@@ -1203,6 +1413,7 @@ struct uwsgi_server {
char *cwd;
// conditional logging
int log_slow_requests;
int log_zero_headers;
int log_empty_body;
@@ -1304,6 +1515,10 @@ struct uwsgi_server {
int cache_server_fd;
pthread_mutex_t cache_server_lock;
// the stats server
char *stats;
int stats_fd;
uint64_t queue_size;
uint64_t queue_blocksize;
void *queue;
@@ -1314,12 +1529,15 @@ struct uwsgi_server {
pthread_mutex_t thunder_mutex;
int locks;
void *cache_lock;
void *queue_lock;
void *user_lock;
void **user_lock;
void *signal_table_lock;
void *fmon_table_lock;
void *timer_table_lock;
void *probe_table_lock;
void *rb_timer_table_lock;
void *cron_table_lock;
void *rpc_table_lock;
@@ -1328,13 +1546,16 @@ struct uwsgi_server {
void *spooler_lock;
#endif
void *daemon_table_lock;
// subscription client
int subscribe_freq;
int subscription_tolerance;
struct uwsgi_string_list *subscriptions;
char *startup_daemons[MAX_DAEMONS];
int startup_daemons_cnt;
char *subscriptions[MAX_SUBSCRIPTIONS];
int subscriptions_cnt;
#ifdef __linux__
#ifdef MADV_MERGEABLE
int linux_ksm;
#endif
#endif
};
@@ -1433,6 +1654,7 @@ struct uwsgi_shared {
#ifdef UWSGI_SPOOLER
pid_t spooler_pid;
int spooler_frequency;
time_t spooler_harakiri;
#endif
#ifdef UWSGI_SNMP
@@ -1454,15 +1676,21 @@ struct uwsgi_shared {
#ifdef UWSGI_SPOOLER
int spooler_signal_pipe[2];
#endif
int mule_signal_pipe[2];
int mule_queue_pipe[2];
struct uwsgi_signal_entry signal_table[256];
struct uwsgi_fmon files_monitored[64];
int files_monitored_cnt;
struct uwsgi_timer timers[64];
struct uwsgi_signal_probe probes[MAX_PROBES];
int probes_cnt;
struct uwsgi_timer timers[MAX_TIMERS];
int timers_cnt;
struct uwsgi_signal_rb_timer rb_timers[64];
struct uwsgi_signal_rb_timer rb_timers[MAX_TIMERS];
int rb_timers_cnt;
struct uwsgi_rpc rpc_table[MAX_RPC];
@@ -1470,8 +1698,6 @@ struct uwsgi_shared {
int worker_log_pipe[2];
struct uwsgi_daemon daemons[MAX_DAEMONS];
int daemons_cnt;
#ifdef __linux__
struct tcp_info ti;
#endif
@@ -1517,6 +1743,7 @@ struct uwsgi_worker {
uint64_t respawn_count;
uint64_t requests;
uint64_t delta_requests;
uint64_t failed_requests;
time_t harakiri;
@@ -1524,8 +1751,7 @@ struct uwsgi_worker {
uint64_t vsz_size;
uint64_t rss_size;
double running_time;
double last_running_time;
uint64_t running_time;
int manage_next_request;
@@ -1536,9 +1762,65 @@ struct uwsgi_worker {
int apps_cnt;
struct uwsgi_app apps[MAX_APPS];
uint64_t tx;
int busy;
int cheaped;
int suspended;
int sig;
uint8_t signum;
// signals managed by this worker
uint64_t signals;
int signal_pipe[2];
uint64_t avg_response_time;
char name[0xff];
};
struct uwsgi_mule {
int id;
pid_t pid;
int signal_pipe[2];
int queue_pipe[2];
time_t last_spawn;
uint64_t respawn_count;
char *patch;
// signals managed by this mule
uint64_t signals;
int sig;
uint8_t signum;
time_t harakiri;
char name[0xff];
};
struct uwsgi_mule_farm {
struct uwsgi_mule *mule;
struct uwsgi_mule_farm *next;
};
struct uwsgi_farm {
int id;
char name[0xff];
int signal_pipe[2];
int queue_pipe[2];
struct uwsgi_mule_farm *mules;
};
char *uwsgi_get_cwd(void);
void warn_pipe(void);
@@ -1565,7 +1847,7 @@ void daemonize(char *);
void logto(char *);
void log_request(struct wsgi_request *);
void get_memusage(void);
void get_memusage(uint64_t *, uint64_t *);
void harakiri(void);
void stats(int);
@@ -1588,6 +1870,8 @@ pid_t spooler_start(void);
#endif
void set_harakiri(int);
void set_mule_harakiri(int);
void set_spooler_harakiri(int);
void inc_harakiri(int);
#ifdef __BIG_ENDIAN__
@@ -1597,7 +1881,7 @@ uint64_t uwsgi_swap64(uint64_t);
#endif
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t, char *, char *, uint16_t);
ssize_t send_udp_message(uint8_t, uint8_t, char *, char *, uint16_t);
#endif
int uwsgi_parse_packet(struct wsgi_request *, int);
@@ -1706,7 +1990,7 @@ char *uwsgi_concat4n(char *, int, char *, int, char *, int, char *, int);
int uwsgi_get_app_id(char *, int, int);
char *uwsgi_strncopy(char *, int);
void master_loop(char **, char **);
int master_loop(char **, char **);
int find_worker_id(pid_t);
@@ -1851,7 +2135,6 @@ ssize_t fcgi_send_record(int, uint8_t, uint16_t, char *);
ssize_t fcgi_send_param(int, char *, uint16_t, char *, uint16_t);
uint16_t fcgi_get_record(int, char *);
int uwsgi_attach_daemon(char *);
void spawn_daemon(struct uwsgi_daemon *);
void emperor_loop(void);
@@ -1908,33 +2191,12 @@ struct uwsgi_dict {
void *data;
void *lock;
uint64_t count;
struct uwsgi_dict_item *items;
};
#define SUBSCRIBER_PAGESIZE 4096
#define SUBSCRIBER_NODES (SUBSCRIBER_PAGESIZE/128)-4
struct uwsgi_subscriber_name {
uint16_t len;
char name[128];
uint8_t modifier1;
uint8_t modifier2;
// total requests managed by this node
uint64_t requests;
// bytes transferred by this node
uint64_t transferred;
};
struct uwsgi_subscriber {
uint64_t nodes;
uint64_t current;
// support upto md5
char auth[32];
struct uwsgi_subscriber_name names[SUBSCRIBER_NODES];
};
struct uwsgi_subscribe_req {
char *key;
@@ -1950,13 +2212,6 @@ struct uwsgi_subscribe_req {
uint8_t modifier2;
};
struct uwsgi_dict *uwsgi_dict_create(uint64_t, uint64_t);
void uwsgi_add_subscriber(struct uwsgi_dict *, struct uwsgi_subscribe_req *);
char *uwsgi_dict_get(struct uwsgi_dict *, char *, uint16_t, uint64_t *);
int uwsgi_dict_set(struct uwsgi_dict *, char *, uint16_t, char *, uint64_t);
struct uwsgi_subscriber_name *uwsgi_get_subscriber(struct uwsgi_dict *, char *, uint16_t);
#ifndef _NO_UWSGI_RB
#include "lib/rbtree.h"
@@ -2022,7 +2277,7 @@ int uwsgi_netlink_del(char *);
int uwsgi_amqp_consume_queue(int, char *, char *, char *, char *, char *, char *);
char *uwsgi_amqp_consume(int, uint64_t *, char **);
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t, char *, uint16_t);
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
inline int uwsgi_starts_with(char *, int, char *, int);
#ifdef __sun__
@@ -2113,6 +2368,7 @@ socklen_t socket_to_in_addr(char *, char *, struct sockaddr_in *);
socklen_t socket_to_un_addr(char *, struct sockaddr_un *);
int uwsgi_get_shared_socket_fd_by_num(int);
struct uwsgi_socket *uwsgi_get_shared_socket_by_num(int);
int uwsgi_get_shared_socket_num(struct uwsgi_socket *);
@@ -2155,6 +2411,119 @@ char *uwsgi_str_contains(char *, int, char);
int uwsgi_simple_parse_vars(struct wsgi_request *, char *, char *);
void uwsgi_build_mime_dict(char *);
struct uwsgi_dyn_dict *uwsgi_dyn_dict_new(struct uwsgi_dyn_dict **, char *, int, char *, int);
void uwsgi_dyn_dict_del(struct uwsgi_dyn_dict *);
void uwsgi_send_stats(int);
void uwsgi_apply_config_pass(char symbol, char*(*)(char *) );
void uwsgi_mule(int);
char *uwsgi_string_get_list(struct uwsgi_string_list **, int, size_t *);
void uwsgi_fixup_fds(int, int);
void uwsgi_set_processname(char *);
void http_url_decode(char *, uint16_t *, char *);
pid_t uwsgi_fork(char *);
struct uwsgi_mule *get_mule_by_id(int);
struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **, struct uwsgi_mule *);
int uwsgi_farm_has_mule(struct uwsgi_farm *, int);
struct uwsgi_farm *get_farm_by_name(char *);
struct uwsgi_subscribe_slot;
struct uwsgi_subscribe_node {
char name[0xff];
uint16_t len;
uint8_t modifier1;
uint8_t modifier2;
time_t last_check;
uint64_t requests;
uint64_t transferred;
int death_mark;
uint64_t reference;
struct uwsgi_subscribe_slot *slot;
struct uwsgi_subscribe_node *next;
};
struct uwsgi_subscribe_slot {
char key[0xff];
uint16_t keylen;
#ifdef UWSGI_PCRE
pcre *pattern;
pcre_extra *pattern_extra;
#endif
uint64_t hits;
// used for round robin
uint64_t rr;
struct uwsgi_subscribe_node *nodes;
struct uwsgi_subscribe_slot *prev;
struct uwsgi_subscribe_slot *next;
};
void mule_send_msg(int, char *, size_t);
void create_signal_pipe(int *);
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **, char *, uint16_t, int);
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **, char *, uint16_t, char *, uint16_t, int);
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **, char *, uint16_t, int);
int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **, struct uwsgi_subscribe_node *);
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **, struct uwsgi_subscribe_req *, int);
ssize_t uwsgi_mule_get_msg(int, int, char *, size_t, int);
uint8_t uwsgi_signal_wait(int);
void uwsgi_add_app(int, uint8_t, char *, int);
int uwsgi_signal_send(int, uint8_t);
int uwsgi_remote_signal_send(char *, uint8_t);
void uwsgi_configure(void);
void cluster_setup(void);
void manage_cluster_announce(char *, uint16_t, char *, uint16_t, void *);
int uwsgi_read_response(int, struct uwsgi_header *, int, char **);
char *uwsgi_simple_file_read(char *);
void uwsgi_send_subscription(char *, char *, size_t , char *, size_t, uint8_t);
void uwsgi_subscribe(char *, uint8_t);
struct uwsgi_daemon *uwsgi_daemon_new(struct uwsgi_daemon **, char *);
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **, char *, int (*)(int, struct uwsgi_signal_probe *));
int uwsgi_add_probe(uint8_t sig, char *, char *, int, int);
int uwsgi_is_bad_connection(int);
#ifdef __linux__
#ifdef MADV_MERGEABLE
void uwsgi_linux_ksm_map(void);
#endif
#endif
#ifdef UWSGI_CAP
void uwsgi_build_cap(char *);
#endif
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int, char **, char **);
#endif
+18 -2
View File
@@ -264,20 +264,36 @@ $(document).ready(function() {
<a name="workers"></a>
<h3>Workers</h3>
<div class="info">
<table width="400">
<table width="600">
<tr>
<th>#</th>
<th>pid</th>
<th>status</th>
<th>requests</th>
<th>exceptions</th>
<th>signals</th>
<th>running time</th>
<th>avg response time</th>
{% if 'memory-report' in uwsgi.opt %}
<th>rss</th>
<th>vsz</th>
{% endif %}
<th># respawn</th>
</tr>
{% for w in uwsgi.workers() %}
<tr class="{{ loop.cycle('odd', 'even') }}">
<td>{{w.id}}</td>
<td>{{w.pid}}</td>
<td>{{w.status}}</td>
<td>{{w.requests}}</td>
<td>{{w.exceptions}}</td>
<td>{{w.signals}}</td>
<td>{{w.running_time/1000}}</td>
<td>{{w.avg_rt/1000}}</td>
{% if 'memory-report' in uwsgi.opt %}
<td>{{(w.rss/1000/1000)|round(2,'floor')}}MB</td>
<td>{{(w.vsz/1000/1000)|round(2,'floor')}}MB</td>
{% endif %}
<td>{{w.respawn_count}}</td>
</tr>
{% endfor %}
@@ -294,7 +310,7 @@ $(document).ready(function() {
<div class="info">
{% for w in uwsgi.workers() %}
worker {{w.id}}
<table width="400">
<table width="600">
<tr>
<th>#</th>
<th>modifier1</th>
+136 -26
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '0.9.9-dev'
uwsgi_version = '1.0-dev'
import os
import re
@@ -25,13 +25,15 @@ GCC = os.environ.get('CC', sysconfig.get_config_var('CC'))
if not GCC:
GCC = 'gcc'
CPP = os.environ.get('CPP', 'cpp')
binary_list = []
def binarize(name):
return name.replace('/', '_').replace('.','_').replace('-','_')
def spcall(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,stderr=open('/dev/null','w'))
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,stderr=open('uwsgibuild.log','w'))
if p.wait() == 0:
if sys.version_info[0] > 2:
@@ -57,10 +59,22 @@ def spcall2(cmd):
else:
return None
def spcall3(cmd):
p = subprocess.Popen(cmd, shell=True, stdin=open('/dev/null'), stderr=subprocess.PIPE, stdout=subprocess.PIPE)
if p.wait() == 0:
if sys.version_info[0] > 2:
return p.stderr.read().rstrip().decode()
return p.stderr.read().rstrip()
else:
return None
def add_o(x):
if x == 'uwsgi':
x = 'main'
elif x.endswith('.a'):
return x
x = x + '.o'
return x
@@ -85,7 +99,7 @@ def compile(cflags, objfile, srcfile):
except:
pass
cmdline = "%s -c %s -o %s %s" % (GCC, cflags, objfile, srcfile)
print(cmdline)
print("[%s] %s" % (GCC, objfile))
ret = os.system(cmdline)
if ret != 0:
sys.exit(1)
@@ -100,7 +114,7 @@ def build_uwsgi(uc):
epc = "-DUWSGI_DECLARE_EMBEDDED_PLUGINS=\""
eplc = "-DUWSGI_LOAD_EMBEDDED_PLUGINS=\""
for p in ep:
p = p.rstrip().lstrip()
p = p.strip()
if p == 'ugreen':
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
continue
@@ -112,12 +126,15 @@ def build_uwsgi(uc):
cflags.append(epc)
cflags.append(eplc)
print("configured CFLAGS: %s" % ' '.join(cflags))
print("*** uWSGI compiling server core ***")
for file in gcc_list:
objfile = file
if objfile == 'uwsgi':
objfile = 'main'
compile(' '.join(cflags), objfile + '.o', file + '.c')
if not objfile.endswith('.a'):
compile(' '.join(cflags), objfile + '.o', file + '.c')
if uc.get('embedded_plugins'):
ep = uc.get('embedded_plugins').split(',')
@@ -125,7 +142,7 @@ def build_uwsgi(uc):
if len(ep) > 0:
print("*** uWSGI compiling embedded plugins ***")
for p in ep:
p = p.rstrip().lstrip()
p = p.strip()
if p == 'ugreen':
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
@@ -140,10 +157,23 @@ def build_uwsgi(uc):
p_cflags = cflags[:]
p_cflags += up.CFLAGS
try:
p_cflags.remove('-Wdeclaration-after-statement')
except:
pass
try:
p_cflags.remove('-Werror=declaration-after-statement')
except:
pass
for cfile in up.GCC_LIST:
compile(' '.join(p_cflags),
path + '/' + cfile + '.o', path + '/' + cfile + '.c')
gcc_list.append('%s/%s' % (path, cfile))
if not cfile.endswith('.a'):
compile(' '.join(p_cflags),
path + '/' + cfile + '.o', path + '/' + cfile + '.c')
gcc_list.append('%s/%s' % (path, cfile))
else:
gcc_list.append(cfile)
libs += up.LIBS
ldflags += up.LDFLAGS
@@ -160,7 +190,7 @@ def build_uwsgi(uc):
print("*** uWSGI building plugins ***")
for p in plugins:
p = p.rstrip().lstrip()
p = p.strip()
print("*** building plugin: %s ***" % p)
build_plugin("plugins/%s" % p, uc, cflags, ldflags, libs)
@@ -195,25 +225,70 @@ class uConf(object):
print("using profile: %s" % filename)
if not os.path.exists(filename):
raise Exception("profile not found !!!")
if os.path.exists('uwsgibuild.lastprofile'):
ulp = open('uwsgibuild.lastprofile','r')
last_profile = ulp.read()
ulp.close()
if last_profile != filename:
os.environ['UWSGI_FORCE_REBUILD'] = '1'
ulp = open('uwsgibuild.lastprofile','w')
ulp.write(filename)
ulp.close()
self.config.read(filename)
self.gcc_list = ['utils', 'protocol', 'socket', 'logging', 'master', 'master_utils', 'emperor', 'notify',
'plugins', 'lock', 'cache', 'queue', 'event', 'signal', 'rpc', 'gateway', 'loop', 'lib/rbtree', 'lib/amqp', 'rb_timers', 'uwsgi']
self.gcc_list = ['utils', 'protocol', 'socket', 'logging', 'master', 'master_utils', 'emperor', 'notify', 'mule', 'subscription',
'plugins', 'lock', 'cache', 'queue', 'event', 'signal', 'cluster', 'rpc', 'gateway', 'loop', 'lib/rbtree', 'lib/amqp', 'rb_timers', 'uwsgi']
# add protocols
self.gcc_list.append('proto/base')
self.gcc_list.append('proto/uwsgi')
self.gcc_list.append('proto/http')
self.gcc_list.append('proto/fastcgi')
self.include_path = []
self.cflags = ['-O2', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()
if uwsgi_os == 'Linux':
self.gcc_list.append('lib/linux_ns')
self.gcc_list.append('lib/netlink')
self.cflags = ['-O2', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()
try:
lk_ver = uwsgi_os_k.split('.')
if int(lk_ver[0]) <= 2 and int(lk_ver[1]) <= 6 and int(lk_ver[2]):
self.cflags.append('-DOBSOLETE_LINUX_KERNEL')
except:
pass
try:
gcc_version = str(spcall("%s -dumpversion" % GCC))
except:
print("*** you need a c compiler to build uWSGI ***")
sys.exit(1)
gcc_major = int(gcc_version.split('.')[0])
gcc_minor = int(gcc_version.split('.')[1])
try:
add_it = False
cpp_include_list = str(spcall3("%s -v" % CPP)).split("\n")
for line in cpp_include_list:
if line.startswith('#include <...> search starts here:'):
add_it = True
elif line.startswith('End of search list.'):
add_it = False
elif add_it:
self.include_path.append(line.strip().split()[0])
if not self.include_path:
raise
except:
self.include_path = ['/usr/include', '/usr/local/include']
print("detected include path: %s" % self.include_path)
try:
gcc_major = int(gcc_version.split('.')[0])
gcc_minor = int(gcc_version.split('.')[1])
except:
raise Exception("you need a C compiler to build uWSGI")
if (sys.version_info[0] == 2) or (gcc_major < 4) or (gcc_major == 4 and gcc_minor < 3):
self.cflags = self.cflags + ['-fno-strict-aliasing']
# add -fno-strict-aliasing only on python2 and gcc < 4.3
@@ -266,6 +341,12 @@ class uConf(object):
print("%s needs %s support." % (what, d))
sys.exit(1)
def has_include(self, what):
for include in self.include_path:
if os.path.exists("%s/%s" %(include, what)):
return True
return False
def get_gcll(self):
global uwsgi_version
@@ -273,7 +354,7 @@ class uConf(object):
self.cflags.append('-DUWSGI_BUILD_DATE="\\"%s\\""' % time.strftime("%d %B %Y %H:%M:%S"))
kvm_list = ['FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly']
if os.path.exists('/usr/include/ifaddrs.h') or os.path.exists('/usr/local/include/ifaddrs.h'):
if self.has_include('ifaddrs.h'):
self.cflags.append('-DUWSGI_HAS_IFADDRS')
if uwsgi_os == 'SunOS':
@@ -369,7 +450,7 @@ class uConf(object):
if timer_mode == 'timerfd':
self.cflags.append('-DUWSGI_EVENT_TIMER_USE_TIMERFD')
if not os.path.exists('/usr/include/sys/timerfd.h') and not os.path.exists('/usr/local/include/sys/timerfd.h'):
if not self.has_include('sys/timerfd.h'):
self.cflags.append('-DUWSGI_EVENT_TIMER_USE_TIMERFD_NOINC')
elif timer_mode == 'kqueue':
self.cflags.append('-DUWSGI_EVENT_TIMER_USE_KQUEUE')
@@ -412,6 +493,9 @@ class uConf(object):
self.ldflags.append('-shared')
self.ldflags.append('-fPIC')
self.cflags.append('-DUWSGI_AS_SHARED_LIBRARY')
if uwsgi_os == 'Darwin':
self.ldflags.append('-dynamiclib')
self.ldflags.append('-undefined dynamic_lookup')
if self.get('embedded'):
self.cflags.append('-DUWSGI_EMBEDDED')
@@ -420,7 +504,7 @@ class uConf(object):
self.cflags.append("-DUWSGI_UDP")
# re-enable after pcre fix
if self.get('pcreOFF'):
if self.get('pcre'):
if self.get('pcre') == 'auto':
pcreconf = spcall('pcre-config --libs')
if pcreconf:
@@ -442,10 +526,14 @@ class uConf(object):
self.gcc_list.append('regexp')
self.cflags.append("-DUWSGI_PCRE")
if self.has_include('sys/capability.h'):
self.cflags.append("-DUWSGI_CAP")
self.libs.append('-lcap')
has_json = False
has_uuid = False
if os.path.exists('/usr/include/uuid/uuid.h') or os.path.exists('/usr/local/include/uuid/uuid.h'):
if self.has_include('uuid/uuid.h'):
has_uuid = True
self.cflags.append("-DUWSGI_UUID")
if os.path.exists('/usr/lib/libuuid.so') or os.path.exists('/usr/local/lib/libuuid.so') or os.path.exists('/usr/lib64/libuuid.so') or os.path.exists('/usr/local/lib64/libuuid.so'):
@@ -550,7 +638,7 @@ class uConf(object):
self.cflags.append("-DUWSGI_LIBYAML")
self.libs.append('-lyaml')
if self.get('yaml_implementation') == 'auto':
if os.path.exists('/usr/include/yaml.h') or os.path.exists('/usr/local/include/yaml.h'):
if self.has_include('yaml.h'):
self.cflags.append("-DUWSGI_LIBYAML")
self.libs.append('-lyaml')
@@ -563,7 +651,7 @@ class uConf(object):
self.gcc_list.append('json')
self.libs.append(spcall("pkg-config --libs jansson"))
has_json = True
elif os.path.exists('/usr/include/jansson.h') or os.path.exists('/usr/local/include/jansson.h'):
elif self.has_include('jansson.h'):
self.cflags.append("-DUWSGI_JSON")
self.gcc_list.append('json')
self.libs.append('-ljansson')
@@ -576,7 +664,7 @@ class uConf(object):
if self.get('ldap'):
if self.get('ldap') == 'auto':
if os.path.exists('/usr/include/ldap.h'):
if self.has_include('ldap.h'):
self.cflags.append("-DUWSGI_LDAP")
self.gcc_list.append('ldap')
self.libs.append('-lldap')
@@ -587,7 +675,7 @@ class uConf(object):
if has_uuid and self.get('zeromq'):
if self.get('zeromq') == 'auto':
if os.path.exists('/usr/include/zmq.h') or os.path.exists('/usr/local/include/zmq.h'):
if self.has_include('zmq.h'):
self.cflags.append("-DUWSGI_ZEROMQ")
self.gcc_list.append('proto/zeromq')
self.libs.append('-lzmq')
@@ -635,7 +723,7 @@ class uConf(object):
if self.get('sqlite3'):
if self.get('sqlite3') == 'auto':
if os.path.exists('/usr/include/sqlite3.h') or os.path.exists('/usr/local/include/sqlite3.h'):
if self.has_include('sqlite3.h'):
self.cflags.append("-DUWSGI_SQLITE3")
self.libs.append('-lsqlite3')
self.gcc_list.append('sqlite3')
@@ -683,6 +771,12 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
else:
p_cflags.append("-D%s_plugin=%s_plugin" % (up.NAME, name))
try:
for opt in uc.config.options(name):
p_cflags.append('-DUWSGI_PLUGIN_%s_%s="%s"' % (name.upper(), opt.upper(), uc.config.get(name, opt, '1')))
except:
pass
plugin_dest = uc.get('plugin_dir') + '/' + name + '_plugin'
shared_flag = '-shared'
@@ -693,7 +787,9 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
shared_flag = '-dynamiclib -undefined dynamic_lookup'
for cfile in up.GCC_LIST:
if not cfile.endswith('.c') and not cfile.endswith('.cc'):
if cfile.endswith('.a'):
gcc_list.append(cfile)
elif not cfile.endswith('.c') and not cfile.endswith('.cc'):
gcc_list.append(path + '/' + cfile + '.c')
else:
gcc_list.append(path + '/' + cfile)
@@ -703,8 +799,21 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
except:
pass
try:
p_cflags.remove('-Wdeclaration-after-statement')
except:
pass
try:
p_cflags.remove('-Werror=declaration-after-statement')
except:
pass
#for ofile in up.OBJ_LIST:
# gcc_list.insert(0,ofile)
gccline = "%s -fPIC %s -o %s.so %s %s %s %s" % (GCC, shared_flag, plugin_dest, ' '.join(p_cflags), ' '.join(p_ldflags), ' '.join(gcc_list), ' '.join(p_libs) )
print(gccline)
print("[%s] %s.so" % (GCC, plugin_dest))
ret = os.system(gccline)
if ret != 0:
@@ -755,6 +864,7 @@ if __name__ == "__main__":
name = sys.argv[4]
except:
name = None
print("*** uWSGI building and linking plugin %s ***" % sys.argv[2] )
build_plugin(sys.argv[2], uc, cflags, ldflags, libs, name)
elif cmd == '--clean':
os.system("rm -f *.o")
+133
View File
@@ -1,6 +1,12 @@
import uwsgi
from threading import Thread
try:
import cPickle as pickle
except:
import pickle
if uwsgi.masterpid() == 0:
raise Exception("you have to enable the uWSGI master process to use this module")
@@ -8,6 +14,7 @@ if uwsgi.opt.get('lazy'):
raise Exception("uWSGI lazy mode is not supported by this module")
spooler_functions = {}
mule_functions = {}
postfork_chain = []
def get_free_signal():
@@ -75,6 +82,46 @@ class spoolraw(spool):
return uwsgi.spool(arguments)
class mulefunc(object):
def __init__(self, f):
if callable(f):
self.fname = f.__name__
self.mule = 0
mule_functions[f.__name__] = f
else:
self.mule = f
self.fname = None
def real_call(self, *args, **kwargs):
uwsgi.mule_msg(pickle.dumps(
{
'service': 'uwsgi_mulefunc',
'func':self.fname,
'args': args,
'kwargs': kwargs
}
), self.mule)
def __call__(self, *args, **kwargs):
if not self.fname:
self.fname = args[0].__name__
mule_functions[self.fname] = args[0]
return self.real_call
return self.real_call(*args, **kwargs)
def mule_msg_dispatcher(message):
msg = pickle.loads(message)
if msg['service'] == 'uwsgi_mulefunc':
return mule_functions[msg['func']](*msg['args'],**msg['kwargs'])
uwsgi.mule_msg_hook = mule_msg_dispatcher
class rpc(object):
def __init__(self, name):
@@ -84,6 +131,80 @@ class rpc(object):
uwsgi.register_rpc(self.name, f)
return f
class farm_loop(object):
def __init__(self, f, farm):
self.f = f
self.farm = farm
def __call__(self):
if uwsgi.mule_id() == 0:
return
if not uwsgi.in_farm(self.farm):
return
while True:
message = uwsgi.farm_get_msg()
if message:
self.f(message)
class farm(object):
def __init__(self, name=None, **kwargs):
self.name = name
def __call__(self, f):
postfork_chain.append(farm_loop(f, self.name))
class mule_brain(object):
def __init__(self, f, num):
self.f = f
self.num = num
def __call__(self):
if uwsgi.mule_id() == self.num:
self.f()
class mule_brainloop(mule_brain):
def __call__(self):
if uwsgi.mule_id() == self.num:
while True:
self.f()
class mule(object):
def __init__(self, num):
self.num = num
def __call__(self, f):
postfork_chain.append(mule_brain(f, self.num))
class muleloop(mule):
def __call__(self, f):
postfork_chain.append(mule_brainloop(f, self.num))
class mulemsg_loop(object):
def __init__(self, f, num):
self.f = f
self.num = num
def __call__(self):
if uwsgi.mule_id() == self.num:
print " i am the mule"
while True:
message = uwsgi.mule_get_msg()
if message:
self.f(message)
class mulemsg(object):
def __init__(self, num):
self.num = num
def __call__(self, f):
postfork_chain.append(mulemsg_loop(f, self.num))
class signal(object):
def __init__(self, num, **kwargs):
@@ -148,11 +269,23 @@ class filemon(object):
uwsgi.add_file_monitor(self.num, self.fsobj)
return f
class erlang(object):
def __init__(self, name):
self.name = name
def __call__(self, f):
uwsgi.erlang_register_process(self.name, f)
return f
class lock(object):
def __init__(self, f):
self.f = f
def __call__(self, *args, **kwargs):
# ensure the spooler will not call it
if uwsgi.i_am_the_spooler():
return
uwsgi.lock()
try:
return self.f(*args, **kwargs)
+128
View File
@@ -0,0 +1,128 @@
# based on uwsgidecorators.py
if UWSGI.masterpid == 0
raise "you have to enable the uWSGI master process to use this module"
end
def get_free_signal()
for signum in 0..255
if not UWSGI.signal_registered(signum)
return signum
end
end
end
$postfork_chain = []
$mulefunc_list = []
module UWSGI
module_function
def post_fork_hook()
$postfork_chain.each {|func| func.call }
end
module_function
def mule_msg_hook(message)
service = Marshal.load(message)
if service['service'] == 'uwsgi_mulefunc'
mulefunc_manager(service)
end
end
end
def timer(secs, target='', &block)
freesig = get_free_signal
UWSGI.register_signal(freesig, target, block)
UWSGI.add_timer(freesig, secs)
end
def rbtimer(secs, target='', &block)
freesig = get_free_signal
UWSGI.register_signal(freesig, target, block)
UWSGI.add_rb_timer(freesig, secs)
end
def filemon(file, target='', &block)
freesig = get_free_signal
UWSGI.register_signal(freesig, target, block)
UWSGI.add_file_monitor(freesig, file)
end
def cron(minute, hour, day, month, dayweek, target='', &block)
freesig = get_free_signal
UWSGI.register_signal(freesig, target, block)
UWSGI.add_cron(freesig, minute, hour, day, month, dayweek)
end
def signal(signum, target='', &block)
UWSGI.register_signal(signum, target, block)
end
def postfork(&block)
$postfork_chain << block
end
def rpc(name, &block)
if block.arity <= 0
UWSGI.register_rpc(name, block, 0)
else
UWSGI.register_rpc(name, block, block.arity)
end
end
def mulefunc_manager(service)
$mulefunc_list[service['func']].real_call(service['args'])
end
class MuleFunc < Proc
def initialize(id=0, &block)
@id = id
@block = block
@func_pos = (($mulefunc_list << self).length)-1
end
def real_call(*args)
@block.call(*args)
end
def call(*args)
UWSGI.mule_msg( Marshal.dump( {
'service' => 'uwsgi_mulefunc',
'func' => @func_pos,
'args'=> args
}), @id)
end
end
class MuleProc < Proc
def initialize(id, block)
@id = id
@block = block
end
def call()
if UWSGI.mule_id == @id
@block.call
end
end
end
class MuleLoopProc < MuleProc
def call()
if UWSGI.mule_id == @id
loop do
@block.call
end
end
end
end
def mule(id, &block)
$postfork_chain << MuleProc.new(id, block)
end
def muleloop(id, &block)
$postfork_chain << MuleLoopProc.new(id, block)
end
+11
View File
@@ -0,0 +1,11 @@
[uwsgi]
socket = :$(PORT)
socket = /tmp/uwsgi_welcome.socket
vacuum = true
appname = welcome
module = %(appname)
numproc = 4
master = %(vacuum)
processes = %(numproc)
mount = /werkzeug=tests/werkzeug.py
manage-script-name = true

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