Compare commits

...
1221 Commits
Author SHA1 Message Date
roberto@oneiric64 0c9b6e98f7 added support for yaml lists under libyaml 2011-12-07 10:21:11 +01:00
roberto@colossus ce33d0be5a support for older rails apps 2011-12-07 09:21:28 +01:00
roberto@oneiric64 4f0fb90bff added failcnt in subscription system 2011-12-06 11:17:26 +01:00
roberto@mrspurr 66eff0107a fixed SEQPACKET usage 2011-12-06 10:50:30 +01:00
roberto@oneoric64 82f83e610f fixed a fd leak on static file serving 2011-12-06 09:29:41 +01:00
roberto@oneiric64 cf7df391ad correctly report load in fastrouter stats 2011-12-04 15:58:38 +01:00
roberto@oneiric64 244c9f8204 allows modifier2 to be subscribed 2011-12-04 15:35:29 +01:00
roberto@oneoric64 26dc19df7d reverted subscription string usage 2011-12-04 15:30:08 +01:00
roberto@oneiric64 7b8bff1a08 fixed a bug in load value 2011-12-04 13:50:18 +01:00
roberto@oneiric64 0b010124ef subscription optimizations 2011-12-04 13:45:18 +01:00
roberto@oneiric64 c7bde15f39 ready for next (last?) -rc 2011-12-04 10:38:53 +01:00
roberto@oneiric64 b941e4f2f0 pep8 setup.py 2011-12-04 07:41:49 +01:00
roberto@oneiric64 536c6e7e29 pep8 uwsgidecorators 2011-12-04 07:39:01 +01:00
roberto@oneiric64 dfe4abec35 added health_check in log_pipe 2011-12-04 07:14:19 +01:00
roberto@oneiric64 693b80d7d3 fixed healthcheck skip 2011-12-03 11:06:30 +01:00
roberto@oneiric64 c9e6475ef4 fixed another leak in master 2011-12-03 08:26:41 +01:00
roberto@oneiric64 b745132ebd improved ksm support 2011-12-02 13:31:17 +01:00
roberto@oneiric64 19686cb19f update the copyright to 2011 in apache module 2011-12-01 14:18:54 +01:00
roberto@oneiric64 e0c0593b5b fixed a memory leak in glob() 2011-12-01 13:45:52 +01:00
roberto@oneiric64 415a8af363 fix compilation with async=false 2011-12-01 05:44:23 +01:00
roberto@oneiric64 d44777b1b4 fixed mod_uwsgi when SCRIPT_NAME = / 2011-11-30 18:47:14 +01:00
roberto@oneiric64 e3ff3037b4 use vector-io in fileserve mode 2011-11-30 18:38:42 +01:00
roberto@oneiric64 7add30fd31 added uWSGIemptyRemoteUser in mod_uwsgi 2011-11-30 15:37:48 +01:00
roberto@fiorenzo 501cd0349b another fastrouter fix/optimization 2011-11-29 20:52:08 +01:00
roberto@oneiric64 7b4e3f6601 better error reporting in fastrouter 2011-11-29 19:34:29 +01:00
roberto@oneiric64 8622c2780c fixed cheap reporting 2011-11-29 16:17:17 +01:00
roberto@oneiric64 13de7b6d5b fixed a loop in subscription system 2011-11-29 13:29:23 +01:00
roberto@fiorenzo 53cb864f9c added death mark in fastrouter stats 2011-11-29 11:50:09 +01:00
roberto@fiorenzo 72f693f02a fixed subscription rr and added --fastrouter-stats 2011-11-29 11:46:50 +01:00
roberto@genesi fb80e32682 fix obsolete kernel check 2011-11-29 10:41:57 +01:00
roberto@oneiric64 1db3426ee1 applied riccardo's fix for sendfile 2011-11-29 07:52:26 +01:00
roberto@oneiric64 a44879e384 improved lazy mode to allows signals 2011-11-29 07:47:19 +01:00
roberto@oneiric64 c0075c817d remove unneeded debug entry 2011-11-28 22:06:08 +01:00
roberto@oneiric64 177dc3322b remove unneded rb_gc_unregister_address 2011-11-28 21:57:35 +01:00
roberto@storm 21ef4fc89b multiline headers rack fixes 2011-11-28 21:36:03 +01:00
roberto@oneiric64 f467643f6f better post_buffering 2011-11-28 14:14:24 +01:00
roberto@oneiric64 3db41e7e05 better usage of fwrite() 2011-11-28 14:04:49 +01:00
roberto@oneiric64 73151729c6 mark route() requests 2011-11-28 13:58:15 +01:00
roberto@longshot 5d9c415028 merge 2011-11-28 13:07:05 +01:00
roberto@longshot b92ed4da4e fixed after_request remapper 2011-11-28 13:06:43 +01:00
roberto@oneiric64 2d1a9a03d2 reduce a potetial race conditions in evil reloads 2011-11-28 11:35:35 +01:00
roberto@longshot 5d6edd2321 force removal of -Winline during plugins building 2011-11-28 10:29:46 +01:00
roberto@oneiric64 365f4ba83f fixed a bug in FIFO reading 2011-11-28 07:17:58 +01:00
roberto@oneiric64 66e30ae293 report config in USR1 management 2011-11-27 21:05:06 +01:00
roberto@oneiric64 728425de19 Added tag 1.0-rc7 for changeset a3ca2e8e27c5 2011-11-26 18:50:41 +01:00
roberto@oneiric64 b0af1f800b fixed a bug in #ifdef for pump/web3 spotted by riccardo 2011-11-26 18:39:44 +01:00
roberto@oneiric64 543271e856 fixed a ksm leak 2011-11-26 13:02:47 +01:00
roberto@oneiric64 a1564a44fa added postgresql probe 2011-11-26 12:44:38 +01:00
roberto@oneiric64 571029cfd3 added probe infrastructure 2011-11-26 11:05:49 +01:00
roberto@oneiric64 579eaa630a refactored daemons and removed uwsgi.attach_daemon function 2011-11-26 09:04:19 +01:00
roberto@oneiric64 9530c8ffe0 applied riccardo's patch [2] 2011-11-26 08:10:29 +01:00
roberto@oneiric64 0d8690091b applied riccardo's patch [1] 2011-11-26 08:04:39 +01:00
roberto@goyle 5b5e3a1ec1 added delta_requests 2011-11-25 15:34:41 +01:00
roberto@centos64 869ae5e3ed allows the building of uWSGI on ancient linux kernel (like CentOS4) 2011-11-24 12:57:08 +01:00
roberto@oneiric64 d6dc8d86f8 added subscription report on startup 2011-11-24 07:42:14 +01:00
roberto@oneiric64 758745be68 closed bug #56 2011-11-24 07:35:32 +01:00
roberto@oneiric64 2adfa56d6a added threading name in python threads object 2011-11-23 17:44:41 +01:00
roberto@oneiric64 a4c728f5df added auto-patching for Rack::BodyProxy.each 2011-11-23 11:45:13 +01:00
roberto@oneiric64 5c06341b7f ready for -rc7 2011-11-23 10:08:49 +01:00
roberto@oneiric64 6f57902a9b another cron fix 2011-11-23 05:37:00 +01:00
roberto@longshot a3e118893d do not build sqlite on unbit 2011-11-22 18:52:12 +01:00
roberto@oneiric64 ff2d3c29d6 fixed a bug in cron management 2011-11-22 17:56:03 +01:00
roberto@oneiric64 59a8df85f2 added --st as a --subscribe/--subscribe-to alias 2011-11-22 11:23:10 +01:00
roberto@oneiric64 e303bd182a report subscribed nodes timeout 2011-11-22 11:15:13 +01:00
roberto@oneiric64 dcef9a497c less verbose build system 2011-11-22 09:46:16 +01:00
roberto@oneiric64 8d4fd66aaf fixed a bug in execvp() during reload on 64 bit 2011-11-22 09:16:34 +01:00
roberto@debian32 471bd23acf added --subscribe-freq and --subscription-tolerance 2011-11-21 20:22:00 +01:00
roberto@debian32 ffcef81dd0 greatly improved subscription system 2011-11-21 16:23:24 +01:00
roberto@debian32 317df5d06b added @(filename) magic var 2011-11-21 13:22:05 +01:00
roberto@debian32 ad7b5efd6f added --logfile-chmod 2011-11-21 10:32:48 +01:00
roberto@deban32 891f770724 added Lukas to CONTRIBUTORS 2011-11-21 09:55:43 +01:00
roberto@debian32.local 0b6d715982 refactored ping and nagios 2011-11-21 09:42:48 +01:00
roberto@debian32 76c2415516 moved cluster-related functions to a dedicated file 2011-11-20 11:36:42 +01:00
roberto@gambit 3260faca17 Added tag 1.0-rc6 for changeset a2b8f25fd17e 2011-11-19 08:40:45 +01:00
roberto@arch32 feb493158c a fix fir capability support on arch linux 2011-11-19 07:55:22 +01:00
roberto@debian32 a5c1556cb7 do not exit on realod if chdir() fail 2011-11-18 20:46:07 +01:00
roberto@longshot 89e640bdd9 better to not remove -g/-ggdb 2011-11-18 09:29:30 +01:00
roberto@longshot 3ade8daff8 fixed rack compilation 2011-11-18 09:23:06 +01:00
roberto@debian32 049ea3fbed added Linux KSM support 2011-11-17 11:16:48 +01:00
roberto@goyle 715d26beed added support for remote signalling in rack plugin 2011-11-16 18:30:00 +01:00
roberto@goyle 1f5064094c better signal registration reporting 2011-11-15 18:33:44 +01:00
roberto@goyle 7ed522dc29 added --signal 2011-11-15 18:18:42 +01:00
roberto@goyle 2086500405 added signal plugin 2011-11-15 18:06:37 +01:00
roberto@debian32 8f79409ed1 added uwsgi.route() 2011-11-14 15:05:23 +01:00
roberto@debian32 c2a3cd1476 added mule support to ruby DSL 2011-11-13 17:25:47 +01:00
roberto@debian32 e195a5d72c improved signal handling and rack mule_msg 2011-11-13 15:08:29 +01:00
roberto@debian32 c86b757904 use app_id in rack plugin 2011-11-12 16:24:47 +01:00
roberto@debian32 6800d2ac95 added lock/unlock to rack plugin 2011-11-12 11:31:22 +01:00
roberto@debian32 90fda2b4bb added UWSGI.mem 2011-11-12 11:18:25 +01:00
roberto@debian32 bf7ded9058 added a bunch of constant to rack plugin 2011-11-12 11:13:06 +01:00
roberto@debian32 6615dc3a62 added UWSGI.setprocname 2011-11-12 11:07:38 +01:00
roberto@debian32 c35054085c completed ruby cache support 2011-11-12 11:02:30 +01:00
roberto@debian32 fdf2bd7f96 fixed ruby 1.9 support 2011-11-12 10:53:19 +01:00
roberto@debian32 1c10b9dfe1 ported cache api to rack plugin 2011-11-12 10:44:23 +01:00
roberto@debian32 6854394e5c added rpc support to ruby 2011-11-11 12:29:04 +01:00
roberto@debian32 78a0d5f432 added postfork in uwsgidsl 2011-11-11 09:57:35 +01:00
roberto@debian32 5fe5aa70a4 added post_fork_hook to ruby 2011-11-11 09:49:17 +01:00
roberto@debian32 e9c0c6bd0b report GC frequency 2011-11-11 06:54:08 +01:00
roberto@debian32 5d12b3dc9c added --rbrequire 2011-11-11 06:51:29 +01:00
roberto@debian32 169a4b66db added UWSGI.signal_received to ruby 2011-11-10 16:32:26 +01:00
roberto@debian32 fbd6329db9 improved ruby signal handling 2011-11-10 16:11:48 +01:00
roberto@debian32 69c2e56857 ported python plugin to new signal_wait api 2011-11-10 15:36:36 +01:00
roberto@debian32 18f7d1edd3 refactored signal_wait 2011-11-10 15:34:19 +01:00
roberto@debian32 3f7cd5ff92 added rubydsl 2011-11-10 15:33:41 +01:00
roberto@debian32 785e1dbf83 re-thinked remap-modifier 2011-11-10 15:33:19 +01:00
roberto@debian32 bc6acf8d14 use SIGTSTP instead of SIGWINCH for pause/suspend/resume 2011-11-10 11:25:22 +01:00
roberto@sirius 3a099d0b2e added --pause/--suspend/--resume 2011-11-10 09:38:32 +01:00
roberto@longshot f9ad5e4144 fixed multi-option parser 2011-11-09 20:58:33 +01:00
roberto@debian32 ce9f6650a0 allows carbon-id to include dots 2011-11-09 07:08:44 +01:00
roberto@mrspurr fdeef04343 fixed a stupid bug in carbon plugin 2011-11-09 06:57:21 +01:00
roberto@debian32 fe72ec82e1 completed carbon plugin 2011-11-09 06:50:51 +01:00
roberto@debian32 fd0f308273 added carbon plugin 2011-11-09 06:25:38 +01:00
roberto@longshot f4e9ab43cb fixed rack compilation 2011-11-08 18:46:29 +01:00
roberto@debian32 3a141b523c Added tag 1.0-rc5 for changeset 043ba93dd69c 2011-11-03 09:40:07 +01:00
roberto@debian32 2d731532be various erlang fixes 2011-11-03 09:09:17 +01:00
roberto@debian32 d545cd5be0 added @erlang decorator 2011-11-02 20:48:11 +01:00
roberto@debian32 261d05d67e added @mulemsg decorator 2011-11-02 19:55:11 +01:00
roberto@debian32 639995785a fixed pyerl 2011-11-02 14:41:32 +01:00
roberto@debian32 817e076cae uwsgidecorators is installed when run under pip/easy_install 2011-11-02 14:20:51 +01:00
roberto@debian32 713370f343 completed regexp support in subscription system 2011-11-01 08:33:52 +01:00
roberto@debian32 5594503a56 pcre support in subscription system 2011-10-31 09:11:02 +01:00
roberto@debian32 d57e5d46fb fixed subscriptions removal in http plugin 2011-10-31 07:56:01 +01:00
roberto@debian32 ee2db5fabd a bunch of subscription optimizations 2011-10-30 13:10:26 +01:00
roberto@debian32 0c4cd6f378 ported http plugin to new subscription system 2011-10-30 11:36:53 +01:00
roberto@debian32 8c32b9665c re-implementation of subscription system 2011-10-30 11:30:53 +01:00
roberto@colossus 7405a01654 ready for next -rc ? 2011-10-28 17:53:16 +02:00
roberto@colossus 5d27691b4b fixed log rotation 2011-10-28 16:49:26 +02:00
roberto@debian32 19bbcfbf4c added @mule decorator 2011-10-28 16:22:39 +02:00
roberto@debian32 fa1064db87 added --umask 2011-10-28 16:10:26 +02:00
roberto@colossus 850ac69ca1 fixed master reloading 2011-10-28 11:35:18 +02:00
roberto@debian32 943edeb30c fixed a typo in subscribe-to and incresed slots to 64 2011-10-28 08:11:51 +02:00
roberto@debian32 01815a354b added a centos init script in contrib 2011-10-27 13:54:29 +02:00
roberto@debian32 2f4412aca1 allows .json as a valid vassal extension 2011-10-27 13:52:11 +02:00
roberto@oneiric64 2782bb7594 fixed 64bit support in rrdtool 2011-10-27 12:44:01 +02:00
roberto@debian32 074c1298d5 procname-prefix-spaced 2011-10-27 10:08:38 +02:00
roberto@debian32 55a7911611 added rrdtool plugin 2011-10-27 09:26:59 +02:00
roberto@debian32 013ad3044d added @mulefuc decorators 2011-10-26 10:51:03 +02:00
roberto@debian32 dcf4217b9d greatly improved uwsgi.mule_msg() 2011-10-26 10:13:20 +02:00
roberto@debian32 876dfc31a9 dynamic buffer_size and timeout for mule_get_msg 2011-10-26 06:43:07 +02:00
roberto@debian32 fd03bdbe00 improved mule and farm signal handling 2011-10-26 06:30:42 +02:00
roberto@debian32 83612649d5 mule_get_msg can manage signals 2011-10-26 06:11:07 +02:00
roberto@debian32 3c4db7e97e timerfd_create workaround 2011-10-26 05:45:06 +02:00
roberto@colossus 088c70efdc fixed locking 2011-10-25 18:05:52 +02:00
roberto@debian32 2b19029dd0 multiple mule_msg() 2011-10-25 17:46:41 +02:00
roberto@debian32 4fb5a84378 improved multi-mule support 2011-10-25 17:35:52 +02:00
roberto@debian32 b3107d9a25 another mule fix 2011-10-25 17:03:13 +02:00
roberto@debian32 bf32988f3e applied riccardo magliocchetti patch for .json support 2011-10-25 16:44:33 +02:00
roberto@debian32 1bf3dd7bf4 fixed mule patch message 2011-10-24 18:52:41 +02:00
roberto@debian32 07fd84f89f ported symimporter/symzipimporter to python3 2011-10-24 16:35:59 +02:00
roberto@debian32 3a8db4a97a fixed unlocking 2011-10-24 15:56:17 +02:00
roberto@debian32 aea30a26f5 added --mules <n> 2011-10-24 10:40:29 +02:00
roberto@gambit 8f5d1cdae7 Added tag 1.0-rc4 for changeset 24f7e260ea34 2011-10-24 10:05:02 +02:00
roberto@gambit 53913357e0 fixed strtok usage 2011-10-24 10:04:25 +02:00
roberto@debian32 098416f444 uWSGI 1.0-rc3 2011-10-24 09:42:41 +02:00
roberto@debian32 c98cb09c7c Added tag 1.0-rc3 for changeset 4e4e781ef89a 2011-10-24 09:42:27 +02:00
roberto@debian32 bb1ef28d69 updated decorators with @farm([name]) 2011-10-23 19:59:53 +02:00
roberto@debian32 1d5b05265d initial farm implementation 2011-10-23 19:18:31 +02:00
roberto@debian32 d9fef3c30e a little hack for psgi loader waiting for a truly agnostic init_uwsgi_app 2011-10-23 12:14:53 +02:00
roberto@debian32 e5dfb9efc3 improved get_memusage 2011-10-23 12:04:02 +02:00
roberto@debian32 02bab15e86 perl threading improvements 2011-10-23 11:49:25 +02:00
roberto@debian32 6f4ddead09 Added tag 1.0-rc2 for changeset 7a4e021ea7ba 2011-10-23 08:37:03 +02:00
roberto@gambit b361248ff6 fixed add_exported_opts 2011-10-23 08:35:15 +02:00
roberto@debian32 e9c42ceaa5 support for multiple values in options 2011-10-22 18:32:32 +02:00
roberto@debian32 5d7029744a PATH_INFO is correctly escaped in http modes 2011-10-22 09:35:01 +02:00
roberto@gambit 1084a3afa8 fixed mule patch loading 2011-10-20 10:38:59 +02:00
roberto@gambit ed254bffee fixed mule process name 2011-10-20 10:20:44 +02:00
roberto@djangocloud 733784d7dd another procname fix... 2011-10-19 16:13:10 +10:00
roberto@djangocloud cb5b26bcb4 another bunch of procname fixes 2011-10-19 14:26:07 +10:00
roberto@djangocloud 0065152bb1 daemons throttling subsystem 2011-10-18 18:53:22 +10:00
roberto@djangocloud 03266203fd another fix for environ 2011-10-18 18:30:13 +10:00
roberto@djangocloud 4a5f68f9d8 fixed environ 2011-10-18 18:12:39 +10:00
roberto@djangocloud 83e31a1c27 another setprocname fix 2011-10-18 16:20:33 +10:00
roberto@djangocloud 0efed5ef9c various emperor procname fixes 2011-10-18 16:15:06 +10:00
roberto@djangocloud cdfef1281d fixed another spooler compilation bug 2011-10-18 15:12:59 +10:00
roberto@debian32 e00907e142 --spooler-harakiri 2011-10-17 19:07:12 +02:00
roberto@app1 6dcbcf39e3 fixed compilation when spooler is disabled 2011-10-17 03:16:55 -05:00
roberto@debian32 044579a8e0 more verbose annihilation report 2011-10-16 11:16:13 +02:00
roberto@debian32 d2b52b4663 added uwsgi.setprocname() 2011-10-16 10:37:26 +02:00
roberto@debian32 7f75b2c02c added --procname and --procname-master 2011-10-16 10:18:45 +02:00
roberto@freebsd64 24a3f671e5 freebsd setproctitle 2011-10-16 10:06:08 +02:00
roberto@debian32 875100e3c8 check for mules before nuke 2011-10-16 09:58:37 +02:00
roberto@mrspurr 34bc7c0cfd check for procname 2011-10-16 09:54:35 +02:00
roberto@debian32 b39a10ff7c procname initial management 2011-10-16 09:45:41 +02:00
roberto@debian32 02331904de uWSGI 1.0-rc1 2011-10-15 08:47:00 +02:00
roberto@debian32 d1a4ae694e --locks 2011-10-15 08:32:32 +02:00
roberto@debian32 7a5ffc1124 --spooler-chdir 2011-10-14 19:20:05 +02:00
roberto@debian32 19c5bfb42c fixed a spooler signal bug spotted by Gabriele Giaccari 2011-10-14 18:32:17 +02:00
roberto@debian32 893bf3686b fixed a wrong typecast 2011-10-14 10:58:02 +02:00
roberto@debian32 e54fa9bcd4 added --emperor-stats 2011-10-13 07:53:32 +02:00
roberto@debian32 c1eb5ab0fe prepare for emperor-stats 2011-10-12 06:51:49 +02:00
roberto@mrspurr 461914dde4 completed --evil-reload options 2011-10-12 06:48:52 +02:00
roberto@debian32 85662578e4 implemented --mule-harakiri 2011-10-12 01:48:30 +02:00
roberto@debian32 a59c0ae795 setlinebuf in syslog mode 2011-10-12 00:54:18 +02:00
roberto@debian32 3a860155ee added --evil-reload-on-as and --evil-reload-on-rss 2011-10-11 20:39:00 +02:00
roberto@debian32 27553c2967 prepare for --evil-reload-... options 2011-10-11 20:18:31 +02:00
roberto@colossus 9a8ac9af3c added uwsgi.mule_id() 2011-10-11 07:31:41 +02:00
roberto@debian32 2f5daffe99 use hggit for better github sync 2011-10-09 09:11:54 +02:00
roberto@debian32 75cd31dce4 better spooler error reporting 2011-10-07 03:30:16 +02:00
roberto@colossus f7150d1b41 fixed mule socketpair 2011-10-06 18:37:24 +02:00
roberto@debian32 d6a6b65338 added --log-x-forwarded-for 2011-10-06 06:42:31 +02:00
roberto@freebsd64 979f6027b4 ignore SIGPIPE by default 2011-10-05 20:45:55 +02:00
roberto@freebsd64 7dc059c75b completed new freebsd64 sendfiel async support 2011-10-05 20:34:25 +02:00
roberto@freebsd64 b639b5974f better freebsd sendfile support 2011-10-05 20:19:12 +02:00
roberto@netbsd64 0de08c553c fixed a potential overflow 2011-10-05 21:16:28 +02:00
roberto@freebsd64 80788ac695 freebsd event fix 2011-10-05 19:01:29 +02:00
roberto@freebsd64 1494c621c1 non-linux fix 2011-10-05 18:43:53 +02:00
roberto@debian32 605e5b5173 export listen_queue size in stats 2011-10-05 17:24:46 +02:00
roberto@debian32 4cf2213051 added --log-truncate --log-reopen --log-maxsize --log-backupname 2011-10-05 11:58:15 +02:00
roberto@debian32 3aa36668e5 better error reporting 2011-10-04 20:28:08 +02:00
roberto@debian32 1c0b5b42e9 support for multiple --touch-reload options 2011-10-04 19:40:09 +02:00
roberto@openindiana64 702dc44fad fixed openindiana build on 64bit 2011-10-03 15:46:04 +02:00
roberto@solrisexpress 2cae07aa52 fixed 64bit compilation 2011-10-03 09:37:32 +00:00
roberto@ebian32 b5616ff25c completed mule signal handling 2011-10-03 08:36:21 +02:00
roberto@debian32 b7b7521975 refactored fds closing and socketpair 2011-10-03 08:29:19 +02:00
roberto@debian32 dce3263ee3 added mule messaging subsystem 2011-10-03 07:45:18 +02:00
roberto@debian32 9796e05ca1 added support for X_FORWARDED_SSL in http parser 2011-10-03 06:38:14 +02:00
roberto@debian32 5cc0d459ec struct uwsgi_server is becoming huge, better to add some comment 2011-10-02 20:45:03 +02:00
roberto@debian32 531a850a71 first almost-working commit for uWSGI mules 2011-10-02 20:05:31 +02:00
roberto@debian32 4c36280287 support --manage-script-name in http socket mode 2011-09-30 12:32:31 +02:00
roberto@debian32 70be8eb55e restored setup.py 2011-09-30 10:55:12 +02:00
roberto@debian32 f8b757b21e print argv in setup.py 2011-09-30 10:39:22 +02:00
roberto@debian32 3a63d352bb print envs in setup.py 2011-09-30 10:36:30 +02:00
roberto@sirius 60467705c5 fixed a stupid bug 2011-09-30 10:31:00 +02:00
roberto@debian32 eada0c09e0 refactored placeholder management 2011-09-30 10:21:26 +02:00
roberto@debian32 8e851aa6a1 fixed egg 2011-09-30 09:56:51 +02:00
roberto@debian32 eaf7bb967d added a check for http (3) 2011-09-30 09:43:42 +02:00
roberto@debian32 7be45c77b1 added a check for http (2) 2011-09-30 09:42:19 +02:00
roberto@debian32 5e2b460dc8 added a check for http (2) 2011-09-30 09:24:33 +02:00
roberto@debian32 16143e698f added a check for http 2011-09-30 09:21:12 +02:00
roberto@debian32 4259946e3b second little typecast fix 2011-09-30 08:51:18 +02:00
roberto@debian32 0a750d76ee little typecast fix 2011-09-30 08:50:00 +02:00
roberto@debian32 e4a9f5f0dd merge 2011-09-28 20:21:11 +02:00
roberto@debian32 d5b7698f89 added --stats 2011-09-28 20:20:40 +02:00
roberto@sirius a481e8508e added .gitignore 2011-09-28 17:23:22 +02:00
roberto@debian32 a53b57497b close bug #47 2011-09-28 07:27:43 +02:00
roberto@debian32 d871357b2d added uwsgi_req_error 2011-09-25 16:16:08 +02:00
roberto@debian32 2d57db55f4 removed a useless error checking 2011-09-25 14:06:06 +02:00
roberto@debian32 bae45ce03a error checking in uwsgi proto writer 2011-09-25 14:01:06 +02:00
roberto@debian32 44cc4336f1 added posix capability support 2011-09-25 13:41:10 +02:00
roberto@debian32 44f6e214fd improved uwsgi.queue_last 2011-09-25 10:44:19 +02:00
roberto@debian32 3e46f81d2b use PyLong_FromUnsignedLongLong 2011-09-25 06:42:23 +02:00
roberto@debian32 e4532b9a50 added memory usage in uwsgicc 2011-09-24 09:07:34 +02:00
roberto@debian32 2694be562c fixed respawn_count 2011-09-24 08:28:19 +02:00
roberto@debian32 fadb9edd7f added running time and avg_rt to uwsgicc 2011-09-24 08:24:51 +02:00
roberto@debian32 d85e0790de added response_time and running_time statistics 2011-09-24 06:40:30 +02:00
roberto@debian32 bc46c4d704 python3 fix 2011-09-23 08:36:28 +02:00
roberto@centos64 a73a010188 fixed build system for older gcc releases 2011-09-23 08:33:15 +02:00
roberto@debian3 4e8c8ef317 improved screen support 2011-09-21 06:09:05 +02:00
roberto@debian32 e402e7805d no need to set pty, screen is much metter 2011-09-21 05:27:58 +02:00
roberto@debian32 302b8f026b --cheaper improvement 2011-09-19 10:15:24 +02:00
roberto@debian32 630054b72a better wakeup of workers 2011-09-19 07:53:51 +02:00
roberto@debian32 a05f459b2b preliminary cheaper implementation 2011-09-19 07:13:45 +02:00
roberto@debian32 207979580a added uwsgi.extract 2011-09-18 07:04:36 +02:00
roberto@debian32 f69526f8bf parse plugin-specific options 2011-09-18 06:57:19 +02:00
roberto@debian32 e249d567a1 --fastrouter-cheap 2011-09-16 15:14:08 +02:00
roberto@debian32 a23ba653da better shared sockets support 2011-09-16 07:46:45 +02:00
roberto@debian32 0644d53572 set pty to raw mode 2011-09-13 08:35:50 +02:00
roberto@debian32 f58f51294d fixed sendfile typecasting 2011-09-11 07:41:42 +02:00
roberto@debian32 86194eb93e GC in symzipimporter is useless 2011-09-11 07:33:23 +02:00
roberto@debian32 0a89f375e6 added charles as contributor 2011-09-11 06:55:27 +02:00
roberto@debian32 6282178b3c fixed python optimize flag 2011-09-11 06:42:45 +02:00
roberto@debian32 8e14d68022 merge 2011-09-10 17:28:40 +02:00
roberto@debian32 e86bd0c070 preliminary support for detachable pyshell 2011-09-10 17:28:01 +02:00
roberto@mrspurr bf991f8892 report gb objects in welcome.py 2011-09-10 11:03:39 +02:00
roberto@mrspurr b341678d20 another symzip fix 2011-09-10 10:58:37 +02:00
roberto@mrspurr 5f59365d88 symzip GC fix 2011-09-10 10:54:27 +02:00
roberto@debian32 5130a7bb33 moved the old 'j' to 'J' option 2011-09-09 20:36:00 +02:00
roberto@dexter cc84a596d6 better iso99 check 2011-09-09 18:44:18 +02:00
roberto@longshot e67bed431a a fix for older gcc 2011-09-09 18:43:08 +02:00
roberto@dexter 72613a9f48 mime type optimization 2011-09-09 18:35:29 +02:00
roberto@sirius c048ea0615 better mimetype file check 2011-09-09 18:14:53 +02:00
roberto@dexter 957ca1b7ed added mime types support in static file serving 2011-09-09 17:06:35 +02:00
roberto@ebian32 d80a6df039 fixed a threading bug 2011-09-09 10:00:09 +02:00
roberto@mrspurr 94f9bd9d91 added Corey as contributor 2011-09-09 08:53:37 +02:00
roberto@mrspurr b480efe672 fixed script_name handling 2011-09-09 08:42:31 +02:00
roberto@mrspurr 4fc306d979 added a new debug entry 2011-09-09 08:32:20 +02:00
roberto@mrspurr 56abccbdeb another fix for urack.rb 2011-09-08 19:59:37 +02:00
roberto@mrspuur f218af0735 clang fixes 2011-09-08 19:45:46 +02:00
roberto@mrspurr 9b69c62780 automagic bundler in urack.rb 2011-09-08 13:44:50 +02:00
roberto@dexter eb5d67e07f 1.0 is better than 1.0.0 2011-09-07 16:09:45 +02:00
roberto@sirius e7391987b1 fixed sandboxviolation on osx 2011-09-07 12:33:12 +02:00
roberto@sirius 02cbe15575 test3 2011-09-07 12:32:02 +02:00
roberto@sirius a5a657f0d4 a second test 2011-09-07 12:29:24 +02:00
roberto@sirius 67567c86e0 a test 2011-09-07 12:27:47 +02:00
roberto@dexter 445d02da45 make easy_install happy 2011-09-06 17:58:02 +02:00
roberto@debian32 4a05df41ce subscription logging 2011-09-05 16:26:25 +02:00
roberto@debian32 5c0c2f6b45 yaml fix 2011-09-05 08:12:12 +02:00
roberto@debian32 0ab55fef46 added support for regexp in UWSGI_APPID 2011-09-04 21:33:30 +02:00
roberto@debian32 dd344bfe38 fixed a bug in multiapp mode 2011-09-04 18:01:04 +02:00
roberto@debian32 e92a889bcc refactored UWSGI_PY_READLINE_BUFSIZE 2011-09-03 07:15:51 +02:00
roberto@debian32 419d656a83 1.0.0-dev cycle started 2011-08-31 14:27:21 +02:00
roberto@debian32 3c3d58bfe9 pypyuwsgi.py 2011-08-31 14:01:46 +02:00
roberto@debian32 1989099cc5 preliminary pypy support 2011-08-31 13:18:32 +02:00
roberto@sirius 1446e3f0a9 allows pyuwsgi in osx 2011-08-31 12:09:56 +02:00
roberto@debian32 00fc31289d a pyuwsgi fix 2011-08-31 12:06:26 +02:00
roberto@sirius 2c463ad6af a test for libless pyuwsgi 2011-08-31 12:02:19 +02:00
roberto@sirius e641ae05c4 pyuwsgi 2011-08-31 11:42:22 +02:00
roberto@debian32 a13e0075ee fixed virtualhosting in fully-dynamic mode 2011-08-31 07:55:34 +02:00
roberto@debian32 e617a7b88e added an example for the new fd-based config 2011-08-30 12:08:22 +02:00
roberto@debian32 cbdeb4caad --stop and --reload, open by fifo and fd 2011-08-30 10:51:50 +02:00
roberto@sirius 59314d692f uWSGI 0.9.9 2011-08-29 17:32:08 +02:00
roberto@sirius 3dfa56b279 Added tag 0.9.9 for changeset 376ffd8f1906 2011-08-29 17:26:31 +02:00
roberto@dexter 920d5d7416 Changelog for 0.9.9 2011-08-29 11:32:27 +02:00
roberto@dexter dcb654d7fb spooler reload fix 2011-08-29 10:50:09 +02:00
roberto@solarisexpress a563da1223 solaris fix for lockf() 2011-08-29 10:34:46 +00:00
roberto@sirius 1e26cda615 fixed a race condition 2011-08-29 10:30:01 +02:00
roberto@dexter 97133b27ce the decoratortest is fully working, ready for release 2011-08-29 09:54:07 +02:00
roberto@sirius b428bd3b87 another bunch of build fixes 2011-08-29 08:02:37 +02:00
roberto@dexter 05136e74b4 fixed build system 2011-08-29 07:55:46 +02:00
roberto@mrspurr 9f28a8bdf1 improved upload progress 2011-08-28 20:53:46 +02:00
roberta@mrspurr d9361f1fee added test for upload progress 2011-08-28 19:13:56 +02:00
roberto@debian32 835230b1a4 emperor-tyrant 2011-08-28 09:15:13 +02:00
roberto@debian32 f88f51c553 added welcome.ini 2011-08-28 08:33:49 +02:00
roberto@debian32 1996305eb1 allows multiple --ini options 2011-08-28 07:55:54 +02:00
roberto@solrisexpress c7ad50e950 do not free getexecname() ret value 2011-08-28 07:37:21 +00:00
roberto@debian32 0ec0c29d67 fixed an indentation 2011-08-28 07:21:49 +02:00
roberto@solarisexpress 75af117e8a better magic plugin loading on binary_path 2011-08-28 07:14:42 +00:00
roberto@debian32 2b04cefe4e added help for a bunch of options 2011-08-27 19:37:34 +02:00
roberto@debian32 0e41c4111a fixed upstart 2011-08-27 18:46:53 +02:00
roberto@debian32 5f5d382c64 signal framework ported to gevent 2011-08-27 07:15:44 +02:00
roberto@dexter 3e867fe401 resolve domain names in socket logging 2011-08-26 16:20:14 +02:00
roberto@dexter 153142b8b0 fixed django uwsgi_admin without spooler 2011-08-26 15:02:02 +02:00
roberto@dexter 5562c0c047 use hub.join() instead of hub.switch() 2011-08-26 14:05:03 +02:00
roberto@debian32 f4a1f800ba timeout handling in gevent plugin 2011-08-26 12:34:12 +02:00
roberto@debian32 bdbc5e5605 another gevent improvement suggested by denis 2011-08-26 11:35:32 +02:00
roberto@debian32 4104f825ff another improvement for sys.executable in python3 2011-08-26 10:28:34 +02:00
roberto@longshot efa01ea404 better sys.executable and sys.argv values 2011-08-26 10:08:01 +02:00
roberto@debian32 982559ae66 snmp fixes 2011-08-26 09:54:11 +02:00
roberto@gambit 60002e8de8 Added tag 0.9.9-rc2 for changeset 6aa667612019 2011-08-26 08:17:20 +02:00
roberto@debian32 25d671e0f6 fixed python snmp api 2011-08-26 08:13:14 +02:00
roberto@debian32 5a58281a3f various gevent fixes 2011-08-26 07:37:26 +02:00
roberto@debian32 c422231806 ops another grunt fix 2011-08-25 18:16:58 +02:00
roberto@debian32 4979883fe5 fixed a grunt bug 2011-08-25 17:51:04 +02:00
roberto@debian32 8158a624d3 check for loop engine 2011-08-25 14:34:18 +02:00
roberto@debian32 06403b5fce fixed stupid bug in setup.py 2011-08-25 14:15:55 +02:00
roberto@debian32 bc482652fc updated setup.py 2011-08-25 14:13:13 +02:00
roberto@debian32 58aa5755e0 fixed a typo 2011-08-25 14:04:57 +02:00
roberto@debian32 bca835c58a added UWSGI_PROFILE unix env 2011-08-25 14:03:43 +02:00
roberto@debian32 4b0f68a57a check gevent version 2011-08-25 13:53:38 +02:00
roberto@debian32 b693d73ebe gevent dedicated plugin 2011-08-25 13:46:42 +02:00
roberto@dexter dfab80447b added a check for Riccardo 2011-08-24 18:24:45 +02:00
roberto@dexter bbde0c866a a couple of fixes, and reintroduction of string-based multiapp 2011-08-24 17:48:27 +02:00
roberto@mrspurr 7b3514f757 --emperor-throttle 2011-08-24 13:03:25 +02:00
roberto@mrspurr 6d5fb3b252 export cache and queue functions only if available 2011-08-20 11:12:32 +02:00
roberto@debian32 87e8f118d3 fix refcnt in async-disabled compilation 2011-08-19 16:35:16 +02:00
roberto@debian32 3ae78cc0a8 another bufsize fix 2011-08-19 16:28:44 +02:00
roberto@debian32 7ef921356f updated sharedarea 2011-08-19 15:22:20 +02:00
roberto@debian32 378185d997 added a build profile for uwsgi_pypy integration 2011-08-19 12:24:38 +02:00
roberto@debian32 c4b15a8509 changed final banner in library mode 2011-08-19 12:15:18 +02:00
roberto@debian32 96ef9d155b uwsgi.magic_table 2011-08-19 11:44:40 +02:00
roberto@debian32 d5e6412b20 uWSGI 0.9.9-rc1 2011-08-19 09:57:58 +02:00
roberto@debian32 eebe757c16 Added tag 0.9.9-rc1 for changeset fb168b0b8616 2011-08-19 08:51:26 +02:00
roberto@debian32 43a21d32cb fixed a stupid bug 2011-08-19 08:49:39 +02:00
roberto@debian32 9f9eb5ef17 improved apache2 SCRIPT_NAME/PATH_INFo handling 2011-08-19 08:48:15 +02:00
roberto@debian32 0116c62980 another refcnt fix 2011-08-19 07:06:29 +02:00
roberto@debian32 fae446e495 fix for 3.0-arch 2011-08-19 06:46:07 +02:00
roberto@debian32 6f7054df18 more tolerant cache and queue size 2011-08-18 14:27:21 +02:00
roberto@debian32 0f31c21f4a completed queue subsystem with test 2011-08-18 09:46:32 +02:00
roberto@debian32 bd3e234703 another xml app tag fix 2011-08-18 07:06:27 +02:00
roberto@gambit 71bfd63623 fixed xml app tag 2011-08-18 07:01:13 +02:00
unbit@localhost 98b89dc83c Added tag 0.9.9-beta1 for changeset 6945ee03c7ea 2011-08-18 06:33:20 +02:00
roberto@gambit 97ec789bbe fixed casting 2011-08-18 06:13:51 +02:00
roberto@debian32 14b403c046 fixed a post-buffering bug 2011-08-17 12:42:12 +02:00
roberto@debian32 bc01d25068 uWSGI can now be built as a shardd library 2011-08-17 11:21:22 +02:00
roberto@fedora64 69808c34a8 fixed callable and start_response refcnt 2011-08-16 17:00:15 +02:00
roberto@debian32 273181daf5 another threading fix 2011-08-16 08:00:09 +02:00
roberto@debian32 8d2394eba1 better name handling in --wsgi-file 2011-08-16 07:33:46 +02:00
roberto@debian32 6f5b468b11 fix threading bug in pyshell 2011-08-16 07:31:20 +02:00
roberta@mrspurr c9e759bc14 allow threads in gateways 2011-08-14 07:46:29 +02:00
roberto@debian32 e6d064f5c1 allows fastrouter cache to set modifier1 2011-08-13 11:25:06 +02:00
roberto@debian32 8f7ed02475 a bunch of lua fixes 2011-08-13 11:12:10 +02:00
roberto@debian32 f7edcebbdc added --fastrouter-use-code-string 2011-08-13 08:39:17 +02:00
roberto@debian32 a19b392ba6 applications list is now shared 2011-08-12 08:08:39 +02:00
roberto@mrspurr 287df9ef86 fixed a stupid bug with thread stacksize 2011-08-11 07:32:02 +02:00
roberto@juggernaut de7be379c4 shut up gcc on ubuntu lucid 2011-08-10 14:43:57 +02:00
roberto@debian32 1e4d41795c allows setting threads stacksize 2011-08-10 12:13:46 +02:00
roberto@debian32 e2e973a20e we are now at 0.9.9-dev 2011-08-09 08:25:09 +02:00
roberto@debian32 5d993fbfc0 implemented UWSGI_APPID var 2011-08-09 08:20:12 +02:00
roberto@debian32 a94a8ea287 added a check on spooler unlink 2011-08-05 06:53:43 +02:00
roberto@debian32 55d8677a46 fixed a spooler thread problem 2011-08-04 18:20:44 +02:00
roberto@debian32 4004aeb54e fileno() for wsgi.input 2011-08-04 16:53:39 +02:00
roberto@debian32 2de2898d86 fix a stupid bug 2011-08-04 16:28:47 +02:00
roberto@debian32 8c1b48a88d a new kick-ass feature for the spooler 2011-08-04 16:25:17 +02:00
roberto@debian32 9bd3022a5e a bunch of threading fixes in the spooler 2011-08-04 14:11:40 +02:00
roberto@debian32 eb0ce609f0 wakeup spooler (if possibile) after each submission 2011-08-04 11:15:24 +02:00
roberto@debian32 5353eba35b improved the pyshell 2011-08-04 07:05:39 +02:00
roberto@debian32 4f94ceed5e fix for solaris 2011-08-03 16:00:35 +02:00
roberto@debian32 cd29998b40 --pyshell and fix for wsgi.url_scheme in pep3333 2011-08-03 15:07:15 +02:00
roberto@debian32 9aad6be26a better realoding in lazy mode 2011-08-03 06:54:48 +02:00
roberto@debian32 19edee88bc fixed --log-master 2011-08-02 21:15:10 +02:00
roberto@debian32 42e6a7d024 wait max 60 seconds for gracefull reload 2011-08-02 20:36:16 +02:00
roberto@debian32 1890290d05 fixed reload-mercy in lazy mode 2011-08-02 20:28:31 +02:00
roberto@debian32 c85231be96 improved picasso test 2011-08-02 16:10:17 +02:00
roberto@debian32 0ca89771d6 fixed pump method 2011-08-02 16:01:06 +02:00
roberto@debian32 d203b12464 fixed --http-var 2011-08-02 15:48:54 +02:00
roberto@debian32 b64690bdd6 allow compilation of pump in python3 2011-08-02 15:38:41 +02:00
roberto@debian32 e76c696678 completed pump support 2011-08-02 15:31:39 +02:00
roberto@debian32 f1ad2090fc remove incompatible LDFLAGS 2011-08-02 15:13:21 +02:00
roberto@debian32 f0be3c3966 fixed rack.scheme 2011-08-02 15:02:26 +02:00
roberto@debian32 8b7abc956f first round for pump support 2011-08-02 13:56:52 +02:00
roberto@debian32 25a8af392b fixed a leak in web3 subhandler 2011-08-02 12:48:15 +02:00
roberto@debian32 ebe1b3497e updated web3 handler 2011-08-02 09:33:49 +02:00
roberto@debian32 6a7246fe5a a little fix 2011-07-31 19:47:54 +02:00
roberto@debian32 1d64e46fcd support for data:// in import/module 2011-07-31 19:42:24 +02:00
roberto@debian32 6d5e089e4e uwsgi.ZipImporter 2011-07-31 19:32:14 +02:00
roberto@debian32 845bc1d41b added data:// facility 2011-07-31 18:51:10 +02:00
roberto@solarixexpress 007cd73ac5 solaris fix 2011-07-31 19:13:01 +00:00
roberto@freebsd64 651a7e4078 added freebsd binary detection 2011-07-31 17:47:15 +02:00
roberto@debian32 c3423370ec added binary detection for sun 2011-07-31 16:07:36 +02:00
roberto@mrspurr 500f1e37f6 better binary detection in osx 2011-07-31 17:25:10 +02:00
roberto@debian32 699a9bfa8e better binary detection on linux 2011-07-31 15:39:36 +02:00
roberto@debian32 90aa7f0d0e fixed --set 2011-07-31 14:44:36 +02:00
roberto@debian32 527819703e added -S/--set option 2011-07-31 14:35:54 +02:00
roberto@debian32 47adc8fe48 added --http-socket and --fastcgi-socket 2011-07-29 14:26:07 +02:00
roberto@debian32 865ad5d631 virtualhosting for http protocol 2011-07-29 13:59:29 +02:00
roberto@debian32 877b99c1d5 extreme optimization for http protocol 2011-07-29 13:49:22 +02:00
roberto@debian32 45bb124200 fixed a typo 2011-07-29 10:04:10 +02:00
roberto@debian32 147af04342 fixed apache2 module, adding uWSGImaxVars directive (bug #31) 2011-07-29 08:06:13 +02:00
roberto@debian32 b30e54bdc1 close bug #35 2011-07-29 07:30:24 +02:00
roberto@debian32 1b7484cf22 closed bug #34 2011-07-29 07:27:03 +02:00
roberto@debian32 c04513f8bd fixed SERVER_PORT in http protocol handler 2011-07-29 06:13:50 +02:00
roberto@debian32 c29db6ee6f cache fixed WSGI values 2011-07-29 05:53:54 +02:00
roberto@debian32 0d60b001fb uwsgi.cache_update 2011-07-28 10:27:37 +02:00
roberto@dexter ea7d428c1b added UWSGI.signal_registered 2011-07-27 11:11:30 +02:00
roberto@dexter 55ac61dbb0 signal framework ported to ruby.rack plugin 2011-07-27 10:58:03 +02:00
roberto@mrspurr 048878b197 added uwsgi.signal to ruby interface 2011-07-27 08:27:24 +02:00
roberto@dexter 1e479de839 auto-set post-buffering in rack plugin 2011-07-26 09:46:11 +02:00
roberto@debian32 5b34f6c515 fixed multiprotocol uwsgi.sendfile 2011-07-26 07:06:46 +02:00
roberto@centos6 8fcf83769c a zombie cannot be avoided... 2011-07-25 08:58:17 +02:00
roberto@centos6 d1ca55da55 get rid of a zombie in http-only mode 2011-07-25 08:23:05 +02:00
roberto@gambit 375328623b Added tag 0.9.8.3 for changeset f4d3c4dcd7a6 2011-07-23 08:27:35 +02:00
roberto@gambit be15137a49 uWSGI 0.9.8.3 2011-07-23 08:26:42 +02:00
roberto@dexter 43d89b2eaf added --freebind option (Linux only) 2011-07-22 13:11:14 +02:00
roberto@fedora15 d590a189ed added support for systemd socket activation 2011-07-22 13:03:18 +02:00
roberto@dexter c26861bff6 fixed fd 0 inheritance for xinetd support 2011-07-22 11:11:03 +02:00
roberto@mrspurr b4923deae2 fixed OSX build 2011-07-21 18:50:00 +02:00
roberto@natty32 20e7a65d92 finalized zip import 2011-07-19 21:19:15 +02:00
roberto@natty32 fc895d105e added bootstrap2.py for uwsgi.SymZipImporter class 2011-07-19 20:28:45 +02:00
roberto@natty32 e0e8dbe6b6 added uwsgi.SymZipImporter class 2011-07-19 20:28:04 +02:00
roberto@sirius 8e5834dcbb Added tag 0.9.8.2 for changeset 7169ef1d68d3 2011-07-19 07:53:44 +02:00
roberto@natty32 668c173969 uWSGI 0.9.8.2 2011-07-19 07:36:11 +02:00
roberto@debian32 4c19a941eb disabled embedded loading in python 3.x 2011-07-18 19:18:00 +02:00
roberto@debian32 9761153ab0 symbol based python importer in C 2011-07-18 18:24:01 +02:00
roberto@debian32 140a1b1587 added a django template loader for embedded files 2011-07-16 09:15:14 +02:00
roberto@debian32 e5f5f40f3c added bootstrap.py 2011-07-16 08:20:52 +02:00
roberto@debian32 2e13622ecc build directory 2011-07-16 08:05:26 +02:00
roberto@debian32 a4fb281859 allow directories to be embedded 2011-07-16 08:01:07 +02:00
roberto@dexter 75ba4e2220 better translation in import by filename 2011-07-15 12:02:42 +02:00
roberto@dexter 24b17da2ea added AUTHORS file 2011-07-15 11:15:07 +02:00
roberto@dexter c4664fe6e3 thunder_lock enabled only in threading mode 2011-07-15 10:51:35 +02:00
roberto@debian32 a1ab298609 Changelog for 0.9.8.2 2011-07-15 05:53:05 +02:00
roberto@natty32 533f9f8323 fixed an ini and yaml parsing bug spotted by Raffaele Colace 2011-07-14 20:03:20 +02:00
roberto@sirius 6d5912f307 a couple of spooler improvements 2011-07-13 19:41:56 +02:00
roberto@centos6 3d2b7c136a drop privileges after chown-socket (second-try) 2011-07-12 20:58:40 +02:00
roberto@centos6 f25d147908 drop privileges after chown-socket 2011-07-12 20:54:35 +02:00
roberto@centos6 e119c8cc53 solaris fix 2011-07-12 20:31:48 +02:00
roberto@centos6 73e94350df return the name of the spoolfile on uwsgi.spool() 2011-07-12 20:20:55 +02:00
roberto@centos6 9d8ee5aec8 --chown-socket 2011-07-12 20:11:19 +02:00
roberto@sirius c3bbd5f54f fixed spooler decorators 2011-07-11 19:15:26 +02:00
roberto@natty32 e17be93cb6 fixed rack.input 2011-07-11 11:56:19 +02:00
roberto@natty32 1013ca340a uwsgi.embedded_data 2011-07-10 19:47:53 +02:00
roberto@natty32 b87e7c0af8 added embed_files 2011-07-10 19:31:12 +02:00
roberto@natty32 615348c5a1 new embed_config build_option 2011-07-10 18:13:02 +02:00
roberto@natty32 cae0f9bc2e fixed fd leaks generated by new signal improvements 2011-07-10 16:26:36 +02:00
roberto@sirius 93b23e3de0 fixed cache-server on 64bit 2011-07-07 12:22:36 +02:00
roberto@natty32 eebb00d2b3 cache-server implementation 2011-07-07 12:02:11 +02:00
roberto@natty32 11f9b04fd1 thunder lock (sigh) 2011-07-07 09:58:03 +02:00
roberto@natty32 bde996de75 added -f in rm for make clean 2011-07-07 09:44:57 +02:00
roberto@natty32 552163a3bd second try for fixing inheritance of build profiles 2011-07-07 09:35:14 +02:00
roberto@natty32 2e6af966a9 revert last useless fix 2011-07-07 09:27:38 +02:00
roberto@natty32 c1775967c8 fixed build system 2011-07-07 09:25:10 +02:00
roberto@natty32 034a0a594d remove json from unbitstaff 2011-07-07 09:11:26 +02:00
roberto@natty32 63a66ea82a added an hello_world 2011-07-07 08:35:23 +02:00
roberto@maverick64 6f155ebf17 spooler object debug 2011-07-06 19:43:28 +02:00
roberto@maverick64 f39d8cc5fb fixed spooler for python 3 2011-07-06 18:17:53 +02:00
roberto@maverick64 aecba7e710 export UWSGI_VASSALS_DIR even on stop-hook 2011-07-05 20:17:34 +02:00
roberto@maverick64 c365eeec76 fixed a typo 2011-07-05 15:06:51 +02:00
roberto@maverick64 5bd06402de added shebang in decoratortest.py 2011-07-05 14:56:23 +02:00
roberto@maverick64 ec899a45d5 added body to spooler 2011-07-05 14:55:10 +02:00
roberto@maverick64 513c9cee3d allow plugin to be written in C++ 2011-07-05 11:28:35 +02:00
roberto@mrspurr 850f2abd5c fixed psgi on osx 2011-07-05 07:50:27 +02:00
roberto@maverick64 8d7940ebee fixed plugin value in uwsgi.opt 2011-07-04 16:14:33 +02:00
roberto@maverick64 195e9c398e use TCP port '0' for auto-socket in http mode 2011-07-04 10:38:07 +02:00
roberto@longshot c998d6bd1b fixed a master bug in socketpair 2011-07-04 09:55:13 +02:00
roberto@maverick64 34be14ece1 updated unbit.ini 2011-07-04 09:17:34 +02:00
roberto@maverick64 c0d6f33d54 support SIGQUIT in emperor 2011-07-03 19:17:24 +02:00
roberto@maverick64 d5210283ca launch stop hook on emperor quit 2011-07-03 19:16:09 +02:00
roberto@maverick64 545784d7af fixed ticket #12 reported bugs 2011-07-03 19:08:22 +02:00
roberto@maverick64 e9726b1e75 fixed ticket #28 2011-07-03 12:59:58 +02:00
roberto@maverick64 e08b2cccf9 implemented workerN signal target 2011-07-03 12:55:18 +02:00
roberto@maverick64 0ba1b982d1 implemented target='workers' for signal infrastructure 2011-07-03 12:43:30 +02:00
roberto@maverick64 374c02c46e prefork/multithread uwsgi.signal_wait() implementation 2011-07-03 12:00:06 +02:00
roberto@maverick64 5ed59690a0 report time taken for each spooler job 2011-07-02 19:53:31 +02:00
roberto@maverick64 2de489f301 fixed uwsgi_log_verbose 2011-07-02 19:49:12 +02:00
roberto@maverick64 40a722294f added 'at' variable to the spooler 2011-07-02 11:04:25 +02:00
roberto@maverick64 9598c525cf export uwsgi.node in WSGI vars 2011-07-02 10:03:34 +02:00
roberto@maverick64 3ed6c5e943 added @lock decorator 2011-07-02 09:22:52 +02:00
roberto@maverick64 0f178c17ee report threading status in uwsgicc 2011-07-02 08:43:52 +02:00
roberto@maverick64 1c963b72a3 added @thread decorator 2011-07-02 08:35:08 +02:00
roberto@maverick64 bd1b3b8b12 allows spooler to manage signals 2011-07-01 15:17:43 +02:00
roberto@maverick64 f9a843dfd5 added @postfork decorator 2011-07-01 10:03:16 +02:00
roberto@maverick64 9df8f4ae2b better spooler check 2011-07-01 09:56:38 +02:00
roberto@maverick64 87f649b71b a new bunch of decorators 2011-07-01 09:48:54 +02:00
roberto@sirius 3585bb0a6e added spoolforever 2011-07-01 09:12:30 +02:00
roberto@sirius 750bbd64b2 new option --import, new api function uwsgi.signal_registered 2011-07-01 09:05:55 +02:00
roberto@maverick64 19c567cef3 fixed fastrouter nodes stats 2011-06-30 13:00:14 +02:00
roberto@maverick64 5024368854 gather statistics about subscribed fastrouter nodes 2011-06-30 12:56:13 +02:00
roberto@debian32 3200f88363 applied Riccardo Magliocchetti patch for spooler pid and uwsgicc 2011-06-28 15:14:49 +02:00
roberto@debian32 650c77d0d1 refactored cgroups 2011-06-28 06:46:43 +02:00
roberto@debian32 3fa29515f2 --emperor-broodlord added 2011-06-27 20:27:34 +02:00
roberto@debian32 012435747e first attempt of bloodlord mode 2011-06-27 18:18:24 +02:00
roberto@debian32 733077a437 added another example 2011-06-26 18:18:57 +02:00
roberto@debian32 6b3fa74800 fixed uwsgi.h indentation 2011-06-26 11:36:18 +02:00
roberto@freebsd64 d673627c79 FreeBSD fix and applied riccardo's patch 2011-06-26 11:35:18 +02:00
roberto@debian32 8b423d00e9 added priority keyword to spooler 2011-06-26 11:26:52 +02:00
roberto@gambit 201086c854 uWSGI 0.9.8.1 2011-06-25 10:34:50 +02:00
roberto@gambit 2441cf36b3 Added tag 0.9.8.1 for changeset fd8477b6348f 2011-06-25 10:33:43 +02:00
roberto@debian32 df0f2a549e TODO: survive to dynamic loading errors 2011-06-25 10:24:52 +02:00
roberto@debian32 9b7cbab37c preparing for official release... 2011-06-25 10:09:44 +02:00
roberto@debian32 ac46cb2371 a bit of debug junk 2011-06-25 10:08:42 +02:00
roberto@debian32 c858c88bb3 fixed a race condition 2011-06-25 09:52:42 +02:00
roberto@debian32 a05f5d9860 another series (the last i hope) of threading fixes 2011-06-25 09:36:59 +02:00
roberto@debian32 e6914b91e1 spooler task are now managed asap on startup 2011-06-25 08:13:15 +02:00
roberto@debian32 b624bd2d35 update psgix.harakiri to last spec 2011-06-25 08:03:28 +02:00
roberto@debian32 e3c9b2c0bf cheap+idle+lazy improved for threading 2011-06-25 07:58:40 +02:00
roberto@debian32 576a1e7cb2 fixed threadstate swap 2011-06-25 07:44:21 +02:00
roberto@debian32 55c3ba73d3 added Changelog for 0.9.8.1 2011-06-25 07:27:31 +02:00
roberto@debian32 2246d30bbe fixed threaded loading 2011-06-24 19:42:01 +02:00
roberto@goyle 789e333736 master_fixup on reloads 2011-06-24 07:41:01 +02:00
roberto@goyle 283904107f better master threading 2011-06-24 06:56:30 +02:00
roberto@goyle 8d92261852 re-enabled threads in master process 2011-06-23 20:50:14 +02:00
roberto@goyle e8f5d82b78 -propagate-touch 2011-06-22 12:40:00 +02:00
roberto@goyle 0a8643155e an attempt for a better touch reload in threading mode 2011-06-22 12:12:15 +02:00
roberto@goyle 61793201c7 fixed uwsgi.sendfile in threading mode 2011-06-22 11:14:02 +02:00
roberto@goyle 41f2982074 fixed stupid bug in wsgi.input readline 2011-06-22 07:19:49 +02:00
roberto@goyle 27b86f1b79 fixed a bug in dynamic touch reload 2011-06-21 17:19:28 +02:00
roberto@goyle d69892c91e @europython add --logto2 option 2011-06-21 14:53:50 +02:00
roberto@debian32 296549d1bf export %c in config files 2011-06-18 11:59:37 +02:00
roberto@debian32 7d2f147172 fixed libyaml support and support for modifiers in subscription requests 2011-06-18 11:31:38 +02:00
roberto@debian32 aa56f99ee2 reset random seed on first python spooler job 2011-06-18 09:32:23 +02:00
roberto@debian32 ca82b99f42 subscribe from file 2011-06-18 08:59:02 +02:00
roberto@debian32 d204a5b844 allow binding to port 0 (auto-assignment) 2011-06-18 07:50:37 +02:00
roberto@debian32 0a98550770 reset random seed on grunt 2011-06-18 06:58:01 +02:00
roberto@debian32 0c0c2736a7 maintain a constant mapping in vhost mode 2011-06-17 17:54:49 +02:00
roberto@debian32 27e2d984ce debug in virtualhosting 2011-06-17 17:41:48 +02:00
roberto@debian32 14eeae09b1 fix python3 + virtualenv 2011-06-17 16:31:55 +02:00
roberto@debian32 16eb47070d survive to task doing chdir() in the spooler 2011-06-17 16:20:02 +02:00
roberto@debian32 1f69f58593 fixed a stupid bug in non-async initialization 2011-06-17 08:44:32 +02:00
roberto@debian32 1b4421e013 better zeromq+clustering support 2011-06-17 08:11:56 +02:00
roberto@debian32 f13400d592 improved zeromq support 2011-06-17 07:52:38 +02:00
roberto@mrspurr e29f0323ea fixed make clean 2011-06-17 07:33:53 +02:00
roberto@debian32 15a582d046 allow clustering without a socket 2011-06-17 07:26:36 +02:00
roberto@mrspurr 1e01f8be17 fixed a typecast in fastcgi 2011-06-17 06:39:44 +02:00
roberto@debian32 8cc73991a3 added checks for decorators 2011-06-16 13:52:22 +02:00
roberto@debian32 ecce74ade5 less verbose logging in inotify 2011-06-16 10:16:06 +02:00
roberto@debian32 836efaaf70 less verbose logging in python api for clustering 2011-06-16 07:20:15 +02:00
roberto@debian32 46f8e7dc00 less verbose log in cluster joining 2011-06-16 07:17:35 +02:00
roberto@mrspurr 88cd033ca6 refactored clustering 2011-06-16 07:08:56 +02:00
roberto@debian32 984df3bcdf added signal sending in uwsgicc 2011-06-15 19:05:14 +02:00
roberto@debian32 7673cdb1aa refactored uwsgi_parse_response to uwsgi_parse_packet 2011-06-15 14:01:00 +02:00
roberto@debian32 8af700ce37 fixed rpc 2011-06-15 12:30:01 +02:00
roberto@mrspurr ffb8752190 report corrent worker id in cheap mode 2011-06-15 07:04:07 +02:00
roberto 71fa3ab3af report max buffer_size on pktsize error 2011-06-14 14:07:48 +00:00
roberto@dj1 09501cfa74 remove pipe in uwsgi_daemon 2011-06-14 13:37:33 +00:00
roberto@dj1 d84ae12733 fixed a fd leak in attach-daemon 2011-06-14 13:37:00 +00:00
roberto@dj1 05f292abe6 use setsid in attach-daemon 2011-06-14 13:22:14 +00:00
roberto@sirius a75833d322 OSX fixes 2011-06-14 11:26:03 +02:00
roberto@debian32 ca3f56de5c Zerg mode added 2011-06-14 11:24:25 +02:00
roberto@debian32 9d75f2c9c7 added psgix.harakiri.supported 2011-06-13 19:13:12 +02:00
roberto@debian32 a58cbf92b0 added psgix.harakiri 2011-06-13 16:45:19 +02:00
roberto@debian32 7bac76fae5 added PLACK_SERVER 2011-06-13 11:55:42 +02:00
roberto@debian32 9c71b39edd fixed rpc 2011-06-13 09:07:49 +02:00
roberto@debian32 52f731c6b7 fixed argv clobbering in command line module functions 2011-06-13 08:17:36 +02:00
roberto@dj1.djangocloud.com 735d1cb689 fixed fastrouter 2011-06-12 13:19:39 -05:00
roberto@debian32 5a0977f412 allows magic vars in sqlite3 db 2011-06-12 19:58:38 +02:00
roberto@dj1 1da1fccbc7 fixed plugin loading 2011-06-12 12:19:23 -05:00
roberto@debian32 ca5a528818 added UWSGI_FASTROUTER_KEY var 2011-06-12 11:45:30 +02:00
roberto@debian32 a9ef806a37 added flaskpost to address a bug reported on post-buffering 2011-06-12 09:04:59 +02:00
roberto@debian32 de112b7788 no more than 1 'async queue is full' message per-second 2011-06-12 07:16:24 +02:00
roberto@debian32 ef7baba274 process options in reverse order for better templating 2011-06-12 06:51:45 +02:00
roberto@debian32 3a9d13b011 --cron option, thanks Simon Litchfield for the idea 2011-06-11 15:05:20 +02:00
roberto@debian32 5b5493aab0 --vassals-start-hook and --vassals-stop-hook 2011-06-11 11:56:21 +02:00
roberto@debian32 5f208d8f12 remove the old proxy plugin, bug #8 2011-06-11 10:54:59 +02:00
roberto@debian32 47c077d066 closed bug #14 2011-06-11 10:45:58 +02:00
roberto@debian32 d2ac69b6c1 applied leonid borisenko patch for better automagic plugin loading 2011-06-11 09:47:42 +02:00
roberto@dj1 8860cac7dd close unneded fd in subemperor and vassals 2011-06-08 13:54:50 -05:00
roberto@debian32 28bcc73c70 reintroduced clang support 2011-06-07 21:26:07 +02:00
roberto@netbsd64 af20c2d8f0 fix CMSG_SPACE mess 2011-06-07 22:37:55 +02:00
roberto@mrspurr 44213ca510 move msg_control union to end of struct wsgi_request (as suggested by Riccardo Magliocchetti) 2011-06-07 20:02:24 +02:00
roberto@mrspurr ab21a1ac00 applied Piotr Sikora fix for OpenBSD/NetBSD 2011-06-07 20:00:36 +02:00
roberto@dj1 a67f366501 fix for abstract socket without prefix 2011-06-07 06:21:09 -05:00
roberto@mrspurr b32251e5aa osx launchd examples 2011-06-07 06:37:54 +02:00
roberto@gambit 16e0accb74 uWSGI 0.9.8 2011-06-05 08:28:03 +02:00
roberto@gambit c6ce291cbf Added tag 0.9.8 for changeset 42efe1f32900 2011-06-05 08:27:51 +02:00
roberto@debian32 b7525475d8 ready for 0.9.8 release 2011-06-05 08:20:23 +02:00
roberto@debian32 f35a36ac02 set a mercy mode for INT/QUIT 2011-06-05 07:38:58 +02:00
roberto@netbsd64 3b53f89a24 netbsd fix 2011-06-05 09:17:38 +02:00
roberto@debian32 764d94e41b support for abstract unix socket prefixed with \0 2011-06-04 08:55:49 +02:00
roberto@indianajones 0292e15497 add /lib to linker on SunOS-derived systems 2011-06-02 19:35:05 +01:00
roberto@debian32 bde4ac7b2f uWSGI 0.9.8-rc4 2011-06-02 18:53:49 +02:00
roberto@debian32 c71fa3abd1 Added tag 0.9.8-rc4 for changeset 0f1f3924ee53 2011-06-02 18:53:38 +02:00
roberto@indianajones d2abdb5d3a fix accept() to receive the correct ip 2011-06-02 18:44:48 +01:00
roberto@indianajones 1392791837 OpenIndiana is now officially supported 2011-06-02 15:15:35 +01:00
roberto@goyle 6f7d9634d5 allows log-date 2011-06-02 12:08:56 +02:00
roberto@goyle 82b95114a8 added welcome.py 2011-06-02 11:38:18 +02:00
roberto@debian32 d90e701acd use int in uwsgi.version_info 2011-06-01 13:02:33 +02:00
roberto@debian32 42993022bb python3 fix 2011-06-01 12:55:20 +02:00
roberto@dj1 29b1e46252 uwsgi.version_info 2011-06-01 05:52:46 -05:00
roberto@sirius 260cea639f better myadmin.py 2011-06-01 10:04:57 +02:00
roberto@sirius 208aea8aca two new management flag for backlog queue 2011-06-01 10:00:17 +02:00
roberto@sirius f164d401d3 another uwsgi_log fix 2011-06-01 09:47:58 +02:00
roberto@dj1 5e1c34a08b really fix uwsgi_log 2011-06-01 02:15:53 -05:00
roberto@debian32 9c7b596a0d fixed uwsgi_log 2011-06-01 08:38:51 +02:00
roberto@debian32 5ff34ac6d0 a couple of admin plugin fixes 2011-06-01 08:12:50 +02:00
roberto@debian32 e304e34929 throw exception on too much big spool requests 2011-06-01 07:11:54 +02:00
roberto@dj1 6d7848248d added --early-emperor option 2011-05-31 08:44:26 -05:00
roberto@sirius dbc0da0586 support for idle mode in single process mode 2011-05-31 14:26:57 +02:00
roberto@debian32 fecdcf9d10 allows sub-emperors (emperors generated by emperors) 2011-05-31 08:56:03 +02:00
roberto@sirius bfd0ab2301 fixed a typo 2011-05-30 19:10:01 +02:00
roberto@sirius 8002777e75 uWSGI 0.9.8-rc3 2011-05-30 19:04:05 +02:00
roberto@debian32 d57d5acb30 --idle mode 2011-05-29 06:52:47 +02:00
roberto@debian32 43e6664dd9 --cheap option 2011-05-28 19:43:29 +02:00
roberto@dj1 d0c6dff83e --add-header option 2011-05-28 05:20:48 -05:00
roberto@dj1 54b40f5978 better cgroup support 2011-05-27 14:23:22 -05:00
roberto@dj1 1c59c03261 unlimited sockets for fastrouter 2011-05-27 08:55:15 -05:00
roberto@dj1 ce23fd38ab better emperor+master mode 2011-05-27 05:11:41 -05:00
roberto@dj1 4818efa7de emperor+amqp fixes 2011-05-27 04:07:07 -05:00
roberto@dj1 ea19e74229 better netlink ns detection 2011-05-27 03:21:21 -05:00
roberto@dj1 fe353de5a8 fixed netlink compilation 2011-05-27 01:58:43 -05:00
roberto@dj1 1d89266f2e unlimited shared sockets 2011-05-27 01:39:01 -05:00
roberto@debian32 61d79394ca --fastrouter-subscription-slot 2011-05-26 05:35:43 +02:00
roberto@debian32 491f2828b5 --no-fd-passing 2011-05-26 05:29:01 +02:00
roberto@nexenta32 431e05d4f4 fixed ifaddrs support 2011-05-26 06:17:46 +02:00
roberto@solarisexpress ae6780a487 remember: do not use the word 'sun' as variable on solaris... 2011-05-26 04:54:55 +00:00
roberto@debian32 5707a70141 added --log-socket 2011-05-25 08:57:13 +02:00
roberto@debian32 e9a7bd7da1 add abstract unix socket 2011-05-23 21:50:04 +02:00
roberto@debian32 91e45daf6c better unix socket support in abstract namespace (Linux only) 2011-05-23 16:10:27 +02:00
roberto@debian32 9f69998075 grunt improvement 2011-05-23 11:43:22 +02:00
roberto@debian32 4f6270976b fixed python3.x spooler 2011-05-22 14:07:01 +02:00
roberto@debian32 328caa43f2 allow --auto-snapshot to take a value 2011-05-22 11:56:58 +02:00
roberto@debian32 368408374a preliminary snapshotting support 2011-05-22 11:43:28 +02:00
roberto@debian32 c3a90db493 uWSGI 0.9.8-rc2 2011-05-21 08:10:03 +02:00
roberto@debian32 5bc0320877 Added tag 0.9.8-rc2 for changeset e91bc724325e 2011-05-21 08:09:49 +02:00
roberto@debian32 622ed620b9 fixed python 3.1 2011-05-21 08:03:22 +02:00
roberto@debian2 1b859413de add mercurial revision to uWSGI version string 2011-05-21 07:43:49 +02:00
roberto@maverick64 95432fd8e3 added --die-on-term 2011-05-19 20:35:47 +02:00
roberto@freebsd64 b3f3c5d7b3 fixed touch reload 2011-05-19 09:33:25 +02:00
roberto@debian32 02cef20462 another fix for wsgi.input 2011-05-19 08:33:11 +02:00
roberto@debian32 3edebe34ae improved upload test 2011-05-18 21:15:41 +02:00
roberto@longshot 28c9b75fb5 wsgi.input fix 2011-05-18 21:10:18 +02:00
roberto@fedora15 a2735e10b7 report number of vassals to systemd 2011-05-17 08:57:50 +02:00
roberto@fedora15 e03d26fd63 report emperor dead status to systemd 2011-05-17 08:36:54 +02:00
roberto@sirius 7c4c346e64 fix systemd on unsupported platform 2011-05-17 08:29:33 +02:00
roberto@fedora15 67b3c0c4a8 systemd integration 2011-05-17 08:26:39 +02:00
roberto@fedora15 dadca785e4 initial systemd support 2011-05-16 17:25:38 +02:00
roberto@debian32 accebe5597 add --log-prefix option 2011-05-16 10:06:47 +02:00
unbit@gambit 792965bedd uWSGI 0.9.8-rc1 2011-05-14 09:57:15 +02:00
unbit@localhost 1bb1bafe0c Added tag 0.9.8-rc1 for changeset d1e57707f631 2011-05-14 09:56:41 +02:00
roberto@debian32 28c11324ca merge 2011-05-14 09:34:29 +02:00
roberto@debian32 42d940c38e a bit of refactoring 2011-05-14 09:34:03 +02:00
roberto@freebsd64 c1ea05b925 fixed profiler compilation in older python 2011-05-14 07:08:33 +02:00
roberto@debian32 9435693865 removed old/useless writers.c 2011-05-13 18:49:31 +02:00
roberto@debian32 14da582637 various static file fixes 2011-05-13 18:46:21 +02:00
roberto@debian32 b2d4a795a1 various ruby.rack fixes 2011-05-13 18:19:26 +02:00
roberto@sirius 493696705b another off_t to size_t fix 2011-05-13 16:52:21 +02:00
roberto@debian32 d827c6f09a moved rack.input to the new POST api 2011-05-13 16:46:06 +02:00
roberto@debian32 df000b0cb2 support for jemalloc 2011-05-12 12:55:07 +02:00
roberto@debian32 d9630a32c7 added support for tcmalloc 2011-05-12 12:49:07 +02:00
roberto@debian32 71cc6f61bd fixed a stupid (really stupid) bug in uwsgi.core allocation 2011-05-11 19:04:52 +02:00
roberto@debian32 46eb832cc7 set in_request per core 2011-05-11 18:47:42 +02:00
roberto@debian32 11b2e4b430 lock goodbye_cruel_world in threading mode 2011-05-11 17:08:02 +02:00
roberto@debian32 11775532ee applied leonid patch for symlinks 2011-05-11 15:49:59 +02:00
roberto@debian32 f3388db8ba do not link core libraries in plugins 2011-05-11 12:28:15 +02:00
roberto@sirius 25ac86393f use size_t instead of off_t 2011-05-11 12:05:48 +02:00
roberto@debian32 b3432a95e1 finally fixed wsgi.input 2011-05-11 11:55:28 +02:00
roberto@debian32 e34d169fa6 merge 2011-05-11 06:24:11 +02:00
roberto@debian32 de84accb7a removed unused variable in pyerl 2011-05-11 06:23:40 +02:00
roberto@sirius 187577cbb5 fixed a stupid typo 2011-05-10 09:53:54 +02:00
roberto@debian32 72109b72d2 various rack fixes 2011-05-10 09:36:07 +02:00
roberto@debian32 f6c01d11e9 completed ruby 1.9 fiber support 2011-05-10 08:50:06 +02:00
roberto@debian32 d695ef4f57 removed garbage 2011-05-09 21:41:55 +02:00
roberto@debian32 16c6dcc573 better threading reload 2011-05-09 21:27:08 +02:00
roberto@debian32 3df19b286a support for plugin as symlinks 2011-05-09 20:18:49 +02:00
roberto@debian32 6f1b08762d adde fixup hook handler 2011-05-09 09:43:55 +02:00
roberto@debian32 a4a379f9d6 rack ported to new socket api 2011-05-07 09:32:49 +02:00
roberto@mrspurr 3d3d0304bc plugin autoloading (finally) 2011-05-07 09:21:07 +02:00
roberto@natty32 26135018a3 added check for patl method in psgi response 2011-05-06 08:09:30 +02:00
roberto@debian32 4bd381bb99 big PSGI update 2011-05-06 14:17:01 +02:00
roberto@debian32 cf08972e82 first round of memleak hunting in psgi/perl 2011-05-06 10:12:59 +02:00
roberto@natty32 d57a58d1e7 psgi input fix 2011-05-06 00:16:57 +02:00
roberto@natty32 f10789965e added seek to psgi custom object 2011-05-05 17:08:52 +02:00
roberto@natty32 94145bd300 temp --psgi-custom-input option 2011-05-05 17:04:51 +02:00
roberto@natty32 cdcb61d10d signal on python thread fix 2011-05-05 02:47:04 +02:00
roberto@natty32 56146a34af python get line number/profier fix 2011-05-05 02:40:53 +02:00
roberto@natty32 991e818449 fixes for python2.6 and forcing -bash in perl 2011-05-05 02:25:17 +02:00
roberto@natty32 80083cba76 funny hack to have a consistent __FILE__ in perl 2011-05-04 17:43:09 +02:00
roberto@natty32 2c44fd5aa2 fix stdout/stderr in python3 2011-05-04 15:39:24 +02:00
roberto@natty32 1561dd38fc another PSGI loading fix 2011-05-04 05:27:32 +02:00
roberto@natty32 8152648f66 psgi loading improvement 2011-05-04 04:59:01 +02:00
roberto@natty32 c1507d0381 put master logging in non-blocking mode 2011-05-04 03:33:44 +02:00
roberto@natty32 f0fb603af2 debug send/recv log buffer 2011-05-04 03:24:44 +02:00
roberto@natty32 93e891153f fixed sqlite3 support 2011-05-03 18:45:04 +02:00
roberto@natty32 26ece717b6 added support for sqlite3 configuration 2011-05-03 18:35:49 +02:00
roberto@natty32 93767335ca added --profiler 2011-05-03 15:01:51 +02:00
roberto@natty32 7cbe751a39 added --perl-local-lib 2011-05-02 17:12:32 +02:00
roberto@natty32 c45df83f19 set buffer size in $/ 2011-05-02 13:25:36 +02:00
roberto@natty32 fabce61a58 add PLACK_ENV and -bash 2011-05-02 12:11:38 +02:00
roberto@natty32 5c9ccae598 added PSGI streamer test 2011-05-02 08:44:50 +02:00
roberto@natty32 6c9d7239f2 uGreen support added to perl 2011-05-02 08:36:57 +02:00
roberto@natty32 4b75e2577e preliminary async/nonblocking support for PSGI 2011-05-02 07:58:16 +02:00
roberto@natty32 08c9d942a4 lazy mode support 2011-05-01 17:31:54 +02:00
roberto@natty32 3b59b4ad21 psgi: allows multiline headers 2011-05-01 17:01:05 +02:00
roberto@natty32 7682eec52a do not die on perl die() :P 2011-05-01 16:42:01 +02:00
roberto@sirius 694517bbe7 export all the required psgi.* vars and all of the supported psgix.* 2011-05-01 15:37:25 +02:00
roberto@natty32 7f443fdd05 allow globbed-pythonpath 2011-04-27 16:28:44 +02:00
roberto@natty32 01ab891c11 unlimited pythonpath entries 2011-04-27 15:56:33 +02:00
roberto@natty32 052aacfd36 fixed --map-socket 2011-04-27 15:46:00 +02:00
roberto@natty32 80a6d2ccfb various fixes in multiple sockets and support for file piped via stdin 2011-04-27 14:15:01 +02:00
roberto@debian32 b4ce175bdf add --master to carbon/graphite example 2011-04-27 08:08:59 +02:00
roberto@debian32 f6f52d32dc fixed a typo 2011-04-27 08:07:19 +02:00
roberto@debian32 865b2de9bb added an example script for graphite/carbon update 2011-04-27 08:04:45 +02:00
roberto@debian32 4a8233a041 support for libzmq 2.0 2011-04-26 19:39:40 +02:00
roberto@natty32 f856ad78a3 added --log-zeromq 2011-04-26 17:26:40 +02:00
roberto@debian32 653267cbe6 added libyaml support, for future advanced implementations 2011-04-26 08:45:44 +02:00
roberto@debian32 8b53df27ab gcc-4.6 fixes and applied Riccardo Magliocchetti patch for libm 2011-04-26 07:38:10 +02:00
roberto@debian32 c4b7c2b58c fix build without zeromq 2011-04-25 16:56:06 +02:00
roberto@maverick64 66f82f364c fixed clustering 2011-04-25 09:50:11 +02:00
roberto@maverick64 6d269607d2 allow clustering + zeromq 2011-04-25 09:38:26 +02:00
roberto@maverick64 8370977e5b fixed indentation 2011-04-25 07:15:41 +02:00
roberto@maverick64 e2c335ff73 threaded zeromq/mongrel2 support 2011-04-25 07:13:23 +02:00
roberto@maverick64 816b9d0343 refactored zeromq 2011-04-24 18:50:44 +02:00
roberto@maverick64 2922e1ba35 slowdown vassals spawn 2011-04-24 07:38:38 +02:00
roberto@maverick64 c86f341d29 first part of --socket-protocol option 2011-04-22 09:34:50 +02:00
roberto@maverick64 73cdd68283 fixed modifier1 30 2011-04-22 09:18:07 +02:00
roberto@maverick64 81641686bc various fixes 2011-04-22 08:51:29 +02:00
roberto@maverick64 14c58c8e62 fixed preforking+threading 2011-04-22 07:53:32 +02:00
roberto@maverick64 74b8f2587c prototype for uwsgidump protocol 2011-04-21 19:28:02 +02:00
roberto@mrspurr bebe041061 added psgi full streaming support 2011-04-21 06:24:41 +02:00
roberto@msrpurr 2e5d3d2952 fixed response size in PSGI 2011-04-21 04:26:58 +02:00
roberto@mrspurr c2d155b8ff --inherit and --vassals-inherit 2011-04-20 21:33:56 +02:00
roberto@natty32 fda368ff08 added support for mongrel2 tnetstrings 2011-04-20 11:49:41 +02:00
roberto@natty32 19cf592e77 fastcgi optimization 2011-04-20 09:32:37 +02:00
roberto@natty32 260cac6b59 fixed zeromq post-file close 2011-04-19 18:19:08 +02:00
roberto@natty32 673275e708 multiprotocol refactoring 2011-04-19 18:14:40 +02:00
roberto@freebsd64 a6bc778c25 conditionally compile libuuid 2011-04-19 20:46:31 +02:00
roberto@centos32 ef2f5879b6 conditionally compile netlink support 2011-04-19 13:46:26 +02:00
roberto@sirius ee725bf625 fixed compilation in no-zmq environments 2011-04-19 11:35:03 +02:00
roberto@natty32 5388fa442c completed zeromq support 2011-04-19 08:34:03 +02:00
roberto@natty32 913493fd2e mongrel2/zeromq support added 2011-04-19 06:59:34 +02:00
roberto@natty32 6d4a8c6619 added a pure-zeromq loop engine 2011-04-18 20:00:26 +02:00
roberto@natty32 4a57115336 edge triggered events support 2011-04-18 17:07:13 +02:00
roberto@natty32 1dd754a0d5 fallback to read/write instead of sendfile in fastcgi mode 2011-04-18 06:32:52 +02:00
roberto@natty32 509b78d906 fastcgi fixes 2011-04-18 05:04:11 +02:00
roberto@natty32 363366d012 preliminary fastcgi support 2011-04-17 07:35:15 +02:00
roberto@natty32 26d4fd4e00 fixed uwsgi protocol support 2011-04-16 20:02:27 +02:00
roberto@natty32 09ee97e775 first destructive commit for uWSGI 0.9.8 2011-04-16 19:41:58 +02:00
roberto@natty32 1400a95cec added JSON support to the Emperor 2011-04-14 09:38:06 +02:00
roberto@natty32 5e96c4ca79 fixed json support with pkg-config 2011-04-14 09:10:03 +02:00
roberto@sirius 3c068b2a00 fixed http support 2011-04-14 09:47:04 +02:00
roberto@sirius 81fd7757c1 JSON support, thanks jansson 2011-04-14 09:32:17 +02:00
roberto@natty32 1db64b72ae fixed build of PSGI plugin on non-Apple platform 2011-04-13 13:27:32 +02:00
roberto@natty32 ab1bed236c use close-on-exec instead of close() on osx reload 2011-04-13 07:38:46 +02:00
roberto@debian64 e503999392 fixed virtualhosting with dynamic virtualenv 2011-04-12 10:34:36 +02:00
roberto@dj1 2392eb7e0b fixed wait in emperor 2011-04-08 03:25:16 -05:00
roberto@dj1 c62b54f18d added vassal loyalty concept 2011-04-08 02:43:05 -05:00
roberto@natty32 603d46c1ae merge 2011-04-07 08:46:34 +02:00
roberto@natty32 c0e0ae551d use binary stream for wsgi.input in Python 3.x 2011-04-07 08:45:59 +02:00
unbit@localhost a0a2507c05 Added tag 0.9.7.2 for changeset a5f13497b392 2011-04-06 09:50:01 +02:00
roberto@natty32 6eed48b28d updated Changelog and copyright year 2011-04-06 09:29:46 +02:00
roberto@netbsd64 9c5d289098 better locking for NetBSD and OpenBSD 2011-04-06 08:16:03 +02:00
roberto@solarisexpress 42ab7f23d8 added timegm to solaris 2011-04-06 06:03:17 +00:00
roberto@natty32 c9c2f4232e preparing for 0.9.7.2 release 2011-04-06 05:06:38 +02:00
roberto@longshot d4f23cc6bd use realpath() for document_root 2011-04-05 20:55:48 +02:00
roberto@natty32 b0db67d4d4 refactored post limit management 2011-04-05 16:51:40 +02:00
roberto@natty32 703cad6715 disallow empty socket names 2011-04-05 11:32:15 +02:00
roberto@natty32 667d67460f do not build netlink support (still useless for non-third-party plugins) 2011-04-05 09:00:58 +02:00
roberto@natty32 35cf9ae328 implemented exc_info in WSGI start_response and added --reload-on-as and --reload-on-rss 2011-04-05 08:58:22 +02:00
roberto@natty32 c04131af4b fixed syslog support 2011-04-04 17:17:47 +02:00
roberto@natty32 9cc4db1a12 various fixes 2011-04-04 09:46:17 +02:00
roberto@natty32 b326500913 --static-map mountpoint=documentroot option 2011-04-04 08:31:17 +02:00
roberto@natty32 a26579fcf5 better plugin loading 2011-04-03 08:18:51 +02:00
roberto@natty32 a2b9c44433 -ldl should be used only for Linux 2011-04-02 15:57:57 +02:00
roberto@natty32 c3b97da1d4 various Riccardo Magliocchetti build fixes 2011-04-02 15:26:00 +02:00
roberto@natty32 048cf0232a nailed connection between emperor and rabbitmq 2011-04-01 16:11:18 +02:00
roberto@natty32 89c113bee6 added EXILE mode for vassals 2011-04-01 08:35:20 +02:00
roberto@natty32 6b9969a302 allow emperor config files to be taken via http 2011-04-01 08:09:34 +02:00
roberto@natty32 a6e7513d2a declare exchange automatically 2011-04-01 07:13:09 +02:00
roberto@natty32 8a04f4810f allow vassals configuration to be stored on amqp/rabbitmq servers 2011-04-01 06:31:54 +02:00
roberto@natty32 1d9d443de0 amqp/rabbitmq emperor fixes 2011-04-01 05:17:50 +02:00
roberto@natty32 00e5809a71 preliminary amqp/rabbitmq support for emperor 2011-04-01 03:14:51 +02:00
roberto@freebsd64 07ba4a040b fixed freebsd kvm_open 2011-03-30 20:48:01 +02:00
roberto@mrspurr 7b319d230a allow building of psgi plugin without ithreads 2011-03-30 08:03:48 +02:00
roberto@natty32 641bc2daec fixed unbitstaff build profile 2011-03-29 12:06:13 +02:00
roberto@dj2 fbaa30cc08 various fixes 2011-03-28 11:31:40 -05:00
roberto@dj2 a0c2c9056b fixed a couple fo emperor race conditions 2011-03-28 09:37:17 -05:00
roberto@dj2 30ab5fd76b added --exit-on-reload 2011-03-28 07:31:51 -05:00
roberto@dj2 30beab4017 fixed a regression in setgroups() 2011-03-28 05:38:29 -05:00
roberto@dj2 4ec1493b09 fixed subscription system 2011-03-28 04:29:04 -05:00
roberto@dj2 e7cbe9709e build netlink support in Linux 2011-03-28 04:17:07 -05:00
roberto@dj2 aacaeba525 shared sockets support 2011-03-28 04:15:31 -05:00
roberto@dj2 6e4da5efb7 add netlink library 2011-03-28 04:11:31 -05:00
roberto@natty32 87443a4ff2 Added tag 0.9.7.1 for changeset 486e7760bcbc 2011-03-26 09:39:57 +01:00
roberto@natty32 9746759c68 fixed changelog before official release 2011-03-26 09:39:53 +01:00
roberto@natty32 170ee2b98a date was wrong in 0.9.7.1 2011-03-26 09:38:21 +01:00
roberto@natty32 938fb777dd uWSGI 0.9.7.1 2011-03-26 09:36:11 +01:00
roberto@natty32 33e1aafcd1 Added tag 0.9.7.1 for changeset d9b9b540f7dc 2011-03-26 09:35:31 +01:00
roberto@natty32 597ee90041 add sys.abiflags if necessary 2011-03-26 09:27:30 +01:00
roberto@natty32 e87e54ea28 allow --namespace-net and fix python library name 2011-03-26 09:18:52 +01:00
roberto@natty32 5c64c1ac3f fixed post-buffering without pep3333-input 2011-03-25 19:11:53 +01:00
roberto@natty32 c611cbc2ca fixed current_wsgi_req in multithreading without cores 2011-03-23 11:59:05 +01:00
roberto@sirius 9d051f4171 fixed a buf on older OSX versions (i hope) 2011-03-22 19:34:12 +01:00
roberto@sirius 6aee788678 fixed cmsg parsing 2011-03-22 17:21:19 +01:00
roberto@natty32 425a45caa7 updated banner message in debug mode 2011-03-22 17:02:20 +01:00
roberto@natty32 0571601e02 added --map-socket 2011-03-22 14:55:54 +01:00
roberto@natty32 c1992c8c7a added --check-cache 2011-03-22 12:12:03 +01:00
roberto@natty32 bd913870c7 fixed setup.py 2011-03-21 10:36:52 +01:00
roberto@natty32 7a479dd47f add 304/If-Modified-Since support for --check-static <dir> 2011-03-21 10:31:50 +01:00
roberto@natty32 7ae77aa58d added UWSGI_CACHE_GET dynamic variable 2011-03-20 21:24:32 +01:00
roberto@natty32 97a4260d44 added --pidfile2 and --logfile-chown 2011-03-20 08:05:27 +01:00
roberto@mrspurr b90d711764 allow python modules to be on http server 2011-03-20 07:51:56 +01:00
roberto@mrspurr 22de5b523e reintroduce modifier1 30 2011-03-19 17:03:00 +01:00
roberto@mrspurr 5798b824c0 forbid daemonizing in vassal mode 2011-03-19 11:03:16 +01:00
roberto@goyle 4cbf6cfc33 various fixes in touch_reload 2011-03-19 09:33:28 +01:00
roberto@mrspurr 8b55460156 added persistence for queue 2011-03-18 20:20:36 +01:00
roberto@mrspurr a61d48a451 fixed stackless support 2011-03-18 08:14:12 +01:00
roberto@mrspurr b9f4d57d67 applied activestate fix for --root support in setup.py 2011-03-18 07:15:10 +01:00
roberto@natty32 92cd36d14d ready for first stable release 2011-03-17 09:15:52 +01:00
roberto@natty32 f74e61b126 fixed psgi compilation 2011-03-16 21:29:52 +01:00
roberto@natty32 c8b4ba2b5b updated iobound_async example and improved pep3333-input 2011-03-16 20:54:54 +01:00
roberto@natty32 0a15ba1c5b remove stackless support, move it to async plugin 2011-03-16 13:12:50 +01:00
roberto@natty32 7ee5948233 better error reporting on failed open/fopen 2011-03-16 12:14:41 +01:00
roberto@natty32 85c8bcf9d2 removed memory leak in greenlet plugin 2011-03-16 11:12:55 +01:00
roberto@natty32 67394c6664 added greenlet plugin 2011-03-16 11:02:05 +01:00
roberto@silente 66ef7d8229 remove uGreen compilation on unsupported platforms 2010-12-29 23:06:47 +01:00
roberto@solarisexpress 3773bc69f2 fixed ldap solaris support 2011-03-16 09:48:52 +00:00
roberto@natty32 912416b119 fixed openldap support 2011-03-16 09:45:15 +01:00
roberto@solarisexpress 7dfe125013 solaris fixes 2011-03-16 09:39:02 +00:00
roberto@mrspurr 87db34ef0b removed setjmp code 2011-03-16 07:46:11 +01:00
roberto@natty32 d4f75ab53c re-added ugreen support (better and faster) 2011-03-16 07:28:23 +01:00
roberto@natty32 dc97e8fce5 new help system 2011-03-15 12:14:22 +01:00
roberto@natty32 b3965d9d67 updated async support 2011-03-15 10:45:23 +01:00
roberto@natty32 7ee90d1e12 fixed python uwsgi.cache_get 2011-03-12 14:52:11 +01:00
roberto@sirius 9d8b373e4f uWSGI 0.9.7-rc3 2011-03-12 14:21:16 +01:00
roberto@natty32 a068a7eb5b added support for cache backing store 2011-03-12 14:14:43 +01:00
roberto@natty32 aa004c1893 less verbose file monitoring 2011-03-12 09:31:14 +01:00
roberto@natty32 9a9c149370 fixed emperor waitpid and erlang list encoding 2011-03-12 07:35:41 +01:00
roberto@natty32 9e6e226e4b improved snmp agent and fixed cache modifier 4 2011-03-11 11:55:44 +01:00
roberto@mrspurr 06c2aed0e0 add modifier 3 in cache plugin 2011-03-11 10:57:39 +01:00
roberto@natty32 df4f610cfc preliminary cpu-affinity support 2011-03-11 07:37:43 +01:00
roberto@natty32 64249abae1 improved ldap support 2011-03-10 19:14:13 +01:00
roberto@sirius 94f4be58bd auto configure ldap support 2011-03-10 10:40:56 +01:00
roberto@sirius 35987d3741 added --allowed-modifiers 2011-03-10 10:21:08 +01:00
roberto@natty32 be73e00dde merge 2011-03-10 09:56:33 +01:00
roberto@natty32 a5f272f337 fixed a bug in getopt_long 2011-03-10 09:56:04 +01:00
roberto@sirius 406691aa69 uWSGI 0.9.7-rc2 2011-03-09 11:26:27 +01:00
roberto@natty32 6827b3bf15 cron-like interface added to signal framework 2011-03-09 10:33:44 +01:00
roberto@natty32 2055a1472f great fix suggested by Damjan Georgievski for linux namespaces 2011-03-08 14:17:30 +01:00
roberto@natty32 f4f9018068 fixed multithreading + max-requests 2011-03-08 11:45:37 +01:00
roberto@sirius 3e82b5cd33 improved configuration system 2011-03-07 16:06:59 +01:00
roberto@sirius 07036bce20 fix %v usage in emperor 2011-03-07 11:52:44 +01:00
roberto@sirius a4a7a75f29 uWSGI 0.9.7-rc1 2011-03-07 09:42:53 +01:00
roberto@natty32 02d6006b2f added %v in emperor 2011-03-06 19:21:09 +01:00
roberto@natty32 e8e5f11c66 use sigaction() instead of signal() 2011-03-05 17:20:10 +01:00
roberto@natty32 e53a6fa4c0 fixed http fd passing on POST 2011-03-04 14:23:36 +01:00
roberto@natty32 c478b0a0c8 added uwsgi.erlang_register_process 2011-03-04 12:07:07 +01:00
roberto@natty32 5f207e6978 fix getsockname on unbound sockets 2011-03-04 09:01:14 +01:00
roberto@natty32 a2b74d0afd fixed linux namespace on recent kernel 2011-03-04 08:20:20 +01:00
roberto@maverick64 b867b11de3 fixed python2.x threads 2011-03-03 17:17:27 +01:00
roberto@maverick64 806765d1d3 fixed python3.2 threads 2011-03-03 17:15:01 +01:00
roberto@sirius 62d2b97e17 export build date 2011-03-03 14:06:29 +01:00
roberto@sirius c04e339034 report clustering without a socket 2011-03-03 11:07:58 +01:00
roberto@sirius 927b495646 nuclear blast all the processes on initialization error 2011-03-03 10:38:19 +01:00
roberto@mrspurr 57b5392590 fixed gateways reloading 2011-03-03 09:52:57 +01:00
roberto@mrspurr 463030108f fixed vacuum 2011-03-03 09:17:03 +01:00
roberto@netbsd64 46dd754264 NetBSD fixes 2011-03-02 19:54:13 +01:00
roberto@silente 12d9641b66 OpenBSD, endianess and clustering fixes 2010-12-16 07:21:51 +01:00
roberto@maverick64 6cb1203d26 fixed post buffering in python 2011-03-02 17:22:12 +01:00
roberto@maverick64 23d0ec333e encode python string/binary to erlang binary 2011-03-02 11:17:12 +01:00
roberto@maverick64 da579fd308 fix refcnt in erlang->python translation 2011-03-02 08:54:01 +01:00
roberto@longshot 14152bc999 removed broken log rotation 2011-03-01 20:55:04 +01:00
roberto@sirius 6c32e5f2e2 fixed no_argument options in ini and yaml parsing 2011-03-01 16:38:45 +01:00
roberto@freebsd64 62f74f2b60 uWSGI 0.9.7-beta1 2011-03-01 10:47:32 +01:00
roberto@maverick64 6ac7f6db7f python 3.2 fixes 2011-03-01 10:43:43 +01:00
roberto@mrspurr 388a836bbc added Changelog for beta1 2011-03-01 10:20:37 +01:00
roberto@mrspurr f0187e8b0f added --reload-mercy 2011-03-01 10:04:36 +01:00
roberto@sirius c698b82c30 do not rely on exit code for server reloads 2011-02-28 17:39:09 +01:00
roberto@fiorenzo afb3e3636e fixed lua and psgi plugins 2011-02-28 15:26:05 +01:00
roberto@cable 774548f268 --attach-daemon fixes 2011-02-28 08:47:04 +01:00
roberto@longshot ee38901855 various rack/rails fixes 2011-02-27 09:29:01 +01:00
roberto@longshot a07ecdb3e3 multiline headers in Rack plugin 2011-02-27 07:10:29 +01:00
roberto@longshot 143c286f3b fixed --eval 2011-02-27 05:54:20 +01:00
roberto@longshot 5f2f13c49e another --processes auto fix 2011-02-27 05:15:15 +01:00
roberto@longshot 2c19a031c7 added --processes auto 2011-02-26 20:28:26 +01:00
roberto@mrspurr a10e67538a passive clustering support 2011-02-26 15:42:56 +01:00
roberto@fiorenzo 4387075930 multicast clustering in http router 2011-02-26 15:25:46 +01:00
roberto@fiorenzo 6ec1eb5c90 added --harakiri-verbose 2011-02-26 11:21:46 +01:00
roberto@fiorenzo 6ac1cbe913 fixed python2.5-erlang bridge 2011-02-25 18:40:32 +01:00
roberto@fiorenzo 4923326bdd another fix for pyerl 2011-02-25 17:53:09 +01:00
roberto@sirius 0f8ca18e0d erlang build fix 2011-02-25 17:35:57 +01:00
roberto@mrspurr 7666e16072 fixed urack.rb 2011-02-24 19:22:22 +01:00
roberto@mrspurr a42f6e5d18 fixed a stupid bug in fd passing 2011-02-24 19:13:34 +01:00
roberto@sirius 67b22ff796 added iterations to uwsgi.add_rb_timer() 2011-02-24 10:50:52 +01:00
roberto@sirius 28c14f4d8c added uwsgi.add_rb_timer() 2011-02-24 10:29:06 +01:00
roberto@sirius 7133069ee9 updated signal framework to the new api 2011-02-24 09:48:28 +01:00
roberto@lupo b752425223 fixed REMOTE_ADDR in http router 2011-02-23 21:18:33 +01:00
roberto@lupo c5367bb338 http timeout fixes 2011-02-23 21:10:23 +01:00
roberto@sirius d1342241bd rbtree timers 2011-02-23 20:54:52 +01:00
roberto@cable 05be07aab4 removed debug from real gil 2011-02-23 10:29:01 +01:00
roberto@mrspurr 7f4f16e96a fixed ini/yaml parsing with optional values, added UWSGI_SETENV var 2011-02-23 09:35:38 +01:00
roberto@lupo f11664642f add REMOTE_ADDR in http router 2011-02-23 05:50:35 +01:00
roberto@lupo 28b074b6ea always export QUERY_STRING in http router 2011-02-22 15:18:49 +01:00
roberto@lupo f43161c939 subscription system fix 2011-02-22 14:10:54 +01:00
roberto@sirius d52b7111ea fixed reloading 2011-02-22 13:47:29 +01:00
roberto@sirius 9331d1154e damn, another fix for spooler leak 2011-02-21 11:03:46 +01:00
roberto@sirius 364a580090 fixed a leak in the spooler 2011-02-21 10:17:28 +01:00
roberto@lupo f33fa5005a better subscription system 2011-02-21 09:28:38 +01:00
roberto@lupo 8029d01b8b report client REMOTE_ADDR in SIGPIPE 2011-02-21 07:46:37 +01:00
roberto@lupo 69586a6134 fixed a couple of leaks spotted by Riccardo and added uwsgi.listen_queue() 2011-02-21 07:44:37 +01:00
roberto@lupo 7c9c50c6a9 --master-as-root can be used with gateways 2011-02-21 06:47:23 +01:00
roberto@lupo 97139a27d7 SERVER_PORT support in http server 2011-02-21 05:49:52 +01:00
roberto@mrspurr 3b67033d65 http fixes and new subscriber infrastructure 2011-02-20 20:06:26 +01:00
roberto@mrspurr ec08632a29 fixed python <= 2.5 support 2011-02-19 08:55:41 +01:00
roberto@mrspurr eea64e0178 new caching modifier2 2011-02-19 08:39:28 +01:00
roberto@goyle 78096fab30 cache items can have a 16bit flags 2011-02-18 19:34:02 +01:00
roberto@goyle 86fcd13dd9 structure for future response caching 2011-02-18 19:31:58 +01:00
roberto@goyle 4badecdbbc --attach-daemon option 2011-02-18 16:11:24 +01:00
roberto@fedora32 8d1a0d6a13 better check for linux namespace support 2011-02-17 15:24:24 +01:00
roberto@goyle b102b2979b allow uwsgi queue to be used as a stack 2011-02-17 08:04:17 +01:00
roberto@arch32 393235fbfe python3 fixes 2011-02-16 16:56:51 +01:00
roberto@goyle 183a109119 another bunch of async optimizations 2011-02-16 16:42:33 +01:00
roberto@goyle bcff6e0173 various fixes 2011-02-16 15:44:53 +01:00
roberto@goyle 3bd2c3a573 merge 2011-02-16 08:12:53 +01:00
roberto@goyle afba91ad61 added uwsgi queue subsystem 2011-02-16 08:12:21 +01:00
roberto@goyle a34c0f5556 http event optimization 2011-02-15 14:24:53 +01:00
roberto@openbsd32 3fd41a3d2e OpenBSD fixes 2011-02-15 11:53:56 +01:00
roberto@openbsd32 1c5ba25437 use gcc -dumpversion 2011-02-15 10:34:58 +01:00
roberto@arch32 f7ff6b5488 fix gcc version detect 2011-02-15 09:54:22 +01:00
roberto@goyle 53ac53167b osx rwlock fix 2011-02-15 08:39:42 +01:00
roberto@maverick64 c4eccd0d93 first attempt of a better wsgi.input 2011-02-14 20:48:01 +01:00
roberto@maverick64 7744285dc3 move caching locking to rwlock 2011-02-13 18:58:51 +01:00
roberto@maverick64 238c98c0bd a bunch of caching fixes 2011-02-12 10:59:20 +01:00
roberto@maverick64 f9a9ef5752 new cache subsystem 2011-02-12 10:33:12 +01:00
roberto@maverick64 6e5e357a36 suppress epoll_wait warning on reload 2011-02-11 05:36:37 +01:00
roberto@maverick64 0c4004ed14 fixed cache expire (again) 2011-02-11 05:10:42 +01:00
roberto@maverick64 008cd13c4f fixed cache expire 2011-02-10 18:39:29 +01:00
roberto@maverick64 7f3ba8324a fixed uwsgi.cache_exists 2011-02-10 18:37:09 +01:00
roberto@mmaverick64 e9002f2111 allow empty string in cache python api 2011-02-10 15:07:46 +01:00
roberto@maverick64 8f161909bb erlang_recv re-added 2011-02-10 09:48:08 +01:00
roberto@maverick64 1eea49a010 another bunch of erlang new features 2011-02-09 20:28:16 +01:00
roberto@maverick64 e62679cc26 another bunch of erlang features: atoms are mapped to unicode 2011-02-09 12:32:26 +01:00
roberto@sirius f8f9325cbc osx fixes 2011-02-08 16:10:51 +01:00
roberto@maverick64 fa1dd3fbfd the new (production-friendly) HTTP server 2011-02-08 16:04:41 +01:00
roberto@maverick64 0288313524 updated async stack 2011-02-07 10:28:11 +01:00
roberto@solarisexpress df18d66319 various solaris fixes 2011-02-05 22:29:54 +00:00
roberto@maverick64 e8eb86f998 merge 2011-02-05 15:17:13 +01:00
roberto@maverick64 534ff245f2 new Erlang subsystem 2011-02-05 15:16:22 +01:00
roberto@sirius 172654d409 fixed kqueue support 2011-02-04 09:48:38 +01:00
roberto@maverick64 4dea7cfb4b --fastrouter-use-base --fastrouter-use-pattern, multi fd wait in async stack 2011-02-04 09:09:58 +01:00
roberto@maverick64 f7955858bf better processes intercommunication 2011-02-03 21:02:26 +01:00
roberto@maverick64 fb5a5ddadd added uwsgi.erl in contrib 2011-02-03 16:25:56 +01:00
roberto@freebsd64 2bacd79c43 fixed a couple of leaks 2011-02-03 11:10:16 +01:00
roberto@freebsd64 6ca539497d add %d to magic table 2011-02-03 07:56:40 +01:00
roberto@mrspurr 78f3524fcb fixed kqueue 2011-02-02 19:20:46 +01:00
roberto@maverick64 937b2de41b the uWSGI fastrouter 2011-02-02 16:38:51 +01:00
roberto@maverick64 a07c79f7be moved listen queue to 100 by default 2011-01-30 05:55:34 +01:00
roberto@maverick64 9562c81590 the new spooler is working 2011-01-29 11:48:46 +01:00
roberto@maverick64 0a37852c5f ready to port the spooler to the new api 2011-01-29 10:08:35 +01:00
roberto@maverick64 460b78857c 64K are greater than 10K.... 2011-01-28 14:32:03 +01:00
roberto@maverick64 ac0e0a9f9e patch by Damjan Georgievski to allow compilation without xml 2011-01-27 18:20:07 +01:00
roberto@maverick64 740f16fe62 added exception for python cache_set 2011-01-27 18:04:35 +01:00
roberto@maverick64 faa0995c9c fix fd 0 usage 2011-01-27 15:41:47 +01:00
roberto@maverick64 dfff71a525 fixed xml and yaml parsing 2011-01-27 14:43:31 +01:00
roberto@maverick64 380d8cb3ea fixed --pyargv 2011-01-27 13:20:25 +01:00
roberto@maverick64 3f5aab2083 UWSGI_VASSAL_ support for Emperor, magic vars for configuration files 2011-01-27 09:27:55 +01:00
roberto@maverick64 2af5ef9016 added the uWSGI emperor 2011-01-26 16:29:49 +01:00
roberto@maverick64 f82dbfd300 support BROADCAST for clustering 2011-01-25 16:20:11 +01:00
roberto@maverick64 9cbf1c545d added uwsgi.fcgi() api function to allows uWSGI being a fastcgi proxy/router 2011-01-23 14:35:42 +01:00
roberto@maverick64 9ac598b9c3 better harakiri on threaded modes 2011-01-21 18:08:04 +01:00
roberto@maverick64 07dd0c2c0b Python3 support back to the future 2011-01-21 10:17:52 +01:00
roberto@maverick64 66b1cdd63c fixed threads startup 2011-01-19 07:59:59 +01:00
roberto@sirius 78980aab9e re-export uwsgi.env in non-threaded modes 2011-01-18 06:11:09 +01:00
roberto@sirius 0ac813be79 fixed reloading/respawn 2011-01-18 06:02:45 +01:00
roberto@maverick64 b09513bb2e xml,ini and yaml file can taken via http automagically 2011-01-17 22:02:13 +01:00
roberto@maverick64 c3e906f1ff threaded example 2011-01-16 09:32:58 +01:00
roberto@maverick64 666c1fec75 added support for cache_get, cache_set and call to PSGI 2011-01-15 19:05:05 +01:00
roberto@sirius 5d86ed46a3 fix psgi compilation 2011-01-15 17:43:01 +01:00
roberto@maverick64 2ee1c3ac32 allow append in build profiles 2011-01-15 14:26:46 +01:00
roberto@maverick64 ef530650c4 --dump-options 2011-01-15 14:07:58 +01:00
roberto@maverick64 fd1c7773ee gateways implementation -> proxy plugin 2011-01-15 12:56:10 +01:00
roberto@sirius 520ff8465b added exceptions counter 2011-01-14 14:49:45 +01:00
roberto@maverick64 170c66b000 fixed paste support: Plone threaded works perfectly 2011-01-13 18:10:13 +01:00
roberto@sirius c94206f7ba a huge list of threading fixes, we are near to ROCK SOLID threading mode 2011-01-13 11:42:59 +01:00
roberto@sirius f9158b39d8 pg async example 2011-01-11 10:38:20 +01:00
roberto@maverick64 daba88f947 --check-static option 2011-01-09 11:19:12 +01:00
roberto@maverick64 a7e4852621 --log-syslog option 2011-01-09 09:31:26 +01:00
roberto@maverick64 8a8d029357 lua build fixes 2011-01-09 08:07:51 +01:00
roberto@maverick64 b9621b620a reindent uwsgiconfig.py 2011-01-08 12:12:08 +01:00
roberto@debian32 cc0d656b86 fixed python multiapp loading 2011-01-08 12:01:19 +01:00
roberto@debian32 18080df77a fix for debian + python2.5 2011-01-08 11:26:45 +01:00
roberto@maverick64 059314e8f3 fixed uwsgi_rawlog 2011-01-08 09:47:26 +01:00
roberto@mrspurr 500e4e41fe uwsgi_rawlog() 2011-01-07 23:17:34 +01:00
roberto@sirius 8b21fb72b2 --logdate=strftime 2011-01-07 23:07:43 +01:00
roberto@mrspurr f8464ac733 fix debug build and better error reporting 2011-01-07 22:38:51 +01:00
roberto@sirius ac05ad1ef5 more tolerant uwsgi array parser 2011-01-07 16:03:29 +01:00
roberto@maverick64 ed5f501a19 improvements in multiple interpreter management 2011-01-06 19:45:43 +01:00
roberto@maverick64 515b9f2838 completely remove leave_open support (sorry that was a bad choice) 2011-01-06 11:48:10 +01:00
roberto@maverick64 d57ddff924 support for --mount option 2011-01-06 11:38:07 +01:00
roberto@maverick64 0a2da2a2ce jail-friendly setuid()/setgid() 2011-01-05 18:48:50 +01:00
roberto@maverick64 72f677bb0d working linux namespace support 2011-01-05 15:42:30 +01:00
roberto@sirius e176af1702 you can do RPC from uwsgicc 2011-01-04 17:42:48 +01:00
roberto@fiorenzo 6e748eafb9 the rpc plugin 2011-01-04 17:43:57 +01:00
roberto@sirius e11f84193a more rpc fixes 2011-01-04 16:02:44 +01:00
roberto@sirius ec4fbdff32 added generic functions for rpc 2011-01-03 20:52:23 +01:00
roberto@sirius d3ced01b43 added struct for uwsgi rpc 2011-01-03 20:25:00 +01:00
Riccardo Magliocchetti 64468ae69e uwsgicc: fix typo in template 2011-01-03 16:28:33 +01:00
Riccardo Magliocchetti 79d75e832f uwsgicc: template beautyfication, thanks to Simone Marcarino 2011-01-03 16:25:28 +01:00
roberto@sirius ae41506764 send log mesages via uwsgicc 2011-01-03 12:31:12 +01:00
roberto@fedora64 f0bb80b9b8 timerfd fix 2011-01-02 21:48:14 +01:00
roberto@solarisexpress 1955d63cad added support for solaris port event subsystem 2011-01-02 21:40:21 +00:00
roberto@mrspurr 4b2fdb3d30 OSX fixes 2011-01-02 18:53:14 +01:00
roberto@fedora64 d586fe2fb3 another test for linux namespace. They works perfectly 2011-01-02 17:51:50 +00:00
roberto@fedora64 924074175e using fedora14 as base for linux namespace support 2011-01-02 18:20:20 +01:00
roberto@fedora64 a64cbea6e8 old glibc fixes 2011-01-02 18:19:11 +01:00
roberto@sirius 9ef571b4fa allow usage of Linux namespace feautures 2011-01-02 12:15:52 +01:00
roberto@sirius 67666a1788 test for logrotation based on size 2011-01-02 10:43:00 +01:00
roberto@sirius e1daf1d360 add skel version of the uWSGI Control Center (flask+jinja2 app) 2011-01-01 12:42:17 +01:00
roberto@sirius 94f3b715e5 fixed cluster node names 2011-01-01 12:03:12 +01:00
roberto@sirius 31892a69df better cluster node management 2011-01-01 11:53:06 +01:00
roberto@sirius a43bc93492 add cluster_fd to master queue 2011-01-01 10:38:09 +01:00
roberto@sirius 8dd9149624 OSX build fixes 2010-12-28 10:10:37 +01:00
roberto@fiorenzo e422f7311a added register_signal tu lua api 2010-12-26 20:07:41 +01:00
roberto@fiorenzo bb093c7614 various Linux fixes 2010-12-26 18:33:12 +01:00
roberto@mrspurr 5186936c3a refactored signal framework 2010-12-26 10:33:50 +01:00
roberto 4269f0483f Leonid Borisenko patch for use absolute path as build profile 2010-12-26 09:39:30 +01:00
roberto@sirius 09f49bb5d6 added the list of healtchecks that will be available by default 2010-12-21 21:18:25 +01:00
roberto@sirius a054f2b968 various fixes for sendfile() and rack plugin 2010-12-21 08:38:43 +01:00
riccardo@unbit 149cf74fe6 compile on git Linux kernel 2010-12-21 07:23:51 +01:00
Riccardo Magliocchetti 123b3fd4b1 buildconf: update unbitstaff profile config 2010-12-20 12:07:28 +01:00
roberto@storm 2e18db2352 added inherit option for buildconf 2010-12-20 10:09:01 +01:00
roberto@freebsd64 d7c2856041 fixed timers on FreeBSD 2010-12-19 15:04:30 +01:00
roberto@mrspurr 07a87bdff3 fixed file monitor and timers on OSX 2010-12-19 14:58:01 +01:00
roberto@centos64 fca3c51351 fixed old linux kernel support 2010-12-19 13:05:37 +01:00
roberto@fiorenzo 70db2befb5 fully working file monitor and timer support for Linux/epoll 2010-12-19 12:50:36 +01:00
roberto@centos64 057fcb0693 remove timerfd() support for Linux kernel < 2.6.25 2010-12-19 09:18:45 +01:00
roberto@fiorenzo 051dc77712 move from poll() to epoll() on linux master.c 2010-12-18 16:48:43 +01:00
roberto@mrspurr 784191f127 moved master from poll() to kqueue() on OSX and *BSD 2010-12-18 14:58:44 +01:00
roberto@mrspurr 3454279ac7 thundering herd is solved even on OSX 2010-12-17 21:07:17 +01:00
roberto@fiorenzo e335cf5e96 solve the thundering herd bug 2010-12-17 20:58:57 +01:00
roberto@fiorenzo 44277b38cd leave_open should not be available for WSGI requests. It overcomplicates things 2010-12-17 18:05:41 +01:00
roberto@sirius 31bd3fa6c4 use uwsgi_signal framework for better/portable --no-orphans 2010-12-17 17:13:45 +01:00
roberto@freebsd64 3104f915e5 use umtx_* locking functions on FreeBSD 2010-12-17 13:44:33 +01:00
roberto@mrspurr 860a017060 remove a bit of pollution in the logs 2010-12-17 08:47:01 +01:00
roberto@mrspurr 23f00ec864 fixed mod_uwsgi for deflate filter 2010-12-16 22:56:24 +01:00
Riccardo Magliocchetti 69fd8aaa36 python plugin: prefer LIBDIR for LDFLAGS
Try to use LIBDIR instead of PREFIX as directory where to look for
python libraries to link with.
2010-12-16 18:41:35 +01:00
roberto@sirius 7ea77afb38 added base for lb (load-balancer) framework 2010-12-16 18:27:07 +01:00
roberto@sirius da577ef923 fixed poll() usage 2010-12-16 18:25:33 +01:00
roberto@sirius 26cae83139 build fix without udp 2010-12-15 18:37:56 +01:00
roberto@sirium a8c4f6bffe the cache can now contains upto 0xFFFFFFFF items, added uwsgi.cache_exists to the api 2010-12-15 10:47:01 +01:00
roberto@sirius eff66ef08f added router.lua 2010-12-13 18:16:15 +01:00
roberto@sirius 381da45196 completed caching framework api 2010-12-13 18:15:11 +01:00
roberto@goyle 43c347d20e use luaL_newstate 2010-12-12 18:29:03 +01:00
roberto@goyle fadee3242f LuaJit works perfectly and FAAAAST 2010-12-12 18:22:30 +01:00
roberto@goyle 27fda41398 first implementation of multi-request per connection (need optimization) 2010-12-12 17:37:28 +01:00
roberto@sirius f6f8dbecc0 better uwsgi_waitfd for nailed connections 2010-12-12 11:26:14 +01:00
roberto@fiorenzo 902991daa4 OOB for nailed connections 2010-12-12 11:22:39 +01:00
roberto@sirius 245ab6d815 various test for trying to allow pre-connected requests 2010-12-11 20:08:23 +01:00
roberto 96700a49e3 ok, i am stupid, added cache.c 2010-12-10 21:51:25 +01:00
roberto@sirius b75ba73264 caching infrastructure (need optimizations) 2010-12-09 19:54:37 +01:00
roberto@sirius 7d6f93d1cb uwsgi.recv_block and uwsgi.recv_frame 2010-12-07 05:38:57 +01:00
roberto@mrspurr 9aaf36141e extended the uwsgi api to allow easy implementation of websockets servers 2010-12-06 13:48:23 +01:00
roberto@mrspurr 68c6dd13b8 fixed fd close on uwsgirouter.py 2010-12-05 18:37:25 +01:00
roberto@mrspurr 8ac5176c4c fixed async routing 2010-12-05 10:52:01 +01:00
roberto@mrspurr fd49ba36eb more custom routing example and optimizations 2010-12-05 10:45:13 +01:00
roberto@mrspurr 047aac8426 export uwsgi.is_connected 2010-12-05 08:17:29 +01:00
roberto@mrspurr 103e7415f3 various threading fixes 2010-12-04 18:30:22 +01:00
roberto@mrspurr b64911d20e fixed uwsgirouter.py 2010-12-04 17:32:31 +01:00
roberto@mrspurr 2f970ce585 various async optimizations and routing python examples 2010-12-04 13:43:12 +01:00
roberto@sirius 47801964c4 merge 2010-12-03 18:27:14 +01:00
roberto@sirius da8eb4ad1b add uwsgirouter.py test script for upcoming custom routing 2010-12-03 18:26:29 +01:00
roberto@fiorenzo 320a2b8a7f various fixes 2010-12-01 13:35:40 +01:00
roberto@fiorenzo eab271e1e1 fixed a stupid bug 2010-11-30 14:27:39 +01:00
roberto@mrspurr d161962db1 pass custom apache variables via SetEnv 2010-11-28 09:54:31 +01:00
roberto@fiorenzo 36a3b408cf --proxy-node @self 2010-11-27 06:58:46 +01:00
roberto@fiorenzo 10af04becc uWSGI proxy is now cluster-aware 2010-11-27 06:06:22 +01:00
roberto@fiorenzo 4db259900e better virtual ip automagic 2010-11-27 05:37:29 +01:00
roberto@mrspurr fe4ba8130d cluster membership improvements 2010-11-27 04:58:20 +01:00
roberto@silente 4c4f92bad2 big endian fixes 2010-09-10 06:58:12 +02:00
roberto@fiorenzo 6f726d6370 wait forever for cluster configuration 2010-11-25 16:26:13 +01:00
roberto@fiorenzo c4f50fccfb various fixes 2010-11-25 16:21:25 +01:00
roberto@sirius 7e2daed0e8 fixed cluster logging (again) 2010-11-25 11:26:39 +01:00
roberto@sirius e4d3f79492 fixed cluster reloading 2010-11-25 11:10:58 +01:00
roberto@sirius d128a958cf cluster realod and logging 2010-11-25 11:07:27 +01:00
roberto@fiorenzo 0024bf56be fixed python module split 2010-11-25 09:53:56 +01:00
roberto@sirius 1d03fdee64 use recvfrom() instead of read() 2010-11-25 09:44:07 +01:00
roberto@sirius 152fb9cde9 cluster announce 2010-11-25 08:51:54 +01:00
roberto@mrspurr e6c5710657 use getifaddrs() instead of ioctl() 2010-11-25 07:33:47 +01:00
roberto@fiorenzo df0b3f7eb5 configuration can now be taken from the cluster nodes automagically 2010-11-24 18:55:15 +01:00
roberto@sirius f420bf3266 save multicast addr structure for performance 2010-11-24 18:28:54 +01:00
roberto@sirius 7a262159dc cluster configuration 2010-11-24 13:25:30 +01:00
roberto@fiorenzo 3dec2821f4 various new clustering implementations 2010-11-24 11:42:15 +01:00
roberto@sirius 652a9c5825 various multiapp and virtualhosting fixes 2010-11-22 11:15:02 +01:00
roberto@debian32 79c30fed23 added --manage-script-name 2010-11-21 15:21:06 +01:00
roberto 5ab8d800d8 more powerful --pymodule-alias directive 2010-11-20 17:57:48 +01:00
roberto@sirius 0beb7108e4 added python module aliases 2010-11-20 12:47:52 +01:00
roberto@sirius 356d59a38d fixed setup.py 2010-11-18 10:06:51 +01:00
roberto@sirius 87853d0ca3 fixed fiber support for kqueue 2010-11-17 15:38:48 +01:00
roberto c9056630b7 Fiber support is now working (no fd monitoring and sleep yet) 2010-11-17 15:06:31 +01:00
roberto@sirius a4120efabe added experimental fiber support for ruby1.9 2010-11-17 07:42:51 +01:00
roberto@sirius 0bd017f722 fixed plugin initialization 2010-11-17 05:13:42 +01:00
roberto@fiorenzo 5a738fba8a i am afraid that ruby will never run on uGreen, time to pass to fibers 2010-11-16 17:53:15 +01:00
roberto@fiorenzo 856fd8b00f towards a better uGreen (with ruby support) 2010-11-16 10:06:19 +01:00
roberto@mrspurr d60d90afe3 various uGreen fixes 2010-11-15 21:55:55 +01:00
roberto@mrspurr 0132c00f41 fix after_request 2010-11-15 18:34:04 +01:00
roberto@mrspurr aebc637f2b new async example 2010-11-15 14:00:09 +01:00
roberto@fiorenzo d4c4643ddc YAML config file support 2010-11-14 20:20:41 +01:00
roberto@mrspurr aea66427f1 various fixes for magic options and new --remap-modifier 2010-11-14 07:18:49 +01:00
roberto@mrspurr 0376c804f9 reintroduced magic configuration 2010-11-13 20:09:54 +01:00
roberto@nexenta32 4a99069a4e NexentaOS is officially supported 2010-11-13 08:36:41 +01:00
roberto@freebsd64 e3bbcc5c84 freebsd notes for JVM 2010-11-13 08:03:01 +01:00
roberto@freebsd64 6fc40077be FreeBSD fixes 2010-11-13 07:04:51 +01:00
roberto@longshot 040d1a9d0b new amazing option: --upload-progress 2010-11-12 08:28:11 +01:00
roberto@longshot 8a121ada9d various fixes 2010-11-12 05:45:37 +01:00
roberto@mrspurr 373c45c7d4 use symlinks to automagically load plugins 2010-11-12 04:08:50 +01:00
roberto@mrspurr 3e7992d0ac added perl embedded module 2010-11-08 18:14:36 +01:00
roberto@fiorenzo 4a4455cd16 fixed jvm/jwsgi compilation on Linux 2010-11-08 16:38:44 +01:00
roberto@mrspurr 444e8d2637 utest.java, jwsgi example 2010-11-08 16:21:42 +01:00
roberto@mrspurr bcd6f7de32 jwsgi fake protocol support, better JVM api 2010-11-08 15:58:06 +01:00
roberto@mrspurr 5346ca68f9 added JVM core plugin 2010-11-07 09:15:20 +01:00
roberto@mrspurr ab83b1c7aa fixed psgi compilation 2010-11-06 08:13:46 +01:00
roberto@fiorenzo bc0eec51b4 PSGI streaming support. WebGUI is running pretty well 2010-11-05 16:02:18 +01:00
roberto@sirius 187100f2bf uwsgi.opt dictionary 2010-11-04 17:52:38 +01:00
roberto@sirius 2e4e23f63f merge 2010-11-03 19:34:55 +01:00
roberto@sirius 6f1f990f69 threads support for perl 2010-11-03 19:34:08 +01:00
roberto@mrspurr.local 75d2109254 added wt.join() in urack.rb 2010-11-03 07:35:25 +01:00
roberto@mrspurr cada9ed520 add threads support in urack.rb 2010-11-03 07:08:34 +01:00
roberto@sirius 6f3fe261d0 added buildconf/psgi.ini 2010-11-01 20:42:35 +01:00
roberto@sirius c78c0a2798 PSGI fixes 2010-11-01 18:14:38 +01:00
roberto@sirius 6249c25411 various virtual hosting fixes 2010-11-01 08:53:20 +01:00
roberto@shadowcat 36fc098c5d various ruby 1.9 fixes 2010-10-31 08:06:36 +01:00
roberto@haiku 070e84125a a bunch of haiku fixes 2010-10-29 19:34:22 +00:00
roberto@sirius aa50669237 python, ping and nagio are embedded by default 2010-10-29 13:53:05 +02:00
roberto@sirius 32ab7e79ca python fixes and optimizations 2010-10-29 13:02:59 +02:00
roberto@sirius 8971539550 pluginize ugreen and nagios 2010-10-29 10:36:58 +02:00
roberto@sirius df52dfd31f uwsgi.h vacuum 2010-10-29 08:14:03 +02:00
roberto@sirius 61756d45a2 even erlang.c was accidentally removed 2010-10-29 08:05:05 +02:00
roberto@sirius fe7a5eb5d3 reintroduce accidentally-removed mod_uwsgi.c 2010-10-29 07:47:16 +02:00
roberto@sirius e744d36fa0 investigating ruby 1.9 fiber and pluggable uWSGI loop 2010-10-28 09:25:31 +02:00
roberto@sirius 2108c85f7e trying to map ruby1.9 pthreads in uWSGI pthreads 2010-10-27 08:48:21 +02:00
roberto@mrspurr e2c405fe02 merge 2010-10-26 06:44:45 +02:00
roberto@sirius 8668b9a614 applied Dan Loewenherz stylish patch 2010-10-26 06:43:40 +02:00
roberto@fiorenzo 87ae9d780e ruby1.9 support 2010-10-25 20:11:40 +02:00
roberto@fiorenzo d0c071e759 pyargv fixes 2010-10-25 08:59:50 +02:00
roberto@fiorenzo 1a6324e825 python24, python27, python20, python31, python32 plugins 2010-10-25 08:51:52 +02:00
roberto@sirius bee3ba73d8 python25, python26 plugins 2010-10-25 08:47:31 +02:00
roberto@sirius 8dde9c2984 multiple python plugin version with the same server core 2010-10-25 08:34:10 +02:00
roberto@sirius 094d4128dc lua sputnik test with threads 2010-10-24 22:05:42 +02:00
roberto@sirius da25f77326 report correct response size in Lua plugin 2010-10-24 12:52:09 +02:00
roberto@sirius c5073f7056 Lua support improvement 2010-10-24 12:28:43 +02:00
roberto@sirius c461d2e6b3 lua plugin ported to the new api 2010-10-24 08:28:47 +02:00
roberto@sirius 6adca06764 fixed python embedded module, first refactoring of the spooler, better rack compliance 2010-10-23 21:59:43 +02:00
roberto@fiorenzo 746f645e6c disable LDAP by default even on rack plugin 2010-10-23 13:19:49 +02:00
roberto@fiorenzo e6ef84bb4b disable LDAP by default 2010-10-23 13:18:44 +02:00
roberto@sirius 17975acb45 modular buildconf 2010-10-23 13:11:13 +02:00
roberto@fiorenzo 4b81ff61eb fix plugins loading 2010-10-23 08:48:41 +02:00
roberto@fiorenzo bf868ff636 build system improvements 2010-10-23 08:44:22 +02:00
roberto@mrspurr c777a0f926 support for rack to_path and ruby GC frequency. Now Radiant works too 2010-10-23 08:41:50 +02:00
roberto@fiorenzo 7a7f499f63 Typo 5 is working \!\!\! 2010-10-22 23:12:28 +02:00
roberto@sirius b22b46b153 another bunch of rails fixes 2010-10-22 21:26:12 +02:00
roberto@sirius bbd8ea51c0 better ruby plugin, we are near to a beta version 2010-10-22 18:40:22 +02:00
roberto@sirius e1969d92ab python and ping plugins now embedded by default 2010-10-21 22:35:38 +02:00
roberto@fiorenzo e8e8b6902c fix compilation on Linux 2010-10-21 16:26:51 +02:00
roberto@sirius 7041a9fa45 xml parsing and pluginized getopt_long stabilization 2010-10-21 11:45:49 +02:00
roberto@sirius bfbca5bc96 ping plugin 2010-10-20 21:56:51 +02:00
roberto@sirius be183bf07f add new files to the tree 2010-10-20 21:55:37 +02:00
roberto@sirius f7aa451af4 uWSGI is now language agnostic, all can be pluginized, python included 2010-10-20 21:54:19 +02:00
roberto@sirius 53ccd3d4b8 new option --http-modifer1 2010-10-17 12:25:50 +02:00
roberto@sirius aaa6033c2a --log-sendfile 2010-10-16 09:09:54 +02:00
roberto@sirius 345c8ed962 another PSGI fixes round 2010-10-14 15:37:01 +02:00
roberto@sirius 9e0c7a3bdc updated PSGI plugin for 0.9.7-dev 2010-10-14 11:43:02 +02:00
Riccardo Magliocchetti 616ed04c79 Show spooler jobs in django admin 2010-10-13 11:00:22 +02:00
roberto@mrspurr 441fb06129 uwsgi.post_fork_hook 2010-10-13 07:17:00 +02:00
roberto@fiorenzo 4b92ba5cbe dynamic apps are now supported in threaded modes 2010-10-12 09:18:36 +02:00
roberto@mrspurr 13932641e5 pthread_atfork() 2010-10-12 08:23:37 +02:00
roberto@sirius 85752ccf2c add pthread locking for init_uwsgi_app 2010-10-12 07:59:37 +02:00
roberto@mrspurr 6d9b753735 various pyloaders fixes 2010-10-11 15:00:15 +02:00
roberto@fedora32 6b7e3a6429 better (race-condition-free) request counters 2010-10-10 07:48:05 +02:00
roberto@fedora32 6ef043c40a reduce GIL impact on yielding apps 2010-10-09 19:20:50 +02:00
roberto@mrspurr 9704abd3e4 apache2 right socket RST handling 2010-10-09 11:27:02 +02:00
roberto@sirius 723acced71 --close-on-exec option 2010-10-06 12:16:15 +02:00
roberto@mrspurr ca43ad0a91 various stabilization fixes 2010-10-05 05:48:20 +02:00
roberto@fiorenzo 17e2dbf85b renamed async_switches to switches 2010-10-04 17:51:22 +02:00
roberto@fiorenzo 7e40c902e6 various threading fixes 2010-10-04 17:24:59 +02:00
roberto@fiorenzo 074d0b95d1 theading support improvements 2010-10-04 14:01:56 +02:00
roberto@mrspurr 36c8a8c675 initial threading mode support 2010-10-03 22:49:22 +02:00
roberto@mrspurr 00a70c2ea2 new 0.9.7 codebase for app loading is complete 2010-10-02 18:34:55 +02:00
roberto@sirius 2bf20631e1 stabilization fixes 2010-10-01 11:50:00 +02:00
roberto 74b9579531 2 new loaders LOADER_CALLABLE and LOADER_STRING_CALLABLE 2010-10-01 10:02:46 +02:00
roberto@sirius 5a152d1bae another big loader refactoring 2010-10-01 07:45:33 +02:00
roberto@sirius 551152ade9 new loader refactoring 2010-09-30 18:13:40 +02:00
roberto@sirius 42c5b356f5 add a note to add dynamic loaders 2010-09-30 14:10:24 +02:00
roberto@sirius 33bd68c44c compilation fix 2010-09-30 14:08:05 +02:00
roberto@sirius 46b715fcc3 first merge from 0.9.6.5 (headers management still missing) 2010-09-29 08:46:38 +02:00
roberto@mrspurr b004168401 automagic recognition of the last parameter by extension 2010-09-28 07:08:04 +02:00
roberto@fiorenzo 6cebf19468 fix --wsgi-file and --pythonpath cooperation 2010-09-27 17:05:58 +02:00
roberto@mrspurr fb73324d25 more code refactoring 2010-09-26 12:17:04 +02:00
roberto@mrspurr 94624c7e52 another one destructive commit, move master to dedicated file 2010-09-26 09:11:57 +02:00
roberto@fiorenzo c4033a5970 http fix 2010-09-25 09:16:44 +02:00
roberto@fiorenzo e66e56b593 get_linux_tcp_info() refactoring 2010-09-25 08:24:16 +02:00
roberto@fiorenzo b408423b03 conditional logging 2010-09-25 08:09:34 +02:00
roberto@fiorenzo c37a2d7842 advanced socket binding and system reloading, need optimizations for single socket 2010-09-24 20:48:52 +02:00
roberto@mrspurr da339bb3a9 remove profiler 2010-09-19 09:56:14 +02:00
roberto@mrspurr f30be82926 First destructive commit for 0.9.7, big python loaders refactoring 2010-09-18 16:41:03 +02:00
roberto@mrspurr f04aa843ff fix argument count check 2010-09-18 08:41:16 +02:00
roberto@fiorenzo 5c42c27cd4 the master process will signal the overload of the listen queue on linux tcp sockets 2010-09-17 10:31:58 +02:00
roberto@fiorenzo fc744f5719 another cgroup fix 2010-09-16 19:09:24 +02:00
roberto@fiorenzo 855c963fb3 working cgroup support 2010-09-16 18:39:33 +02:00
roberto@fiorenzo dd932b0a78 OK. The Web3 test app works 2010-09-16 09:40:33 +02:00
roberto@fiorenzo e4e75a4d64 merge 2010-09-16 09:03:12 +02:00
roberto@fiorenzo ef0464dba6 Web3 support 2010-09-16 09:01:41 +02:00
roberto@fiorenzo bc2b49c8e8 uWSGI 0.9.7-dev started. Cgroup support and initial Web3 support 2010-09-16 09:00:32 +02:00
roberto@sirius 409ce34a0b uWSGI 0.9.6.2 2010-09-15 09:18:02 +02:00
327 changed files with 50671 additions and 13299 deletions
+4
View File
@@ -0,0 +1,4 @@
syntax: glob
*.o
*.pyc
+31
View File
@@ -8,3 +8,34 @@ a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
+19
View File
@@ -0,0 +1,19 @@
- this is a incomplete list of all the contributors of the project -
Roberto De Ioris, Unbit, <roberto@unbit.it>
Riccardo Magliocchetti, Unbit, <riccardo@unbit.it>
Yann Malet, Lincoln Loop
Simon Litchfield
Masahiro Honma, <hiratara@cpan.org>
Łukasz Wróblewski <admin@nri.pl>
Giacomo Bagnoli, Asidev
Guido Notari, Link I.T. S.p.a.
Marco Beri, Link I.T. S.p.a.
Leonid Borisenko
Cal Leeming, Simplicity Media Ltd
Luigi Scarso
Corey Farwell
Charles Duffy
Lukas Lalinsky
Steven Fernandez
Łukasz Mierzwa
+369
View File
@@ -1,5 +1,374 @@
*** august 2011 ***
* 0.9.9 [20110829]
- various spooler improvements
- upload progress optimizations and fixes
- new emperor mode: Tyrant
- allows multiple --ini options
- better binary path detection
- gevent loop engine support
- resolve domain names in socket logging
- snmp fixes and reintroduction of the snmp-api
- fixed grunt mode
- you can specify build profile via env var UWSGI_PROFILE
- reintroduction of string-based multiapp
- new option --emperor-throttle
- improved queue and sharedarea subsystems
- uWSGI can now be built as a shared library
- new api attribute: uwsgi.magic_table
- improved apache2 module
- new option --pyshell
- allow threads in gateways
- fastrouter improvements
- the application list is now shared and exported to the api
- allows setting the thread stack size
- UWSGI_APPID for better multiapp hosting
- better reloading in lazy mode
- native pump support
- various rack fixes
- support for attaching binary data in the executable
- new option --set
- extreme-optimized http protocol parser
- WSGI handler optimizations
*** july 2011 ***
* 0.9.8.3 [20110723]
- implemented uwsgi.SymZipImporter to load embedded zip files
- OSX Lion is officially supported
- fixed xinetd support (example file added in contrib)
- suppot for systemd socket activation
- added --freebind option (Linux only)
* 0.9.8.2 [20110719]
- fixed an ini and yaml parsing bug spotted by Raffaele Colace
- spooler has been extremely improved
- new option --chown-socket
- added uwsgidecorators for elegant uwsgi api access from python
- the rack plugin is now stable
- support for embedding config and generic files in the server binary
- high-performance cache-server
- accept() is now locked on all threads in the same workers
- preliminary implementation of hooks in emperor
- support for C++ in server core
- tcp port auto-bind
- implemented workers, workerN and spooler signal target
- prefork/multithread uwsgi.signal_wait() implementation
- export uwsgi.node in WSGI vars
- new option --import (python plugin)
- support for unlimited number of Linux cgroups
- broodlord mode
*** june 2011 ***
* 0.9.8.1 [20110625]
- the build system has been improved
- various threading fixes
- fix python GIL status after reload
- new option --propagate-touch
- fixed uwsgi.sendfile
- fixed readline() support in wsgi.input
- fixed dynamic touch reload
- new option --logto2
- export %c in config files
- fixed libyaml support
- support passing modifiers in subscription system
- reset random seed in spooler
- subscribe from a list in a text file
- allow binding on port 0 (auto-assignment)
- reset random seed on grunt
- fix vhost mode for empty hostname
- fixed python3+virtualenv support
- tasks are now allowed to chdir() in spooler
- better zeromq+clustering support
- clustering has been refactored
- fixed rpc
- report correct worker id in cheap mode
- fixed a fd-leak in attach-daemon
- use setsid() in attach-daemon
- zerg mode
- added psgix.harakiri
- allows magic vars in sqlite3 config db
- added UWSGI_FASTROUTER_KEY var
- slowdown async-queue-is-full messages
- new option --cron
- --vassals-start-hook and --vassals-stop-hook
- the proxy plugin has been removed
* 0.9.8 [20110605]
- support for --callable in virtualhosting mode
- a NetBSD fix
- abstract unix socket can be prefixed with \0 (nginx-style)
- add /lib to the linker in sun-like systems
- a mercy mode of 5 seconds is enabled by default on SIGINT/SIGQUIT
* 0.9.8-rc4 [20110602]
- fixed REMOTE_ADDR when --protocol=http
- official support for OpenIndiana
- added a welcome.py test script
- new api attribute uwsgi.version_info
- improved the admin plugin
- two new management flag for backlog queue monitoring
- fixed uwsgi_log for bigger loglines
- new option --early-emperor to allows out-of-jail emperors
- emperor can now spawn other emperors (sub-emperors)
- fixed idle mode in single-process
- fixed solaris iovec
*** may 2011 ***
* 0.9.8-rc3 [20110530]
- snapshotting support
- fixed python 3.x spooler
- improvements for grunt processes
- better abstract unix socket
- --log-socket allows logging to generic DGRAM sockets
- a bunch of solaris fixes
- new option --no-fd-passing for fastrouter
- --fastrouter-subscription-slot to set the number of slot in subscription server
- unlimited shared sockets
- fixed netlink compilation
- auto-reconnect on emperor+amqp server disconnection
- various emperor fixes
- unlimited fastrouter sockets
- better cgroup support
- --add-header option allow adding of custom HTTP response headers
- cheap and idle operational modes
* 0.9.8-rc2 [20110521]
- new option --die-on-term
- fixed touch reload
- a couple of optimizations for wsgi.input
- systemd integration
* 0.9.8-rc1 [20110514]
- massive code cleanup and refactoring
- added vassals loyalty concept
- fixed virtualhosting with dynamic virtualenv
- fixed reloading on grand-central-dispatch-enabled OSX
- improved PSGI support with uGreen and async support
- improved Rack support with complete fiber+async in ruby 1.9
- support for JSON config files
- native multi-protocol support (added fastcgi and http)
- Mongrel2 support
- support for templates in vassals
- various threading fixes
- gcc-4.6 support
- support for logging via zeromq
- support for configuration passed via pipe/stdin
- pythonpath entries are now unlimited
- socket entries are unlimited
- pythonpath can be a glob
- lazy mode added
- new language-independent profiling subsystem
- support for configuration stored in a sqlite3 db
- allow workers to survive to syslogd death (when --log-syslog is used)
- fix traceback in Python 3.x
- support for uwsgi signals in threads
- plugin autoloading
- graceful reloading for threads
- new wsgi.input object
- support for alternative allocators (tcmalloc and jemalloc)
*** april 2011 ***
* 0.9.7.2 [20110406]
- new option --touch-reload <file> to reload the stack on <file> modification
--static-map <mountpoint=documentroot> allows to serve static files
- fixed --post-limit management
- disallow empty socket names
- implemented exception_info WSGI support
- new options --reload-on-as <n> and --reload-on-rss <n> allows
to recycle workers when their memory usage is higher than <n> MB
- fixed syslog support (use --log-syslog[=facility] to enable it)
- improved plugin loading system
- added support for RabbitMQ as event dispatcher for the Emperor
- fixed FreeBSD memory report
- PSGI plugin can be compiled without ithreads
- various Emperor fixes
- fixed a regression with setgroups()
- support for shared sockets (used in jails within network namespaces)
*** march 2011 ***
* 0.9.7.1 [20110326]
- fixed python stackless support
- added persistence for queue
- forbid daemonizing in vassal mode
- modifier1 30 is available again
- allow python modules to be mapped/aliased via http
- added --pidfile2 and --logfile-chown
- added UWSGI_CACHE_GET dynamic variable
- 304/If-Modified-Since support for --check-static
- option --check-cache for integrated caching
- option --map-socket to assign specific workers to socket
- fixed unix fd passing on older OSX versions
- fixed post-buffering without pep3333-input
- fixed python threading without uwsgi cores
- support for Linux network namespace
- build with sys.abiflags if necessary
* 0.9.7 [20110317]
- fixed psgi compilation on GNU systems
- improved --pep3333-input
- better error reporting on failed open/fopen
- fixed uGreen
- added greenlet support
- various solaris fixes
- new help system
- updated async support
- fixed uwsgi.cache_get in python
* 0.9.7-rc3 [20110312]
- added support for persistent cache (--cache-store <filename>)
- less verbose file monitoring
- fixed a race condition in emperor startup
- fixed erlang empty list encoding
- improved snmp support
- fixed cache modifier 111 for 3 and 4
- preliminary cpu-affinity support (Linux only)
- fixed ldap support
- auto-configure ldap compilation
- added --allowed-modifiers (allow only a subset of modifiers)
- fixed a bug with getopt_long
* 0.9.7-rc2 [20110309]
- added cron-like interface to signal framework
- improved Linux namespaces support
- fixed multithreading + --max-requests
- added support for reference in configuration files
* 0.9.7-rc1 [20110307]
- export %v in emperor mode
- fixed signal race condition in server reload
- fixed http router post handling bug
- added uwsgi.erlang_register_process in pyerl plugin
- fixed unix socket inherit
- fixed linux namespace support in recent kernel/gcc
- ported threading to python 3.2
- add build date to uWSGI startup info
- do not allow clustering without defining a socket
- kill all the gateways/daemons on startup errors
- fixed vacuum after chdir()
- fixed gateways reload
- re-added support for OpenBSD and NetBSD
- fixed post-buffering in python
- use erlang binary for python string
- fixed memory leak in pyerl plugin
- removed broken log rotation (post-poned)
- fixed no_argument options in ini and yaml parsing
* 0.9.7-beta1 [20110301]
- fully modular re-design
- advanced build system with presets
- threading support
- emperor mode for massive auto-hosting
- caching subsystem
- message queue (even stacked) support
- improved server reloading system
- support for Linux Cgroups and Namespaces
- integrated upload progress
- Clustering infrastructure via multicast, broadcast or subscriptions
- support for attaching/monitoring external apps to the master process
- improved virtualhosting mode
- extremely improved Python support with better usage of multiple interpreters
- improved multiple apps support
- Production ready, evented HTTP router/proxy/load-balancer
- Production ready, evented uwsgi router/proxy/load-balancer
- new Erlang stack
- Internal signal subsystem
- support for RubyOnRails and Rack apps
- A huge series of fixes and optimizations
*** february 2011 ***
* 0.9.6.8 [20110207]
- fixed a bug when using --limit-as
- fixed a erlang buffer initialization
- added --ignore-sigpipe
- added --master-as-root
*** january 2011 ***
* 0.9.6.7 [20110130]
- a huge amount of async optimizations and fixes
- --logdate takes an optional strftime-like value
- follow $PATH on reloading
- uwsgi.core is exported in WSGI env
- uwsgi.log() respect for --logdate
- initial banner respect for --logdate
- fixed --post-buffering
- default listen backlog queue is now 100
- Python 3 support is no more marked as experimental
- Python 3.2 support
- new option --chroot-reload will force a reload of the uWSGI stack after a chroot
- fixed a typo in INI parsing
*** december 2010 ***
* 0.9.6.6 [20101230]
- support for YAML configuration files
- backported python module aliasing from 0.9.7-dev
- better apache2 module (support for SetEnv directive, fixed REQUEST_URI and improved connection handling)
- uwsgi.post_fork_hook implementation (to execute function after fork()) (thanks George Kollias)
- option --gid calls setgroups() after setgid() (thanks Jorge Cardona)
- fixed uGreen compilation (and uGreen is now built by default)
- fixed timeout and thundering herd problem in async modes (many thanks to Test157 for giving us a good async-test-app)
- disable TCP_INFO in older Linux kernels (thanks Bo Shi)
- enable TCP_INFO in FreeBSD (limited usage due to FreeBSD kernel support)
- fixed static virtualhosting mode using xml files (thanks Guido Notari of Link I.T. spa)
- new option --close-on-exec (thanks Jean-Baptiste Quenot)
- use HTTP_HOST var (and fallback to SERVER_NAME) in virtual hosting mode
- fixed a buffer overflow in automatic socket_name allocation (spotted by Riccardo Magliocchetti)
- Official support for Nexenta
*** september 2010 ***
* 0.9.6.5 [20100929]
- PEP 3333 support
- fix --pythonpath with --wsgi-file
- x-wsgiorg.uwsgi.version renamed to uwsgi.version
* 0.9.6.4 [20100925]
- fix a stupid bug in conditional logging backport
* 0.9.6.3 [20100925]
- fix a buffer overflow in .ini parsing (it throws a glibc error on malloc)
- backport of conditional logging from 0.9.7-dev
- backport of backlog queue monitor from 0.9.7-dev (only Linux)
* 0.9.6.2 [20100915]
- fix a regression in virtual hosting mode
- fix pythonpath usage in --ini and --ini-paste
- new uwsgi packet var: UWSGI_CHDIR
* 0.9.6.1 [20100912]
- print the request uri during SIGPIPE or HARAKIRI
+3
View File
@@ -1,2 +1,5 @@
all:
python uwsgiconfig.py --build
clean:
python uwsgiconfig.py --clean
+2
View File
@@ -0,0 +1,2 @@
all:
python3.2 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python uwsgiconfig.py --build pylua
+626 -626
View File
File diff suppressed because it is too large Load Diff
+143 -78
View File
@@ -1,18 +1,18 @@
/*
*** uWSGI/mod_uwsgi ***
*** uWSGI/mod_uwsgi ***
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
Copyright 2009-2011 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
@@ -51,7 +51,6 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
#include <fcntl.h>
#define MAX_VARS 64
#define DEFAULT_SOCK "/tmp/uwsgi.sock"
typedef struct {
@@ -73,6 +72,8 @@ typedef struct {
char script_name[256];
char scheme[9];
int cgi_mode ;
int max_vars;
int empty_remote_user;
} uwsgi_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
@@ -83,8 +84,18 @@ static uint16_t uwsgi_swap16(uint16_t x) {
}
#endif
static int uwsgi_add_var(struct iovec *vec, int i, char *key, char *value, uint16_t *pkt_size) {
static int uwsgi_add_var(struct iovec *vec, int i, request_rec *r, char *key, char *value, uint16_t *pkt_size) {
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
#if APR_IS_BIGENDIAN
if (i+6 > c->max_vars) {
#else
if (i+4 > c->max_vars) {
#endif
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: max number of uwsgi variables reached. consider increasing it with uWSGImaxVars directive");
return i;
}
#if APR_IS_BIGENDIAN
char *ptr;
@@ -150,6 +161,9 @@ static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
c->modifier1 = 0 ;
c->modifier2 = 0 ;
c->cgi_mode = 0 ;
c->max_vars = 128;
c->script_name[0] = 0;
c->empty_remote_user = 1;
return c;
}
@@ -164,6 +178,14 @@ static void *uwsgi_dir_config(apr_pool_t *p, char *dir) {
c->modifier1 = 0 ;
c->modifier2 = 0 ;
c->cgi_mode = 0 ;
c->max_vars = 128;
c->empty_remote_user = 1;
c->script_name[0] = 0;
if (dir) {
if (strcmp(dir, "/")) {
strncpy(c->script_name, dir, 255);
}
}
return c;
}
@@ -243,11 +265,8 @@ static int uwsgi_handler(request_rec *r) {
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
#if APR_IS_BIGENDIAN
struct iovec uwsgi_vars[(MAX_VARS*6)+1] ;
#else
struct iovec uwsgi_vars[(MAX_VARS*4)+1] ;
#endif
struct iovec *uwsgi_vars;
int vecptr = 1 ;
char pkt_header[4];
uint16_t pkt_size = 0;
@@ -264,7 +283,6 @@ static int uwsgi_handler(request_rec *r) {
char uwsgi_http_status[13] ;
int uwsgi_http_status_read = 0;
apr_bucket_brigade *bb;
if (strcmp(r->handler, "uwsgi-handler"))
@@ -287,7 +305,6 @@ static int uwsgi_handler(request_rec *r) {
return HTTP_INTERNAL_SERVER_ERROR;
}
if ( (ret = timed_connect(&uwsgi_poll, (struct sockaddr *) &c->s_addr, c->addr_size, c->socket_timeout, r) ) != 0) {
close(uwsgi_poll.fd);
@@ -317,68 +334,58 @@ static int uwsgi_handler(request_rec *r) {
}
#if APR_IS_BIGENDIAN
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*6)+1);
#else
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*4)+1);
#endif
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_URI", r->uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
//
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user, &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
else if (c->empty_remote_user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", "", &pkt_size) ;
}
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
if (c->scheme[0] != 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
}
if (c->script_name[0] == '/') {
if (c->script_name[1] == 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", c->script_name, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
}
// SCRIPT_NAME = "/" is like SCRIPT_NAME = ""
if (c->script_name[0] != 0 && !(c->script_name[0] == '/' && c->script_name[1] == 0)) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", c->script_name, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
}
else {
if (r->path_info) {
if (strlen(r->path_info) <= 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri, (strlen(r->uri) - strlen(r->path_info) )) , &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->path_info, &pkt_size) ;
}
}
else {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri, &pkt_size) ;
}
headers = apr_table_elts(r->headers_in);
h = (apr_table_entry_t *) headers->elts;
// check for max vars (a bit ugly)
cnt = headers->nelts ;
if (cnt + 11 > MAX_VARS) {
cnt = MAX_VARS -11;
}
for(i=0;i< cnt;i++) {
for(i=0;i< headers->nelts;i++) {
if (h[i].key){
if (!strcasecmp(h[i].key, "Content-Type")) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_TYPE", h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_TYPE", h[i].val, &pkt_size) ;
}
else if (!strcasecmp(h[i].key, "Content-Length")) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
}
else {
penv = apr_pstrcat(r->pool, "HTTP_", h[i].key, NULL);
@@ -390,10 +397,17 @@ static int uwsgi_handler(request_rec *r) {
*cp = toupper(*cp);
}
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, penv, h[i].val, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, penv, h[i].val, &pkt_size) ;
}
}
}
/* environment variables */
headers = apr_table_elts(r->subprocess_env);
h = (apr_table_entry_t*) headers->elts;
for (i = 0; i < headers->nelts; ++i) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, h[i].key, h[i].val, &pkt_size) ;
}
uwsgi_vars[0].iov_base = pkt_header;
@@ -413,11 +427,13 @@ static int uwsgi_handler(request_rec *r) {
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() %s", strerror(errno));
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt != pkt_size+4) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() returned wrong size");
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -429,6 +445,7 @@ static int uwsgi_handler(request_rec *r) {
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: read() client block failed !");
close(uwsgi_poll.fd);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -453,15 +470,22 @@ static int uwsgi_handler(request_rec *r) {
if (cnt == 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
if (uwsgi_poll.revents & POLLIN) {
if (uwsgi_poll.revents & POLLIN || uwsgi_poll.revents & POLLHUP) {
cnt = recv(uwsgi_poll.fd, buf, 4096, 0) ;
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
if (errno != ECONNRESET) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
else {
break;
}
}
else if (cnt > 0) {
if (!c->cgi_mode && uwsgi_http_status_read < 12) {
@@ -479,29 +503,27 @@ static int uwsgi_handler(request_rec *r) {
if (r->connection->aborted) {
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
hret = ap_fflush(r->output_filters, bb) ;
if (hret != APR_SUCCESS) {
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
return hret;
}
}
else {
// EOF
break;
}
}
if (uwsgi_poll.revents & POLLHUP || uwsgi_poll.revents & POLLERR || uwsgi_poll.revents & POLLNVAL) {
break;
}
// error
if (uwsgi_poll.revents & POLLERR || uwsgi_poll.revents & POLLNVAL) {
break;
}
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -515,6 +537,7 @@ static int uwsgi_handler(request_rec *r) {
if (!c->cgi_mode) {
if (uwsgi_http_status_read == 0) {
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -522,11 +545,13 @@ static int uwsgi_handler(request_rec *r) {
if (hret = ap_scan_script_header_err_brigade(r, bb, NULL)) {
apr_brigade_destroy(bb);
free(uwsgi_vars);
return hret;
}
}
free(uwsgi_vars);
return ap_pass_brigade(r->output_filters, bb) ;
}
@@ -558,6 +583,22 @@ static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const
}
static const char *cmd_uwsgi_max_vars(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
int val ;
if (cfg) {
c = cfg ;
}
else {
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
c->max_vars = atoi(value);
return NULL;
}
static const char * cmd_uwsgi_modifier1(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
@@ -592,7 +633,7 @@ static const char * cmd_uwsgi_force_cgi_mode(cmd_parms *cmd, void *cfg, const ch
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value)) {
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
c->cgi_mode = 1 ;
}
@@ -693,6 +734,28 @@ static const char * cmd_uwsgi_socket(cmd_parms *cmd, void *cfg, const char *path
return NULL ;
}
static const char * cmd_uwsgi_empty_remote_user(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
if (cfg) {
c = cfg ;
}
else {
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
c->empty_remote_user = 1;
}
else {
c->empty_remote_user = 0;
}
return NULL ;
}
static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE12("uWSGIsocket", cmd_uwsgi_socket, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path and optional timeout in seconds of uwsgi server socket"),
AP_INIT_TAKE1("uWSGIsocket2", cmd_uwsgi_socket2, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path of failover uwsgi server socket"),
@@ -701,6 +764,8 @@ static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
AP_INIT_TAKE1("uWSGIemptyRemoteUser", cmd_uwsgi_empty_remote_user, NULL, ACCESS_CONF, "Always include REMOTE_USER in the environment, even with an empty value (default true)"),
AP_INIT_TAKE1("uWSGImaxVars", cmd_uwsgi_max_vars, NULL, ACCESS_CONF, "Set the maximum allowed number of uwsgi variables (default 128)"),
{NULL}
};
+377 -398
View File
@@ -1,459 +1,438 @@
#ifdef UWSGI_ASYNC
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef __linux__
#include <sys/epoll.h>
int async_queue_init(int serverfd) {
int epfd ;
struct epoll_event ee;
epfd = epoll_create(256);
if (epfd < 0) {
uwsgi_error("epoll_create()");
return -1 ;
}
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = serverfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, serverfd, &ee)) {
uwsgi_error("epoll_ctl()");
close(epfd);
return -1;
}
return epfd;
struct wsgi_request *find_wsgi_req_proto_by_fd(int fd) {
return uwsgi.async_proto_fd_table[fd];
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
return uwsgi.async_waiting_fd_table[fd];
}
int ret ;
void runqueue_remove(struct uwsgi_async_request *u_request) {
if (timeout <= 0) {
timeout = block;
struct uwsgi_async_request *parent = u_request->prev;
struct uwsgi_async_request *child = u_request->next;
if (parent) {
parent->next = child;
}
if (child) {
child->prev = parent;
}
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
if (u_request == uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last = parent;
}
free(u_request);
uwsgi.async_runqueue_cnt--;
}
void runqueue_push(struct wsgi_request *wsgi_req) {
struct uwsgi_async_request *uar;
if (uwsgi.async_runqueue == NULL) {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
uwsgi.async_runqueue_cnt++;
}
struct wsgi_request *find_first_available_wsgi_req() {
struct wsgi_request *wsgi_req;
if (uwsgi.async_queue_unused_ptr < 0) {
return NULL;
}
wsgi_req = uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr];
uwsgi.async_queue_unused_ptr--;
return wsgi_req;
}
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
time_t current_time = time(NULL);
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for(;;) {
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (urbt == NULL) return;
if (urbt->key <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
uaf = wsgi_req->waiting_fds;
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
while(uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
current_uaf = uaf;
uaf = current_uaf->next;
free(current_uaf);
}
wsgi_req->waiting_fds = NULL;
// put th request in the runqueue
runqueue_push(wsgi_req);
continue;
}
break;
}
}
void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0) return ;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_read();
uad->prev = last_uad;
uad->next = NULL;
if (last_uad) {
last_uad->next = uad;
}
else {
timeout = timeout*1000;
wsgi_req->waiting_fds = uad;
}
//uwsgi_log("waiting with timeout %d nevents %d\n", timeout, nevents);
ret = epoll_wait(queuefd, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
uwsgi_error("epoll_wait()");
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
return ret ;
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_read(uwsgi.async_queue, fd);
}
int async_add(int queuefd, int fd, int etype) {
struct epoll_event ee;
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, time(NULL)+timeout, wsgi_req);
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
struct epoll_event ee;
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (epoll_ctl(queuefd, EPOLL_CTL_MOD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
if (fd < 0) return ;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
return 0;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_write();
uad->prev = last_uad;
uad->next = NULL;
int async_del(int queuefd, int fd, int etype) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
return 0;
}
#elif defined(__sun__)
int async_queue_init(int serverfd) {
int dpfd ;
struct pollfd dpev;
dpfd = open("/dev/poll", O_RDWR);
if (dpfd < 0) {
uwsgi_error("open()");
return -1 ;
}
dpev.fd = serverfd;
dpev.events = POLLIN ;
dpev.revents = 0;
if (write(dpfd, &dpev, sizeof(struct pollfd)) < 0) {
uwsgi_error("write()");
return -1;
}
return dpfd;
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret ;
struct dvpoll dv ;
if (timeout <= 0) {
timeout = block;
}
else {
timeout = timeout*1000;
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
dv.dp_fds = (struct pollfd *) events;
dv.dp_nfds = nevents;
dv.dp_timeout = timeout;
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_write(uwsgi.async_queue, fd);
//uwsgi_log("waiting with timeout %d nevents %d\n", timeout, nevents);
ret = ioctl(queuefd, DP_POLL, &dv);
if (ret < 0) {
uwsgi_error("ioctl()");
}
return ret ;
}
int async_add(int queuefd, int fd, int etype) {
struct pollfd pl;
pl.fd = fd ;
pl.events = etype ;
pl.revents = 0 ;
if (write(queuefd, &pl, sizeof(struct pollfd)) < 0) {
uwsgi_error("write()");
return -1;
}
return 0;
void async_schedule_to_req(void) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
}
int async_mod(int queuefd, int fd, int etype) {
// using the same fd will overwrite existing rule
return async_add(queuefd, fd, etype);
}
void *async_loop(void *arg1) {
int async_del(int queuefd, int fd, int etype) {
// use POLLREMOVE to remove an fd
return async_add(queuefd, fd, POLLREMOVE);
}
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
struct uwsgi_rb_timer *min_timeout;
int timeout;
int is_a_new_connection;
int proto_parser_status;
#else
int async_queue_init(int serverfd) {
int kfd ;
struct kevent kev;
time_t now, last_now = 0;
kfd = kqueue();
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
if (kfd < 0) {
uwsgi_error("kqueue()");
return -1 ;
void *events = event_queue_alloc(64);
struct uwsgi_socket *uwsgi_sock;
uwsgi.async_runqueue = NULL;
uwsgi.async_runqueue_cnt = 0;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
}
EV_SET(&kev, serverfd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(kfd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
return kfd;
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret;
struct timespec ts ;
if (timeout <= 0) {
if (!block) {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout ;
ret = kevent(queuefd, NULL, 0, events, nevents, &ts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
else {
ret = kevent(queuefd, NULL, 0, events, nevents, NULL);
}
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout ;
ret = kevent(queuefd, NULL, 0, events, nevents, &ts);
}
if (ret < 0) {
uwsgi_error("kevent()");
}
return ret;
}
int async_add(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, etype, EV_ADD, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, ASYNC_OUT, EV_DISABLE, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
EV_SET(&kev, fd, etype, EV_ADD, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
int async_del(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, etype, EV_DELETE, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
#endif
inline struct wsgi_request *next_wsgi_req(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
uint8_t *ptr = (uint8_t *) wsgi_req ;
ptr += sizeof(struct wsgi_request) ;
return (struct wsgi_request *) ptr ;
}
int async_get_timeout(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
if (!uwsgi->async_running) return 0;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_timeout_expired) {
return 0;
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return 0;
}
void async_expire_timeouts(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t deadline = time(NULL);
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN && wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_timeout = 0 ;
wsgi_req->async_timeout_expired = 1 ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_OK) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return NULL ;
}
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *uwsgi, int async_id) {
uint8_t *ptr = (uint8_t *) uwsgi->wsgi_requests ;
ptr += sizeof(struct wsgi_request) * async_id ;
return (struct wsgi_request *) ptr ;
}
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *uwsgi, int fd, int etype) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
if (etype != -1) {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd && wsgi_req->async_waiting_fd_type == etype) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
else {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
return NULL ;
}
void async_set_timeout(struct wsgi_request *wsgi_req, time_t timeout) {
wsgi_req->async_timeout = time(NULL);
wsgi_req->async_timeout += timeout;
wsgi_req->async_timeout_expired = 0 ;
}
void async_write_all(struct uwsgi_server *uwsgi, char *data, size_t len) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
ssize_t rlen ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
uwsgi_error("write()");
if (min_timeout) {
timeout = min_timeout->key - time(NULL);
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
}
}
else {
wsgi_req->response_size += rlen ;
timeout = -1;
}
}
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
// timeout ???
if (uwsgi.async_nevents == 0) {
async_expire_timeouts();
}
}
}
void async_unpause_all(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
}
}
}
struct wsgi_request * async_loop(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req ;
int i ;
uwsgi->async_running = -1 ;
wsgi_req = uwsgi->wsgi_requests ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_waiting_fd != -1 && !wsgi_req->async_waiting_fd_monitored) {
// add fd to monitoring
if (async_add(uwsgi->async_queue, wsgi_req->async_waiting_fd, wsgi_req->async_waiting_fd_type)) {
// error adding fd to the async queue, better to close it...
close(wsgi_req->async_waiting_fd);
wsgi_req->async_status = UWSGI_OK ;
return wsgi_req;
for(i=0;i<uwsgi.async_nevents;i++) {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
is_a_new_connection = 0;
// new request coming in ?
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (interesting_fd == uwsgi_sock->fd) {
is_a_new_connection = 1;
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
now = time(NULL);
if (now > last_now) {
uwsgi_log("async queue is full !!!\n");
last_now = now;
}
break;;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi_sock->arg) < 0) {
uwsgi_error("fcntl()");
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
}
#endif
if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
runqueue_push(uwsgi.wsgi_req);
}
break;
}
wsgi_req->async_waiting_fd_monitored = 1;
wsgi_req->async_status = UWSGI_AGAIN;
uwsgi_sock = uwsgi_sock->next;
}
else if (wsgi_req->async_waiting_fd == -1 && wsgi_req->async_timeout <= 0) {
uwsgi->async_running = 0 ;
// st global wsgi_req for python functions
uwsgi->wsgi_req = wsgi_req ;
wsgi_req->async_status = (*uwsgi->shared->hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
wsgi_req->async_switches++;
if (wsgi_req->async_status < UWSGI_AGAIN) {
return wsgi_req;
if (!is_a_new_connection) {
// proto event
uwsgi.wsgi_req = find_wsgi_req_proto_by_fd(interesting_fd);
if (uwsgi.wsgi_req) {
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
// reset timeout
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
// parsing complete
if (!proto_parser_status) {
// remove fd from event poll and fd proto table
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
#endif
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
continue;
}
else if (proto_parser_status == -1) {
uwsgi_log("error parsing request\n");
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
close(interesting_fd);
continue;
}
// re-add timer
async_add_timeout(uwsgi.wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
continue;
}
// app event
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
// unknown fd, remove it (for safety)
if (uwsgi.wsgi_req == NULL) {
close(interesting_fd);
continue;
}
// remove all the fd monitors and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
uwsgi.wsgi_req->async_ready_fd = 1;
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
// event queue managed, give cpu to runqueue
if (!current_request)
current_request = uwsgi.async_runqueue;
if (uwsgi.async_runqueue_cnt) {
uwsgi.wsgi_req = current_request->wsgi_req;
uwsgi.schedule_to_req();
uwsgi.wsgi_req->switches++;
next_async_request = current_request->next;
// request ended ?
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
// remove all the monitored fds and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
// remove from the list
runqueue_remove(current_request);
uwsgi_close_request(uwsgi.wsgi_req);
// push wsgi_request in the unused stack
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from suspended list
runqueue_remove(current_request);
}
current_request = next_async_request;
}
}
return NULL;
}
#endif
+13
View File
@@ -0,0 +1,13 @@
import struct
import sys
import os
filename = sys.argv[1]
size = os.path.getsize(filename)
f = open(filename, 'r')
print(f.read())
f.close()
print(struct.pack("<Q", size))
+5
View File
@@ -0,0 +1,5 @@
import sys
import uwsgi
print("i am the bootstrap for uwsgi.SymbolsImporter")
sys.meta_path.insert(0, uwsgi.SymbolsImporter())
+4
View File
@@ -0,0 +1,4 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("pygments_zip"))
+5
View File
@@ -0,0 +1,5 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("django_zip:djenv/lib/python2.6/site-packages"))
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("djapp_zip"))
+4
View File
@@ -0,0 +1,4 @@
import sys
import uwsgi
sys.meta_path.insert(0, uwsgi.ZipImporter("data://0"))
+3
View File
@@ -0,0 +1,3 @@
import uwsgi
print uwsgi.extract("data://0")
+1
View File
@@ -0,0 +1 @@
object file for embedded files will be put here
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = null
+44
View File
@@ -0,0 +1,44 @@
[uwsgi]
xml = true
ini = true
yaml = true
json = auto
sqlite3 = auto
zeromq = auto
snmp = true
sctp = false
spooler = true
embedded = true
udp = true
multicast = true
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = auto
pcre = auto
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = python, ping, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
embed_files =
embed_config =
[python]
paste = true
web3 = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embed_files = bootstrap3.py,django.zip,djapp.zip
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = default
embed_files = embedme.py,uwsgidecorators.py
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,erlang
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, gevent
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = null
as_shared_library = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = lua
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
plugins = lua
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
plugins = python, ping, rack, psgi, cache, http, fastrouter
plugin_dir = plugins
embedded_plugins = null
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = default
plugin_dir = /usr/lib/uwsgi
embedded_plugins = null
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = psgi
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,erlang,pyerl
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,lua
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = symcall
as_shared_library = true
+31
View File
@@ -0,0 +1,31 @@
[uwsgi]
xml = true
ini = true
snmp = true
sctp = false
erlang = false
spooler = true
embedded = true
udp = true
multicast = true
threading = true
sendfile = true
proxy = true
minterpreters = true
async = true
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rack
[python]
paste = true
web3 = true
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = default
bin_name = pyuwsgi.so
embedded_plugins = pyuwsgi,python,ping,cache,nagios,rpc,ugreen
as_shared_library = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = rack, ping, cache, nagios, rpc, fastrouter, http, ugreen
+30
View File
@@ -0,0 +1,30 @@
[uwsgi]
xml = true
ini = true
yaml = true
snmp = true
sctp = false
erlang = false
spooler = false
embedded = false
udp = true
multicast = false
threading = true
sendfile = true
nagios = true
proxy = true
minterpreters = true
async = true
ugreen = false
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins = rack
bin_name = uwsgi
plugin_dir = .
embedded_plugins =
+35
View File
@@ -0,0 +1,35 @@
[uwsgi]
xml = true
ini = true
yaml = true
json = true
sqlite3 = false
zeromq = false
snmp = false
sctp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = true
pcre = false
debug = false
unbit = true
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
plugins =
bin_name = /opt/unbit/bin/uwsgi
append_version = unbit
plugin_dir = /opt/unbit/uwsgi_plugins
embedded_plugins =
locking = auto
event = auto
timer = auto
filemonitor = auto
+6
View File
@@ -0,0 +1,6 @@
[uwsgi]
inherit = unbit
json = false
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
+423
View File
@@ -0,0 +1,423 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_init_cache() {
int i;
if (!uwsgi.cache_blocksize)
uwsgi.cache_blocksize = UMAX16;
if ((uwsgi.cache_blocksize * uwsgi.cache_max_items) % uwsgi.page_size != 0) {
uwsgi_log("invalid cache blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.cache_blocksize, uwsgi.page_size);
exit(1);
}
uwsgi.cache_hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache_hashtable) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.cache_hashtable, 0, sizeof(uint64_t) * UMAX16);
uwsgi.cache_unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache_unused_stack) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.cache_unused_stack, 0, sizeof(uint64_t) * uwsgi.cache_max_items);
// the first cache item is always zero
uwsgi.shared->cache_first_available_item = 1;
uwsgi.shared->cache_unused_stack_ptr = 0;
//uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (uwsgi.cache_store) {
uwsgi.cache_filesize = (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items);
int cache_fd;
struct stat cst;
if (stat(uwsgi.cache_store, &cst)) {
uwsgi_log("creating a new cache store file: %s\n", uwsgi.cache_store);
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (cache_fd >= 0) {
// fill the caching store
if (ftruncate(cache_fd, uwsgi.cache_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
if ((size_t) cst.st_size != uwsgi.cache_filesize || !S_ISREG(cst.st_mode)) {
uwsgi_log("invalid cache store file. Please remove it or fix cache blocksize/items to match its size\n");
exit(1);
}
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
uwsgi_log("recovered cache from backing store file: %s\n", uwsgi.cache_store);
}
if (cache_fd < 0) {
uwsgi_error_open(uwsgi.cache_store);
exit(1);
}
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, uwsgi.cache_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
uwsgi_cache_fix();
}
else {
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
}
}
if (!uwsgi.cache_items) {
uwsgi_error("mmap()");
exit(1);
}
/*
uwsgi.cache = mmap(NULL, uwsgi.cache_blocksize * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache) {
uwsgi_error("mmap()");
exit(1);
}
*/
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
uwsgi.cache_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.cache_lock);
uwsgi_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));
}
uint32_t djb33x_hash(char *key, int keylen) {
register uint32_t hash = 5381;
int i;
for(i=0;i<keylen;i++) {
hash = ((hash << 5) + hash) ^ key[i];
}
return hash;
}
inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
uint64_t slot = uwsgi.cache_hashtable[hash_key];
struct uwsgi_cache_item *uci;
//uwsgi_log("found slot %d for key %d\n", slot, hash_key);
uci = &uwsgi.cache_items[slot];
// first round
if (uci->djbhash != hash) goto cycle;
if (uci->keysize != keylen) goto cycle;
if (memcmp(uci->key, key, keylen)) goto cycle;
return slot;
cycle:
while(uci->next) {
slot = uci->next;
uci = &uwsgi.cache_items[slot];
if (uci->djbhash != hash) continue;
if (uci->keysize != keylen) continue;
if (!memcmp(uci->key, key, keylen)) return slot;
}
return 0;
}
uint32_t uwsgi_cache_exists(char *key, uint16_t keylen) {
return uwsgi_cache_get_index(key, keylen);
}
char *uwsgi_cache_get(char *key, uint16_t keylen, uint64_t *valsize) {
uint64_t index = uwsgi_cache_get_index(key, keylen);
if (index) {
if (uwsgi.cache_items[index].flags & UWSGI_CACHE_FLAG_UNGETTABLE) return NULL;
*valsize = uwsgi.cache_items[index].valsize;
uwsgi.cache_items[index].hits++;
return uwsgi.cache+(index*uwsgi.cache_blocksize);
}
return NULL;
}
int uwsgi_cache_del(char *key, uint16_t keylen) {
uint64_t index = 0;
struct uwsgi_cache_item *uci;
int ret = -1;
index = uwsgi_cache_get_index(key, keylen);
if (index) {
uci = &uwsgi.cache_items[index] ;
uci->keysize = 0;
uci->valsize = 0;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = index;
// try to return to initial condition...
if (index == uwsgi.shared->cache_first_available_item-1) {
uwsgi.shared->cache_first_available_item--;
//uwsgi_log("FACI: %llu STACK PTR: %llu\n", (unsigned long long) uwsgi.shared->cache_first_available_item, (unsigned long long) uwsgi.shared->cache_unused_stack_ptr);
}
ret = 0;
// relink collisioned entry
if (uci->prev) {
uwsgi.cache_items[uci->prev].next = uci->next;
}
if (uci->next) {
uwsgi.cache_items[uci->next].prev = uci->prev;
}
if (!uci->prev && !uci->next) {
// reset hashtable entry
//uwsgi_log("!!! resetted hashtable entry !!!\n");
uwsgi.cache_hashtable[uci->djbhash % 0xffff] = 0;
}
uci->djbhash = 0;
uci->prev = 0;
uci->next = 0;
}
return ret;
}
void uwsgi_cache_fix() {
uint64_t i;
for(i=0;i< uwsgi.cache_max_items;i++) {
// valid record ?
if (uwsgi.cache_items[i].keysize) {
if (!uwsgi.cache_items[i].prev) {
// put value in hash_table
uwsgi.cache_hashtable[ uwsgi.cache_items[i].djbhash % 0xffff] = i;
}
}
else {
// put this record in unused stack
uwsgi.shared->cache_first_available_item = i;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = i;
}
}
}
int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint16_t flags) {
uint64_t index = 0, last_index = 0 ;
struct uwsgi_cache_item *uci, *ucii;
int ret = -1;
int slot;
if (!keylen || !vallen) return -1;
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
if (uwsgi.shared->cache_first_available_item >= uwsgi.cache_max_items && !uwsgi.shared->cache_unused_stack_ptr) {
uwsgi_log("*** DANGER cache is FULL !!! ***\n");
goto end;
}
//uwsgi_log("putting cache data in key %.*s %d\n", keylen, key, vallen);
index = uwsgi_cache_get_index(key, keylen);
if (!index) {
if (uwsgi.shared->cache_unused_stack_ptr) {
//uwsgi_log("!!! REUSING CACHE SLOT !!! (faci: %llu)\n", (unsigned long long) uwsgi.shared->cache_first_available_item);
index = uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr];
uwsgi.shared->cache_unused_stack_ptr--;
}
else {
index = uwsgi.shared->cache_first_available_item;
if (uwsgi.shared->cache_first_available_item < uwsgi.cache_max_items) {
uwsgi.shared->cache_first_available_item++;
}
}
uci = &uwsgi.cache_items[index] ;
if (expires) expires += time(NULL);
uci->expires = expires;
uci->djbhash = djb33x_hash(key, keylen);
uci->hits = 0;
uci->flags = flags;
memcpy(uci->key, key, keylen);
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
// set this as late as possibile (to reduce races risk)
uci->valsize = vallen;
uci->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
slot = uci->djbhash % 0xffff;
if (uwsgi.cache_hashtable[slot] == 0) {
uwsgi.cache_hashtable[slot] = index;
}
else {
//uwsgi_log("HASH COLLISION !!!!\n");
// append to first available next
last_index = uwsgi.cache_hashtable[slot];
ucii = &uwsgi.cache_items[ last_index ];
while(ucii->next) {
last_index = ucii->next;
ucii = &uwsgi.cache_items[ last_index ];
}
ucii->next = index;
uci->prev = last_index;
}
}
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = &uwsgi.cache_items[index] ;
if (expires) {
expires += time(NULL);
uci->expires = expires;
}
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
uci->valsize = vallen;
ret = 0;
}
end:
return ret;
}
/* THIS PART IS HEAVILY OPTIMIZED: PERFORMANCE NOT ELEGANCE !!! */
void *cache_thread_loop(void *fd_ptr) {
int *fd_tmp = (int *) fd_ptr;
int fd = *fd_tmp;
int i;
ssize_t len;
char uwsgi_packet[UMAX16+4];
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi_packet;
char *val;
uint64_t vallen;
char *key;
uint16_t keylen;
struct pollfd ctl_poll;
char *watermark;
struct sockaddr_un ctl_sun;
socklen_t ctl_sun_len;
ctl_poll.events = POLLIN;
for(;;) {
ctl_sun_len = sizeof(struct sockaddr_un);
pthread_mutex_lock(&uwsgi.cache_server_lock);
ctl_poll.fd = accept(fd, (struct sockaddr *) &ctl_sun, &ctl_sun_len);
pthread_mutex_unlock(&uwsgi.cache_server_lock);
if (ctl_poll.fd < 0) {
uwsgi_error("cache accept()");
continue;
}
i = 0;
while(i < 4) {
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (len <= 0) {
uwsgi_error("cache poll()");
goto clear;
}
len = read(ctl_poll.fd, uwsgi_packet+i, 4-i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i+=len;
}
if (uh->pktsize == 0) goto clear;
while(i < 4+uh->pktsize) {
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (len <= 0) {
uwsgi_error("cache poll()");
goto clear;
}
len = read(ctl_poll.fd, uwsgi_packet+i, (4+uh->pktsize)-i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i+=len;
}
watermark = uwsgi_packet+4+uh->pktsize;
// get first parameter
memcpy(&keylen, uwsgi_packet+4, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
#endif
if (uwsgi_packet+6+keylen > watermark) goto clear;
key = uwsgi_packet+6+keylen+2;
memcpy(&keylen, key-2, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
#endif
if (key+keylen > watermark) goto clear;
val = uwsgi_cache_get(key, keylen, &vallen);
if (val && vallen > 0) {
if (write(ctl_poll.fd, val, vallen) < 0) {
uwsgi_error("cache write()");
}
}
clear:
close(ctl_poll.fd);
}
return NULL;
}
int uwsgi_cache_server(char *socket, int threads) {
int *fd = uwsgi_malloc(sizeof(int));
int i;
pthread_t thread_id;
char *tcp_port = strchr(socket, ':');
if (tcp_port) {
*fd = bind_to_tcp(socket, uwsgi.listen_queue, tcp_port);
}
else {
*fd = bind_to_unix(socket, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
pthread_mutex_init(&uwsgi.cache_server_lock, NULL);
if (threads < 1) threads = 1;
uwsgi_log("*** cache-optimized server enabled on fd %d (%d threads) ***\n", *fd, threads);
for(i=0;i<threads;i++) {
pthread_create(&thread_id, NULL, cache_thread_loop, (void *) fd);
}
return *fd;
}
+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
+18
View File
@@ -0,0 +1,18 @@
require 'fiber'
require 'sinatra'
get '/hi' do
class Response
def each
for i in 1..10
yield "ciao<br/>"
Fiber.yield
end
end
end
Response.new
end
run Sinatra::Application
+25
View File
@@ -0,0 +1,25 @@
require 'stringio'
hello = proc do |signum|
puts "Hello i am signal #{signum}"
end
file_changed = proc do |signum|
puts "/tmp has been modified"
end
UWSGI.register_signal(17, '', hello)
UWSGI.register_signal(30, '', file_changed)
UWSGI.add_rb_timer(17 , 2)
UWSGI.add_timer(17 , 1)
UWSGI.add_file_monitor(30 , '/tmp')
puts UWSGI.signal_registered(1)
puts UWSGI.signal_registered(17)
run lambda { |env|
puts env.inspect
UWSGI.signal(17)
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World!\n")]
}
+7
View File
@@ -0,0 +1,7 @@
require 'sinatra'
get '/hi' do
"Hello World"
end
run Sinatra::Application
+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")]
}
+68 -68
View File
@@ -17,10 +17,10 @@ sub new {
sub run {
my ($self, $app) = @_;
my $server ;
my $server;
if (exists($ENV{'UWSGI_FD'})) {
$server = IO::Socket::UNIX->new_from_fd($ENV{'UWSGI_FD'}, '+<');
$server = IO::Socket::UNIX->new_from_fd($ENV{'UWSGI_FD'}, '+<');
}
else {
$server = IO::Socket::INET->new(LocalPort => $self->{port}, LocalAddr => $self->{host}, Listen => 100, ReuseAddr => 1);
@@ -28,62 +28,62 @@ sub run {
while ( my $client = $server->accept ) {
my $head = '';
my $remains = 4 ;
my $head = '';
my $remains = 4;
while($remains) {
$client->recv(my $buf, $remains);
last unless $buf;
$head.=$buf;
$remains -= length($buf);
}
while($remains) {
$client->recv(my $buf, $remains);
last unless $buf;
$head.=$buf;
$remains -= length($buf);
}
if (length($head) != 4) {
$client->close ;
next;
}
if (length($head) != 4) {
$client->close;
next;
}
my ($mod1, $envsize, $mod2) = unpack('CvC', $head) ;
my ($mod1, $envsize, $mod2) = unpack('CvC', $head);
unless ($envsize) {
$client->close ;
next;
}
unless ($envsize) {
$client->close;
next;
}
$remains = $envsize ;
my $envbuf = '' ;
while($remains) {
my $buf ;
if ($remains >= 4096) {
$client->recv($buf, 4096);
}
else {
$client->recv($buf, $remains);
}
$remains = $envsize;
my $envbuf = '';
while($remains) {
my $buf;
if ($remains >= 4096) {
$client->recv($buf, 4096);
}
else {
$client->recv($buf, $remains);
}
unless($buf) {
$client->close ;
next;
}
unless($buf) {
$client->close;
next;
}
$envbuf.=$buf;
$remains -= length($buf);
}
$envbuf.=$buf;
$remains -= length($buf);
}
if (length($envbuf) != $envsize ) {
$client->close ;
next;
}
if (length($envbuf) != $envsize ) {
$client->close;
next;
}
my %env ;
my %env;
my $i = 0;
while($i < $envsize) {
my $kl = unpack('v', substr($envbuf, $i, 2)) ; $i+=2;
my $key = substr($envbuf, $i, $kl); $i+=$kl;
my $vl = unpack('v', substr($envbuf, $i, 2)) ; $i+=2;
$env{$key} = substr($envbuf, $i, $vl); $i+=$vl;
}
my $i = 0;
while($i < $envsize) {
my $kl = unpack('v', substr($envbuf, $i, 2)); $i+=2;
my $key = substr($envbuf, $i, $kl); $i+=$kl;
my $vl = unpack('v', substr($envbuf, $i, 2)); $i+=2;
$env{$key} = substr($envbuf, $i, $vl); $i+=$vl;
}
my $env = {
%env,
@@ -105,40 +105,40 @@ sub run {
}
elsif (ref $res eq 'CODE') {
$res->(sub {
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $_[0]);
});
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $_[0]);
});
}
else {
die "Bad response $res";
}
$client->close ;
$client->close;
}
}
sub _handle_response {
my ($self, $client, $protocol, $res) = @_;
my ($self, $client, $protocol, $res) = @_;
$client->send($protocol.' '.$res->[0].' '.HTTP::Status::status_message( $res->[0] )."\r\n");
$client->send($protocol.' '.$res->[0].' '.HTTP::Status::status_message( $res->[0] )."\r\n");
my $headers = $res->[1];
my $hdrs = '';
while (my ($k, $v) = splice @$headers, 0, 2) {
$hdrs .= "$k: $v\r\n";
}
$hdrs .= "\r\n";
my $headers = $res->[1];
my $hdrs = '';
while (my ($k, $v) = splice @$headers, 0, 2) {
$hdrs .= "$k: $v\r\n";
}
$hdrs .= "\r\n";
$client->send($hdrs);
$client->send($hdrs);
my $cb = sub { $client->send($_[0]) };
my $body = $res->[2];
if (defined $body) {
Plack::Util::foreach($body, $cb);
}
else {
return Plack::Util::inline_object write => $cb,close => sub { };
}
my $cb = sub { $client->send($_[0]) };
my $body = $res->[2];
if (defined $body) {
Plack::Util::foreach($body, $cb);
}
else {
return Plack::Util::inline_object write => $cb,close => sub { };
}
}
1;
+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
+33
View File
@@ -0,0 +1,33 @@
# uwsgi --master --chdir /opt/graphite/webapp/graphite --module graphite_uwsgi ...
#
#
# this module will update a carbon server (used by the graphite tool: http://graphite.wikidot.com/)
# with requests count made by a Django app (and can track graphite itself as it is a Django app ;)
#
#
import os
import uwsgi
import time
from django.core.handlers.wsgi import WSGIHandler
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
CARBON_SERVER = "127.0.0.1:2003"
def update_carbon(signum):
# connect to the carbon server
carbon_fd = uwsgi.connect(CARBON_SERVER)
# send data to the carbon server
uwsgi.send(carbon_fd, "uwsgi.%s.requests %d %d\n" % (uwsgi.hostname, uwsgi.total_requests(), int(time.time())))
# close the connection with the carbon server
uwsgi.close(carbon_fd)
# register a new uwsgi signal (signum: 17)
uwsgi.register_signal(17, '', update_carbon)
# attach a timer of 10 seconds to signal 17
uwsgi.add_timer(17, 10)
# the Django app
application = WSGIHandler()
+66
View File
@@ -0,0 +1,66 @@
import django
from django.core.management.base import BaseCommand
from django.conf import settings
import os
import sys
class Command(BaseCommand):
help = "Runs this project as a uWSGI application. Requires the uwsgi binary in system path."
http_port = '8000'
socket_addr = None
def handle(self, *args, **options):
for arg in args:
k,v = arg.split('=')
if k == 'http':
if self.http_port:
self.http_port = v
elif k == 'socket':
self.http_port = None
self.socket_addr = v
# load http and python plugin: first the specific version, otherwise try with the generic one
if self.http_port:
os.environ['UWSGI_PLUGINS'] = 'http,python%d%d:python' % (sys.version_info[0], sys.version_info[1])
else:
os.environ['UWSGI_PLUGINS'] = 'python%d%d:python' % (sys.version_info[0], sys.version_info[1])
# load the Django WSGI handler
os.environ['UWSGI_MODULE'] = 'django.core.handlers.wsgi:WSGIHandler()'
# DJANGO settings
if options['settings']:
os.environ['DJANGO_SETTINGS_MODULE'] = options['settings']
else:
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
# bind the http server to the default port
if self.http_port:
os.environ['UWSGI_HTTP'] = ':%s' % self.http_port
elif self.socket_addr:
os.environ['UWSGI_SOCKET'] = self.socket_addr
# map admin static files
os.environ['UWSGI_STATIC_MAP'] = '%s=%s' % (settings.ADMIN_MEDIA_PREFIX, os.path.join(django.__path__[0], 'contrib', 'admin', 'media'))
# remove sockets/pidfile at exit
os.environ['UWSGI_VACUUM'] = '1'
# retrieve/set the PythonHome
os.environ['UWSGI_PYHOME'] = sys.prefix
# increase buffer size a bit
os.environ['UWSGI_BUFFER_SIZE'] = '8192'
# add threads for concurrency
os.environ['UWSGI_THREADS'] = '8'
# enable the master process
os.environ['UWSGI_MASTER'] = '1'
# use uWSGI python module aliasing to fix the PYTHONPATH
os.environ['UWSGI_PYMODULE_ALIAS'] = '%s=./' % os.path.basename(os.getcwd())
# exec the uwsgi binary
os.execvp('uwsgi', ('uwsgi',))
def usage(self, subcomand):
return r"""
run this project on the uWSGI server
http=PORT run the embedded http server on port PORT
socket=ADDR bind the uwsgi server on address ADDR (this will disable the http server)
"""
+11
View File
@@ -0,0 +1,11 @@
from tasksconsumer import enqueue
def application(env, sr):
sr('200 OK', [('Content-Type','text/html')])
enqueue(queue='fast', pippo='pluto')
return "Task enqueued"
+9
View File
@@ -0,0 +1,9 @@
from tasksconsumer import *
@queueconsumer('fast', 4)
def fast_queue(arguments):
print "fast", arguments
@queueconsumer('slow')
def slow_queue(arguments):
print "foobar", arguments
+44
View File
@@ -0,0 +1,44 @@
from uwsgidecorators import *
import Queue
from threading import Thread
queues = {}
class queueconsumer(object):
def __init__(self, name, num=1, **kwargs):
self.name = name
self.num = num
self.queue = Queue.Queue()
self.threads = []
self.func = None
queues[self.name] = self
@staticmethod
def consumer(self):
while True:
req = self.queue.get()
print req
self.func(req)
self.queue.task_done()
def __call__(self, f):
self.func = f
for i in range(self.num):
t = Thread(target=self.consumer,args=(self,))
self.threads.append(t)
t.daemon = True
t.start()
@spool
def spooler_enqueuer(arguments):
if 'queue' in arguments:
queue = arguments['queue']
queues[queue].queue.put(arguments)
else:
raise Exception("You have to specify a queue name")
def enqueue(*args, **kwargs):
return spooler_enqueuer.spool(*args, **kwargs)
+3 -1
View File
@@ -12,4 +12,6 @@ env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --no-orphans avoid workers without master
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -m simple_app --logto $LOGTO -M -p 4
# --die-on-term could be a good idea
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
+24 -1
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'
@@ -9,6 +13,7 @@ require 'optparse'
options = {
:processes => 1,
:threads => 1,
:master => false,
:logging => true,
:static => true,
@@ -19,6 +24,7 @@ options = {
opts = OptionParser.new do |opts|
opts.on("-p", "--processes=nproc", Integer, '') { |p| options[:processes] = p }
opts.on("-t", "--threads=nthreads", Integer, '') { |t| options[:threads] = t }
opts.on("-M", "--master", '') { options[:master] = true }
opts.on("-L", "--no-logging", '') { options[:logging] = false }
opts.on("-S", "--no-static", '') { options[:static] = false }
@@ -37,6 +43,7 @@ end
$requests = 0
$workers = Array.new
$mywid = 0
module Rack
@@ -74,12 +81,14 @@ module Rack
ulog("spawned worker 1 (pid: #{$workers[1]})")
elsif $workers[1].to_i == 0
$0 = "uRack worker 1"
$mywid = 1
can_spawn = false
end
else
$0 = 'uRack worker 1'
$workers[0] = nil
$workers[1] = Process.pid
$mywid = 1
ulog("spawned worker 1 (pid: #{$workers[1]})")
end
@@ -88,6 +97,7 @@ module Rack
$workers[p] = Process.fork
if $workers[p].to_i == 0
$0 = "uRack worker #{p}"
$mywid = p
break
elsif $workers[p].to_i > 0
ulog("spawned worker #{p} (pid: #{$workers[p]})")
@@ -107,6 +117,7 @@ module Rack
if $workers[wid].to_i == 0
$0 = "uRack worker #{wid}"
i_am_a_child = true
$mywid = wid
break
elsif $workers[wid].to_i > 0
ulog("respawned worker #{wid} (pid: #{$workers[wid]})")
@@ -118,9 +129,21 @@ module Rack
end
end
if options[:threads] > 2
for t in 2..options[:threads]
wt = Thread.new do
ulog("spawning thread #{t} on worker #{$mywid}")
while client = server.accept
serve client, app, options
end
end
end
end
while client = server.accept
serve client, app, options
serve client, app, options
end
end
def self.serve(client, app, options)
+30
View File
@@ -0,0 +1,30 @@
-module(uwsgi).
-export([encode/1,send/3]).
encode(Vars) ->
Body = lists:map(fun(X) -> Len = length(X), lists:append( binary_to_list(<<Len:16/little-unsigned-integer>>), X) end, Vars),
lists:flatten(Body).
response(Sock, Output) ->
case gen_tcp:recv(Sock,0) of
{ ok, Data } ->
response(Sock, lists:append(Output, binary_to_list(Data)));
{ error, closed } ->
gen_tcp:close(Sock),
Output
end.
send(Host, Port, Message) ->
{ ok, Sock } = gen_tcp:connect( Host, Port, [ binary, { active, false} ]),
Body = encode(Message),
Len = length(Body),
ok = gen_tcp:send(Sock, << 0, Len:16/little-unsigned-integer, 0>>),
ok = gen_tcp:send(Sock, Body),
response(Sock, []).
+27 -28
View File
@@ -6,7 +6,6 @@ import java.util.Enumeration;
import org.apache.catalina.util.IOTools;
public class uwsgi extends HttpServlet {
private String mountpoint = null;
public void init(ServletConfig config) throws ServletException {
@@ -22,34 +21,34 @@ public class uwsgi extends HttpServlet {
if (getServletConfig().getInitParameter("mountpoint") != null) {
mountpoint = getServletConfig().getInitParameter("mountpoint");
if (mountpoint.length() <= 1) {
mountpoint = null ;
mountpoint = null;
}
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
throws IOException, ServletException {
uWSGIHandler(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
throws IOException, ServletException {
uWSGIHandler(request, response);
}
private void uWSGIHandler(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
throws IOException, ServletException {
Socket client = new Socket("localhost",3017);
ByteArrayOutputStream uwsgi_request = new ByteArrayOutputStream() ;
ByteArrayOutputStream uwsgi_request = new ByteArrayOutputStream();
DataOutputStream wos = new DataOutputStream(uwsgi_request);
DataOutputStream os = new DataOutputStream(client.getOutputStream());
DataInputStream is = new DataInputStream( client.getInputStream() );
ServletOutputStream out = response.getOutputStream();
boolean hasBody = false;
@@ -104,14 +103,14 @@ public class uwsgi extends HttpServlet {
if (mountpoint != null) {
wos.writeShort(swapShort( (short) 11));
wos.writeBytes("SCRIPT_NAME");
wos.writeShort(swapShort( (short) mountpoint.length() ) ) ;
wos.writeBytes( mountpoint ) ;
wos.writeBytes("SCRIPT_NAME");
wos.writeShort(swapShort( (short) mountpoint.length() ) );
wos.writeBytes( mountpoint );
}
wos.writeShort(swapShort( (short) 9));
wos.writeBytes("PATH_INFO");
wos.writeBytes("PATH_INFO");
if (mountpoint != null) {
wos.writeShort(swapShort( (short) (request.getRequestURI().length() - mountpoint.length()) ) );
wos.writeBytes( request.getRequestURI().substring(mountpoint.length()) );
@@ -149,14 +148,14 @@ public class uwsgi extends HttpServlet {
hasBody = true;
}
// taken from CGI servlet
Enumeration headers = request.getHeaderNames();
String header = null;
while (headers.hasMoreElements()) {
header = null;
header = ((String) headers.nextElement()).toUpperCase();
header = null;
header = ((String) headers.nextElement()).toUpperCase();
wos.writeShort(swapShort( (short) ("HTTP_" + header.replace('-', '_')).length() ));
wos.writeBytes("HTTP_" + header.replace('-', '_'));
wos.writeShort(swapShort( (short) request.getHeader(header).length() ));
@@ -175,16 +174,16 @@ public class uwsgi extends HttpServlet {
IOTools.flow(request.getInputStream(), os);
}
boolean statusParsed = false ;
boolean statusParsed = false;
for(;;) {
String line = byte_readline(is) ;
String line = byte_readline(is);
if (line == "") {
break;
}
if (statusParsed == false) {
String[] status = line.split(" ",3);
response.setStatus( Integer.parseInt(status[1]) );
statusParsed = true ;
statusParsed = true;
}
else {
String[] keyval = line.split(": ",2);
@@ -200,7 +199,7 @@ public class uwsgi extends HttpServlet {
byte cb[] = new byte[4096];
int len = 0;
for(;;) {
len = is.read(cb,0,4096) ;
len = is.read(cb,0,4096);
if ( len > 0) {
out.write(cb,0,len);
}
@@ -208,7 +207,7 @@ public class uwsgi extends HttpServlet {
break;
}
}
}
@@ -218,19 +217,19 @@ public class uwsgi extends HttpServlet {
for(;;) {
byte b = is.readByte();
if (b == 10) {
break ;
break;
}
line.write(b) ;
line.write(b);
}
return line.toString("ASCII").replaceAll("\\n","").replaceAll("\\r","");
}
private short swapShort(short x) {
short tmp1 = (short) (x>>8) ;
short tmp2 = (short) (x<<8) ;
return (short) (tmp1 | tmp2) ;
short tmp1 = (short) (x>>8);
short tmp2 = (short) (x<<8);
return (short) (tmp1 | tmp2);
}
}
+65 -65
View File
@@ -2,8 +2,8 @@
*** uWSGI cgi client ***
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_client.c
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_client.c
*/
@@ -18,79 +18,79 @@ to compile:
#define UWSGI_SOCK "/tmp/uwsgi.sock"
int main() {
extern char **environ;
char *env ;
struct sockaddr_un s_addr ;
int uwsgi_socket ;
int res, cnt;
char *place_holder;
unsigned short len ;
char message[4096];
char *mptr;
extern char **environ;
char *env;
struct sockaddr_un s_addr;
int uwsgi_socket;
int res, cnt;
char *place_holder;
unsigned short len;
char message[4096];
char *mptr;
char *content_length;
memset(&s_addr, 0, sizeof(struct sockaddr_un)) ;
memset(&s_addr, 0, sizeof(struct sockaddr_un));
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
memset(message, 0, 4096);
memset(message, 0, 4096);
mptr = message+4;
mptr = message+4;
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len ;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1)) ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len ;
*environ++;
}
}
message[0] = 0;
len = (mptr-message)-4 ;
memcpy(message+1, &len, 2) ;
message[3] = 0 ;
res = send(uwsgi_socket, message, mptr-message, 0);
if ( (content_length = getenv("CONTENT_LENGTH")) != NULL) {
if (atoi(content_length) > 0) {
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0) ;
}
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1));
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len;
*environ++;
}
}
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res) ;
}
}
return 0;
message[0] = 0;
len = (mptr-message)-4;
memcpy(message+1, &len, 2);
message[3] = 0;
res = send(uwsgi_socket, message, mptr-message, 0);
if ( (content_length = getenv("CONTENT_LENGTH")) != NULL) {
if (atoi(content_length) > 0) {
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0);
}
}
}
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res);
}
}
return 0;
}
+64 -64
View File
@@ -2,8 +2,8 @@
*** uWSGI cgi client ***
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_dynamic_client.c
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_dynamic_client.c
*/
@@ -19,77 +19,77 @@ to compile:
#define UWSGI_SCRIPT "myapp_wsgi"
int main() {
extern char **environ;
char *env ;
struct sockaddr_un s_addr ;
int uwsgi_socket ;
int res, cnt;
char *place_holder;
unsigned short len ;
char message[4096];
char *mptr;
extern char **environ;
char *env;
struct sockaddr_un s_addr;
int uwsgi_socket;
int res, cnt;
char *place_holder;
memset(&s_addr, 0, sizeof(struct sockaddr_un)) ;
unsigned short len;
char message[4096];
char *mptr;
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
memset(&s_addr, 0, sizeof(struct sockaddr_un));
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
memset(message, 0, 4096);
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
mptr = message+4;
if (setenv("UWSGI_SCRIPT", UWSGI_SCRIPT, 1) != 0) {
perror("setenv()");
exit(1);
}
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len ;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1)) ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len ;
*environ++;
}
}
memset(message, 0, 4096);
message[0] = 0;
len = (mptr-message)-4 ;
memcpy(message+1, &len, 2) ;
message[3] = 0 ;
mptr = message+4;
if (setenv("UWSGI_SCRIPT", UWSGI_SCRIPT, 1) != 0) {
perror("setenv()");
exit(1);
}
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1));
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len;
*environ++;
}
}
res = send(uwsgi_socket, message, mptr-message, 0);
message[0] = 0;
len = (mptr-message)-4;
memcpy(message+1, &len, 2);
message[3] = 0;
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0) ;
}
res = send(uwsgi_socket, message, mptr-message, 0);
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0);
}
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res);
}
}
return 0;
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res) ;
}
}
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
service uwsgi
{
disable = no
id = uwsgi-000
type = UNLISTED
socket_type = stream
server = /root/uwsgi/uwsgi
server_args = --chdir /root/uwsgi/ --module welcome --logto /tmp/uwsgi.log
port = 3031
bind = 127.0.0.1
user = root
wait = yes
}
+2
View File
@@ -0,0 +1,2 @@
[uwsgi]
show-config = true
+133
View File
@@ -0,0 +1,133 @@
#!./uwsgi --import decoratortest -s :3035 -M --spooler myspool --enable-threads -p 8 --spooler-ordered
import uwsgi
from uwsgidecorators import *
from uwsgicc import app as application
import time
# register rpc function helloworld
@rpc("helloworld")
def hello2():
return "[RPC] Hello World"
# register signal 1
@signal(1)
def what_time_is_it(num):
print(time.asctime())
# register signal 100
@signal(100, target='workers')
def what_time_is_it(num):
print("*** I AM THE WORKER %d AT %s ***" % (uwsgi.worker_id(), time.asctime()))
# a 3 seconds timer
@timer(3)
def salut(num):
print("Salut !!! 3 seconds elapsed and signal %d raised" % num)
# a 10 seconds red black timer (executed by the spooler)
@rbtimer(10, target='spooler')
def tenseconds(num):
print("red black timer !!! 10 seconds elapsed and signal %d raised" % num)
# monitor /tmp directory
@filemon("/tmp")
def tmpmodified(num):
print("/tmp has been modified")
# spool a long running task
@spool
def a_long_task(args):
for i in xrange(1,10):
print("%s = %d" % ( str(args), i))
print(uwsgi.call('helloworld'))
time.sleep(1)
# continuosly spool a long running task
@spoolforever
def an_infinite_task(args):
for i in xrange(1,4):
print("infinite: %d %s" % (i, str(args)))
print(uwsgi.call('helloworld'))
uwsgi.signal(100)
time.sleep(1)
# spool a task after 5 seconds
@spool
def delayed_task(args):
print("*** I am a delayed spool job. It is %s [%s]***" % (time.asctime(), str(args)))
# send a signal to all workers
uwsgi.signal(100)
@spool
def big_body_task(args):
print("*** managing a task with a body of %d bytes ***" % len(args['body']))
print(args['body'].swapcase())
# run a task every hour
@cron(59, -1, -1, -1, -1)
def one_hour_passed(num):
print("received signal %d after 1 hour" % num)
@thread
def a_running_thread():
while True:
time.sleep(2)
print("i am a no-args thread")
@thread
def a_running_thread_with_args(who):
while True:
time.sleep(2)
print("Hello %s (from arged-thread)" % who)
@postfork
@thread
def a_post_fork_thread():
while True:
time.sleep(3)
if uwsgi.i_am_the_spooler():
print("Hello from a thread in the spooler")
else:
print("Hello from a thread in worker %d" % uwsgi.worker_id())
@postfork
def fork_happened():
print("fork() has been called [1]")
@postfork
def fork_happened2():
if uwsgi.i_am_the_spooler():
return
print("worker %d is waiting for signal 100..." % uwsgi.worker_id())
uwsgi.signal_wait(100)
print("worker %d received signal %d" % (uwsgi.worker_id(), uwsgi.signal_received()))
print("fork() has been called [2] wid: %d" % uwsgi.worker_id())
@postfork
@lock
def locked_func():
print("starting locked function on worker %d" % uwsgi.worker_id())
for i in xrange(1, 5):
time.sleep(1)
print("[locked %d] waiting..." % uwsgi.worker_id())
print("done with locked function on worker %d" % uwsgi.worker_id())
print(uwsgi.call('helloworld'))
spool_filename = a_long_task.spool({'foo':'bar'}, hello='world')
print("spool filename = %s" % spool_filename)
an_infinite_task.spool(foo='bar', priority=3)
when = int(time.time())+5
print("scheduling a delayed task at %d" % when)
delayed_task.spool(foo2='bar2', at=when)
a_running_thread()
a_running_thread_with_args("uWSGI")
uwsgi_source_file = open('uwsgi.c','r')
print(big_body_task.spool(priority=9,filename='uwsgi.c',body=uwsgi_source_file.read()))
uwsgi_source_file.close()
+20
View File
@@ -56,6 +56,26 @@
</table>
</div>
<div class="module" style="width:860px">
<table>
<caption style="width:860px">spooler jobs</caption>
<thead>
<tr>
<th scope="row">job filename</th>
<th scope="row">environment</th>
</tr>
</thead>
<tbody>
{% for j in jobs %}
<tr>
<td align="left">{{j.file}}</td>
<td align="left">{{j.env}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if masterpid %}
<br/>
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
+7
View File
@@ -14,12 +14,19 @@ def index(request):
w['load'] = (100 * (w['running_time']/1000))/total_load
w['last_spawn_str'] = time.ctime(w['last_spawn'])
jobs = []
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),
'buffer_size': uwsgi.buffer_size,
'total_requests': uwsgi.total_requests(),
'numproc': uwsgi.numproc,
'workers': workers,
'jobs': jobs,
}, RequestContext(request, {}))
index = staff_member_required(index)
+29
View File
@@ -0,0 +1,29 @@
from django.template.base import TemplateDoesNotExist
from django.template.loader import BaseLoader
from django.conf import settings
try:
import uwsgi
on_uwsgi = True
except:
on_uwsgi = False
class Loader(BaseLoader):
is_usable = on_uwsgi
def symbolize(self, name):
return name.replace('.','_').replace('/','_').replace('-','_')
def load_template_source(self, template_name, template_dirs=None):
filename = 'templates_' + self.symbolize(template_name)
for app in settings.INSTALLED_APPS:
try:
symbol = "%s_%s" % (self.symbolize(app), filename)
return (uwsgi.embedded_data(symbol), "sym://%s" % symbol)
except:
pass
raise TemplateDoesNotExist(template_name)
+898
View File
@@ -0,0 +1,898 @@
#include "uwsgi.h"
#include <glob.h>
extern struct uwsgi_server uwsgi;
extern char **environ;
int emperor_queue;
char *emperor_absolute_dir;
void emperor_send_stats(int);
struct uwsgi_instance {
struct uwsgi_instance *ui_prev;
struct uwsgi_instance *ui_next;
char name[0xff];
pid_t pid;
int status;
time_t born;
time_t last_mod;
time_t last_loyal;
uint64_t respawns;
int use_config;
int pipe[2];
int pipe_config[2];
char *config;
uint32_t config_len;
int loyal;
int zerg;
uid_t uid;
gid_t gid;
};
struct uwsgi_instance *ui;
static void royal_death(int signum) {
if (uwsgi.vassals_stop_hook) {
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
uwsgi_log("running vassal stop-hook: %s %s\n", uwsgi.vassals_stop_hook, c_ui->name);
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
uwsgi_error("setenv()");
}
int stop_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_stop_hook, c_ui->name);
uwsgi_log("%s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
c_ui = c_ui->ui_next;
}
}
uwsgi_notify("The Emperor is buried.");
exit(0);
}
void emperor_stats() {
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
uwsgi_log("vassal instance %s (last modified %d) status %d loyal %d zerg %d\n",c_ui->name, c_ui->last_mod, c_ui->status, c_ui->loyal, c_ui->zerg);
c_ui = c_ui->ui_next;
}
}
struct uwsgi_instance *emperor_get_by_fd(int fd) {
struct uwsgi_instance *c_ui = ui;
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
if (c_ui->pipe[0] == fd) {
return c_ui;
}
}
return NULL;
}
struct uwsgi_instance *emperor_get(char *name) {
struct uwsgi_instance *c_ui = ui;
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
if (!strcmp(c_ui->name, name)) {
return c_ui;
}
}
return NULL;
}
void emperor_del(struct uwsgi_instance *c_ui) {
struct uwsgi_instance *parent_ui = c_ui->ui_prev;
struct uwsgi_instance *child_ui = c_ui->ui_next;
parent_ui->ui_next = child_ui;
if (child_ui) {
child_ui->ui_prev = parent_ui;
}
// this will destroy the whole uWSGI instance (and workers)
close(c_ui->pipe[0]);
if (c_ui->use_config) {
close(c_ui->pipe_config[0]);
}
if (uwsgi.vassals_stop_hook) {
uwsgi_log("running vassal stop-hook: %s %s\n", uwsgi.vassals_stop_hook, c_ui->name);
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
uwsgi_error("setenv()");
}
int stop_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_stop_hook, c_ui->name);
uwsgi_log("%s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
}
uwsgi_log("removed uwsgi instance %s\n", c_ui->name);
if (c_ui->zerg) {
uwsgi.emperor_broodlord_count--;
}
free(c_ui);
}
void emperor_stop(struct uwsgi_instance *c_ui) {
// remove uWSGI instance
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("write()");
}
c_ui->status = 1;
uwsgi_log("stop the uwsgi instance %s\n", c_ui->name);
}
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
// reload the uWSGI instance
if (c_ui->use_config) {
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("write()");
}
}
else {
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
}
}
c_ui->respawns++;
c_ui->last_mod = mod;
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
}
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 **vassal_argv;
char *uef;
char **uenvs;
int counter;
char *colon = NULL;
int i;
usleep(uwsgi.emperor_throttle*1000);
if (uwsgi.emperor_tyrant) {
if (uid == 0 || gid == 0) {
uwsgi_log("[emperor-tyrant] invalid permissions for file %s\n", name);
return;
}
}
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
}
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
memset(n_ui, 0, sizeof(struct uwsgi_instance));
if (config) {
n_ui->use_config = 1;
n_ui->config = config;
n_ui->config_len = config_size;
}
c_ui->ui_next = n_ui;
#ifdef UWSGI_DEBUG
uwsgi_log("c_ui->ui_next = %p\n", c_ui->ui_next);
#endif
n_ui->ui_prev = c_ui;
if (strchr(name,':')) {
n_ui->zerg = 1;
uwsgi.emperor_broodlord_count++;
}
memcpy(n_ui->name, name, strlen(name));
n_ui->born = born;
n_ui->uid = uid;
n_ui->gid = gid;
n_ui->last_mod = born;
// start without loyalty
n_ui->last_loyal = born;
n_ui->loyal = 0;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
uwsgi_error("socketpair()");
goto clear;
}
event_queue_add_fd_read(emperor_queue, n_ui->pipe[0]);
if (n_ui->use_config) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
uwsgi_error("socketpair()");
goto clear;
}
}
// TODO pre-start hook
// a new uWSGI instance will start
pid = fork();
if (pid < 0) {
uwsgi_error("fork()")
}
else if (pid > 0) {
n_ui->pid = pid;
// close the right side of the pipe
close(n_ui->pipe[1]);
if (n_ui->use_config) {
close(n_ui->pipe_config[1]);
}
if (n_ui->use_config) {
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) <= 0) {
uwsgi_error("write()");
}
close(n_ui->pipe_config[0]);
}
return;
}
else {
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
if (setgid(gid)) {
uwsgi_error("setgid()");
exit(1);
}
if (setgroups(0, NULL)) {
uwsgi_error("setgroups()");
exit(1);
}
if (setuid(uid)) {
uwsgi_error("setuid()");
exit(1);
}
}
unsetenv("UWSGI_RELOADS");
unsetenv("NOTIFY_SOCKET");
uef = uwsgi_num2str(n_ui->pipe[1]);
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
}
free(uef);
if (n_ui->use_config) {
uef = uwsgi_num2str(n_ui->pipe_config[1]);
if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
}
free(uef);
}
uenvs = environ;
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
break;
}
free(oe);
uwsgi_log("putenv %s\n", ne);
if (putenv(ne)) {
uwsgi_error("putenv()");
}
// do not free ne as putenv will add it to the environ
uenvs = environ;
continue;
}
uenvs++;
}
// close the left side of the pipe
close(n_ui->pipe[0]);
if (n_ui->use_config) {
close(n_ui->pipe_config[0]);
}
counter = 4;
struct uwsgi_config_template *uct = uwsgi.vassals_templates;
while(uct) {
counter+=2;
uct = uct->next;
}
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
vassal_argv[0] = uwsgi.binary_path;
if (uwsgi.emperor_broodlord) {
colon = strchr(name, ':');
if (colon) {
colon[0] = 0;
}
}
if (!strcmp(name + (strlen(name) - 4), ".xml"))
vassal_argv[1] = "--xml";
if (!strcmp(name + (strlen(name) - 4), ".ini"))
vassal_argv[1] = "--ini";
if (!strcmp(name + (strlen(name) - 4), ".yml"))
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 3), ".js"))
vassal_argv[1] = "--json";
if (!strcmp(name + (strlen(name) - 5), ".json"))
vassal_argv[1] = "--json";
if (colon) {
colon[0] = ':';
}
vassal_argv[2] = name;
counter = 3;
uct = uwsgi.vassals_templates;
while(uct) {
vassal_argv[counter] = "--inherit";
vassal_argv[counter+1] = uct->filename;
counter+=2;
uct = uct->next;
}
vassal_argv[counter] = NULL;
// close all of the unneded fd
for(i=3;i<sysconf(_SC_OPEN_MAX);i++) {
if (i != n_ui->pipe[1]) {
close(i);
}
}
if (uwsgi.vassals_start_hook) {
uwsgi_log("running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name);
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
uwsgi_error("setenv()");
}
int start_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_start_hook, n_ui->name);
uwsgi_log("%s start-hook returned %d\n", n_ui->name, start_hook_ret);
}
// start !!!
if (execvp(vassal_argv[0], vassal_argv)) {
uwsgi_error("execvp()");
}
uwsgi_log("is the uwsgi binary in your system PATH ?\n");
// never here
exit(UWSGI_EXILE_CODE);
}
clear:
free(n_ui);
c_ui->ui_next = NULL;
}
void emperor_loop() {
// monitor a directory
struct uwsgi_instance ui_base;
struct uwsgi_instance *ui_current;
struct stat st;
pid_t diedpid;
int waitpid_status;
int has_children = 0;
int i_am_alone = 0;
int simple_mode = 0;
glob_t g;
int i;
struct dirent *de;
char *amqp_port;
int amqp_fd = -1;
char *amqp_routing_key;
void *events;
int nevents;
int interesting_fd;
char notification_message[64];
uwsgi.emperor_stats_fd = -1;
signal(SIGPIPE, SIG_IGN);
uwsgi_unix_signal(SIGINT, royal_death);
uwsgi_unix_signal(SIGTERM, royal_death);
uwsgi_unix_signal(SIGQUIT, royal_death);
uwsgi_unix_signal(SIGUSR1, emperor_stats);
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
emperor_queue = event_queue_init();
events = event_queue_alloc(64);
if (uwsgi.has_emperor) {
uwsgi_log("*** starting uWSGI sub-Emperor ***\n");
}
else {
uwsgi_log("*** starting uWSGI Emperor ***\n");
}
if (uwsgi.emperor_stats) {
char *tcp_port = strchr(uwsgi.emperor_stats, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
uwsgi.emperor_stats_fd = bind_to_tcp(uwsgi.emperor_stats, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
uwsgi.emperor_stats_fd = bind_to_unix(uwsgi.emperor_stats, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
event_queue_add_fd_read(emperor_queue, uwsgi.emperor_stats_fd);
uwsgi_log("*** Emperor stats server enabled on %s fd: %d ***\n", uwsgi.emperor_stats, uwsgi.emperor_stats_fd);
}
amqp_port = strchr(uwsgi.emperor_dir, ':');
if (amqp_port) {
if (uwsgi.emperor_amqp_vhost == NULL) uwsgi.emperor_amqp_vhost = "/";
if (uwsgi.emperor_amqp_username == NULL) uwsgi.emperor_amqp_username = "guest";
if (uwsgi.emperor_amqp_password == NULL) uwsgi.emperor_amqp_password = "guest";
reconnect:
while(amqp_fd == -1) {
uwsgi_log("connecting to AMQP server...\n");
amqp_fd = uwsgi_connect(uwsgi.emperor_dir, -1, 0);
if (amqp_fd < 0) {
sleep(1);
}
}
uwsgi_log("subscribing to queue...\n");
if (uwsgi_amqp_consume_queue(amqp_fd, uwsgi.emperor_amqp_vhost, uwsgi.emperor_amqp_username, uwsgi.emperor_amqp_password, "", "uwsgi.emperor", "fanout") < 0) {
close(amqp_fd);
amqp_fd = -1;
sleep(1);
goto reconnect;
}
event_queue_add_fd_read(emperor_queue, amqp_fd);
}
else {
if (!glob(uwsgi.emperor_dir, GLOB_MARK|GLOB_NOCHECK, NULL, &g)) {
if (g.gl_pathc == 1 && g.gl_pathv[0][strlen(g.gl_pathv[0]) - 1] == '/') {
simple_mode = 1;
if (chdir(uwsgi.emperor_dir)) {
uwsgi_error("chdir()");
exit(1);
}
}
}
else {
uwsgi_error("glob()");
exit(1);
}
globfree(&g);
emperor_absolute_dir = realpath(".", NULL);
}
ui = &ui_base;
int freq = 0 ;
for (;;) {
if (!i_am_alone) {
diedpid = waitpid(uwsgi.emperor_pid, &waitpid_status, WNOHANG);
if (diedpid < 0 || diedpid > 0) {
i_am_alone = 1;
}
}
nevents = event_queue_wait_multi(emperor_queue, freq, events, 64);
freq = 3;
for (i = 0; i<nevents;i++) {
interesting_fd = event_queue_interesting_fd(events, i);
if (amqp_fd > -1 && interesting_fd == amqp_fd ) {
uint64_t msgsize;
char *config = uwsgi_amqp_consume(amqp_fd, &msgsize, &amqp_routing_key);
if (!config) {
uwsgi_log("problem with RabbitMQ server, trying reconnection...\n");
event_queue_del_fd(emperor_queue, amqp_fd, event_queue_read());
close(amqp_fd);
amqp_fd = -1;
goto reconnect;
}
if (amqp_routing_key) {
uwsgi_log("AMQP routing_key = %s\n", amqp_routing_key);
char *config_file = uwsgi_concat2("emperor://", amqp_routing_key);
free(amqp_routing_key);
ui_current = emperor_get(config_file);
if (ui_current) {
// ignore event if i am not loyal
if (!ui_current->loyal) continue;
free(ui_current->config);
ui_current->config = config;
ui_current->config_len = msgsize;
if (!msgsize) {
// SAFE
emperor_del(ui_current);
}
else {
emperor_respawn(ui_current, time(NULL));
}
}
else {
if (msgsize > 0) {
emperor_add(config_file, time(NULL), config, msgsize, 0, 0);
}
}
free(config_file);
}
else {
if (msgsize) {
if (msgsize >= 0xff) { free(config); continue; }
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s\n", (int)msgsize, config);
#endif
char *config_file = uwsgi_concat2n(config, msgsize, "", 0);
free(config);
if (strncmp(config_file, "http://", 7)) {
if (stat(config_file, &st)) {
free(config_file);
continue;
}
if (!S_ISREG(st.st_mode)) {
free(config_file);
continue;
}
}
ui_current = emperor_get(config_file);
if (ui_current) {
// ignore event if i am not loyal
if (!ui_current->loyal) continue;
emperor_respawn(ui_current, time(NULL));
}
else {
emperor_add(config_file, time(NULL), NULL, 0, 0, 0);
}
free(config_file);
}
}
}
else if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1) {
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) {
char byte;
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
emperor_del(ui_current);
}
else {
if (byte == 17) {
ui_current->loyal = 1;
uwsgi_log("*** vassal %s is now loyal ***\n", ui_current->name);
// TODO post-start hook
}
else if (byte == 22) {
emperor_stop(ui_current);
}
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
char *zerg_name = uwsgi_concat3(ui_current->name,":","zerg");
emperor_add(zerg_name, time(NULL), NULL, 0, ui_current->uid, ui_current->gid);
free(zerg_name);
}
}
}
else {
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
event_queue_del_fd(emperor_queue, interesting_fd, event_queue_read());
close(interesting_fd);
}
}
}
if (amqp_fd == -1) {
if (simple_mode) {
DIR *dir = opendir(".");
while ((de = readdir(dir)) != NULL) {
if (!strcmp(de->d_name + (strlen(de->d_name) - 4), ".xml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".ini") ||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".yml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".yaml") ||
!strcmp(de->d_name + (strlen(de->d_name) - 3), ".js") ||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".json")
) {
if (strlen(de->d_name) >= 0xff)
continue;
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
ui_current = emperor_get(de->d_name);
if (ui_current) {
// check if uid or gid are changed, in such case, sotp the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
emperor_stop(ui_current);
continue;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
}
closedir(dir);
}
else {
if (glob(uwsgi.emperor_dir, GLOB_MARK|GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("glob()");
continue;
}
for (i = 0; i < (int) g.gl_pathc; i++) {
if (!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".xml") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".ini") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".yml") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 3), ".js") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".json") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".yaml")
) {
if (strlen(g.gl_pathv[i]) >= 0xff)
continue;
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
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, st.st_uid, st.st_gid);
}
}
}
globfree(&g);
}
}
// check for removed instances
ui_current = ui;
has_children = 0;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
has_children++;
}
if (uwsgi.notify) {
if (snprintf(notification_message, 64, "The Emperor is governing %d vassals", has_children) >= 34) {
uwsgi_notify(notification_message);
}
}
if (has_children) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
else {
// vacuum
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
diedpid = 0;
}
if (diedpid < 0) {
uwsgi_error("waitpid()");
}
ui_current = ui;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
// check loyalty if not in simple/glob mode
if (amqp_fd > -1) {
if (!ui_current->loyal && (time(NULL)-ui_current->last_loyal) > 60) {
uwsgi_log("!!! no loyalty showed by instance %s !!!\n", ui_current->name);
// SAFE
emperor_del(ui_current);
break;
}
}
if (ui_current->status == 1) {
if (ui_current->config) free(ui_current->config);
// SAFE
emperor_del(ui_current);
break;
}
else if (!ui_current->use_config && strncmp(ui_current->name, "http://",7) && stat(ui_current->name, &st) && !ui_current->zerg) {
emperor_stop(ui_current);
}
else if (ui_current->pid == diedpid) {
if (ui_current->status == 0) {
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
// SAFE
emperor_del(ui_current);
}
else {
// UNSAFE
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
emperor_del(ui_current);
}
break;
}
else if (ui_current->status == 1) {
// remove 'marked for dead' instance
if (ui_current->config) free(ui_current->config);
// SAFE
emperor_del(ui_current);
break;
}
}
}
}
}
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
void emperor_send_stats(int fd) {
struct sockaddr_un client_src;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
stats_send("\"emperor\": \"%s\",\n", uwsgi.emperor_dir);
fprintf(output,"\"emperor_tyrant\": %d,\n", uwsgi.emperor_tyrant);
fprintf(output, "\"vassals\": [\n");
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
fprintf(output,"\t{");
stats_send("\"id\": \"%s\", ", c_ui->name);
fprintf(output,"\"pid\": %d, ", (int) c_ui->pid);
stats_send_llu( "\"born\": %llu, ", c_ui->born);
stats_send_llu( "\"last_mod\": %llu, ", c_ui->last_mod);
fprintf(output,"\"loyal\": %d, ", c_ui->loyal);
fprintf(output,"\"zerg\": %d, ", c_ui->zerg);
fprintf(output,"\"uid\": %d, ", (int)c_ui->uid);
fprintf(output,"\"gid\": %d, ", (int)c_ui->gid);
stats_send_llu( "\"respawns\": %llu ", c_ui->respawns);
c_ui = c_ui->ui_next;
if (c_ui) {
fprintf(output,"},\n");
}
else {
fprintf(output,"}\n");
}
}
fprintf(output,"]}\n");
fclose(output);
}
-702
View File
@@ -1,702 +0,0 @@
#ifdef UWSGI_ERLANG
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static void erlang_log(void);
PyObject *py_erlang_connect(PyObject * self, PyObject * args) {
char *erlang_node;
int fd;
if (!PyArg_ParseTuple(args, "s:erlang_connect", &erlang_node)) {
return NULL;
}
UWSGI_SET_BLOCKING;
fd = erl_connect(erlang_node);
UWSGI_UNSET_BLOCKING;
return PyInt_FromLong(fd);
}
PyObject *py_erlang_recv_message(PyObject * self, PyObject * args) {
int erfd;
struct pollfd erpoll;
ErlMessage emsg;
PyObject *pyer = NULL;
unsigned char erlang_buffer[8192];
int eret;
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
if (!PyArg_ParseTuple(args, "i|i:erlang_recv_message", &erfd, &timeout)) {
return NULL;
}
if (erfd < 0) {
goto clear;
}
erpoll.fd = erfd;
erpoll.events = POLLIN;
cycle:
memset(&emsg, 0, sizeof(ErlMessage));
UWSGI_SET_BLOCKING;
if (timeout > 0) {
eret = poll(&erpoll, 1, timeout * 1000);
if (eret < 0) {
uwsgi_error("poll()");
goto clear;
}
else if (eret == 0) {
goto clear;
}
}
if (erl_receive_msg(erfd, erlang_buffer, 8192, &emsg) == ERL_MSG) {
if (emsg.type == ERL_TICK) {
goto cycle;
}
if (emsg.msg) {
pyer = eterm_to_py(emsg.msg);
}
if (emsg.msg) {
erl_free_compound(emsg.msg);
}
if (emsg.to) {
erl_free_compound(emsg.to);
}
if (emsg.from) {
erl_free_compound(emsg.from);
}
if (!pyer) {
goto clear;
}
UWSGI_UNSET_BLOCKING;
return pyer;
}
clear:
UWSGI_UNSET_BLOCKING;
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_send_message(PyObject * self, PyObject * args) {
ETERM *pymessage;
ETERM *pid;
int erfd;
PyObject *ermessage, *erdest, *zero;
int er_number, er_serial, er_creation;
char *er_node;
if (!PyArg_ParseTuple(args, "iOO|i:erlang_send_message", &erfd, &erdest, &ermessage)) {
return NULL;
}
if (erfd < 0) {
goto clear;
}
if (!PyString_Check(erdest) && !PyDict_Check(erdest)) {
goto clear;
}
pymessage = py_to_eterm(ermessage);
if (!pymessage) {
goto clear;
}
if (PyString_Check(erdest)) {
if (!erl_reg_send(erfd, PyString_AsString(erdest), pymessage)) {
erl_err_msg("erl_reg_send()");
goto clear2;
}
}
else if (PyDict_Check(erdest)) {
zero = PyDict_GetItemString(erdest, "node");
if (!zero) {
goto clear2;
}
if (!PyString_Check(zero)) {
goto clear2;
}
er_node = PyString_AsString(zero);
zero = PyDict_GetItemString(erdest, "number");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_number = PyInt_AsLong(zero);
zero = PyDict_GetItemString(erdest, "serial");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_serial = PyInt_AsLong(zero);
zero = PyDict_GetItemString(erdest, "creation");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_creation = PyInt_AsLong(zero);
pid = erl_mk_pid((const char *) er_node, er_number, er_serial, er_creation);
if (!pid) {
goto clear2;
}
if (!erl_send(erfd, pid, pymessage)) {
erl_err_msg("erl_send()");
erl_free_term(pid);
goto clear2;
}
erl_free_term(pid);
}
else {
goto clear;
}
erl_free_compound(pymessage);
Py_INCREF(Py_True);
return Py_True;
clear2:
erl_free_compound(pymessage);
clear:
PyErr_Print();
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_rpc(PyObject * self, PyObject * args) {
int fd, timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
char *emod, *efun;
PyObject *eargs, *pyer = NULL;
ETERM *pyargs, *rex;
ErlMessage emsg;
int eret;
if (!PyArg_ParseTuple(args, "issO|i:erlang_rpc", &fd, &emod, &efun, &eargs, &timeout)) {
return NULL;
}
if (fd < 0) {
goto clear;
}
pyargs = py_to_eterm(eargs);
if (!pyargs) {
goto clear;
}
if (erl_rpc_to(fd, emod, efun, pyargs)) {
erl_err_msg("erl_rpc_to()");
goto clear2;
}
cycle:
memset(&emsg, 0, sizeof(ErlMessage));
UWSGI_SET_BLOCKING;
eret = erl_rpc_from(fd, timeout * 1000, &emsg);
if (eret == ERL_TICK) {
goto cycle;
}
else if (eret == ERL_MSG) {
if (emsg.msg) {
if (ERL_IS_TUPLE(emsg.msg)) {
rex = erl_element(1, emsg.msg);
if (!rex) {
goto clear2;
}
if (!strncmp("rex", ERL_ATOM_PTR(rex), ERL_ATOM_SIZE(rex))) {
erl_free_term(rex);
rex = erl_element(2, emsg.msg);
if (!rex) {
goto clear2;
}
pyer = eterm_to_py(rex);
erl_free_term(rex);
}
else {
erl_free_term(rex);
}
}
}
if (emsg.msg) {
erl_free_compound(emsg.msg);
}
if (emsg.to) {
erl_free_compound(emsg.to);
}
if (emsg.from) {
erl_free_compound(emsg.from);
}
if (!pyer) {
goto clear2;
}
erl_free_compound(pyargs);
UWSGI_UNSET_BLOCKING;
return pyer;
}
else {
erl_err_msg("erl_rpc_from()");
}
clear2:
UWSGI_UNSET_BLOCKING;
erl_free_compound(pyargs);
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_close(PyObject * self, PyObject * args) {
int fd;
if (!PyArg_ParseTuple(args, "i:erlang_close", &fd)) {
return NULL;
}
if (fd >= 0) {
erl_close_connection(fd);
}
Py_INCREF(Py_True);
return Py_True;
}
static PyMethodDef uwsgi_erlang_methods[] = {
{"erlang_connect", py_erlang_connect, METH_VARARGS, ""},
{"erlang_send_message", py_erlang_send_message, METH_VARARGS, ""},
{"erlang_recv_message", py_erlang_recv_message, METH_VARARGS, ""},
{"erlang_rpc", py_erlang_rpc, METH_VARARGS, ""},
{"erlang_close", py_erlang_close, METH_VARARGS, ""},
{NULL, NULL},
};
int init_erlang(char *nodename, char *cookie) {
struct sockaddr_in e_addr;
char *ip;
char *node;
int efd;
int rlen;
char *cookiefile;
char *cookiehome;
char cookievalue[128];
int cookiefd;
PyMethodDef *uwsgi_function;
ip = strchr(nodename, '@');
if (ip == NULL) {
uwsgi_log( "*** invalid erlang node name ***\n");
return -1;
}
if (cookie == NULL) {
// get the cookie from the home
cookiehome = getenv("HOME");
if (!cookiehome) {
uwsgi_log( "unable to get erlang cookie from your home.\n");
return -1;
}
cookiefile = malloc(strlen(cookiehome) + 1 + strlen(".erlang.cookie") + 1);
if (!cookiefile) {
uwsgi_error("malloc()");
}
cookiefile[0] = 0;
strcat(cookiefile, cookiehome);
strcat(cookiefile, "/.erlang.cookie");
cookiefd = open(cookiefile, O_RDONLY);
if (cookiefd < 0) {
uwsgi_error("open()");
free(cookiefile);
return -1;
}
memset(cookievalue, 0, 128);
if (read(cookiefd, cookievalue, 127) < 1) {
uwsgi_log( "invalid cookie found in %s\n", cookiefile);
close(cookiefd);
free(cookiefile);
return -1;
}
cookie = cookievalue;
close(cookiefd);
free(cookiefile);
}
node = malloc((ip - nodename) + 1);
if (node == NULL) {
uwsgi_error("malloc()");
return -1;
}
memset(node, 0, (ip - nodename) + 1);
memcpy(node, nodename, ip - nodename);
erl_init(NULL, 0);
if (erl_connect_xinit(ip + 1, node, nodename, NULL, cookie, 0) == -1) {
uwsgi_log( "*** unable to initialize erlang c-node ***\n");
return -1;
}
efd = socket(AF_INET, SOCK_STREAM, 0);
if (efd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&e_addr, 0, sizeof(struct sockaddr_in));
e_addr.sin_family = AF_INET;
e_addr.sin_addr.s_addr = inet_addr(ip + 1);
rlen = 1;
if (setsockopt(efd, SOL_SOCKET, SO_REUSEADDR, &rlen, sizeof(rlen))) {
uwsgi_error("setsockopt()");
close(efd);
return -1;
}
if (bind(efd, (struct sockaddr *) &e_addr, sizeof(struct sockaddr_in)) < 0) {
uwsgi_error("bind()");
close(efd);
return -1;
}
rlen = sizeof(struct sockaddr_in);
if (getsockname(efd, (struct sockaddr *) &e_addr, (socklen_t *) & rlen)) {
uwsgi_error("getsockname()");
close(efd);
return -1;
}
if (listen(efd, uwsgi.listen_queue)) {
uwsgi_error("listen()");
close(efd);
return -1;
}
if (erl_publish(ntohs(e_addr.sin_port)) < 0) {
uwsgi_log( "*** unable to subscribe with EPMD ***\n");
close(efd);
return -1;
}
uwsgi_log( "Erlang C-Node initialized on port %d you can access it with name %s\n", ntohs(e_addr.sin_port), nodename);
for (uwsgi_function = uwsgi_erlang_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(uwsgi.embedded_dict, uwsgi_function->ml_name, func);
Py_DECREF(func);
}
return efd;
}
ETERM *py_to_eterm(PyObject * pobj) {
int i;
int count;
PyObject *pobj2;
ETERM *eobj = NULL;
ETERM *eobj2 = NULL;
ETERM **eobj3;
if (pobj == NULL) {
return erl_mk_empty_list();
}
if (PyString_Check(pobj)) {
eobj = erl_mk_atom(PyString_AsString(pobj));
}
else if (PyInt_Check(pobj)) {
eobj = erl_mk_int(PyInt_AsLong(pobj));
}
else if (PyList_Check(pobj)) {
eobj = erl_mk_empty_list();
for (i = PyList_Size(pobj) - 1; i >= 0; i--) {
pobj2 = PyList_GetItem(pobj, i);
eobj2 = py_to_eterm(pobj2);
eobj = erl_cons(eobj2, eobj);
}
}
else if (PyDict_Check(pobj)) {
// a pid
char *er_node;
int er_number, er_serial, er_creation;
pobj2 = PyDict_GetItemString(pobj, "node");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyString_Check(pobj2)) {
goto clear;
}
er_node = PyString_AsString(pobj2);
pobj2 = PyDict_GetItemString(pobj, "number");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_number = PyInt_AsLong(pobj2);
pobj2 = PyDict_GetItemString(pobj, "serial");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_serial = PyInt_AsLong(pobj2);
pobj2 = PyDict_GetItemString(pobj, "creation");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_creation = PyInt_AsLong(pobj2);
eobj = erl_mk_pid(er_node, er_number, er_serial, er_creation);
}
else if (PyTuple_Check(pobj)) {
count = PyTuple_Size(pobj);
eobj3 = malloc(sizeof(ETERM *) * count);
for (i = 0; i < count; i++) {
pobj2 = PyTuple_GetItem(pobj, i);
if (!pobj2) {
break;
}
eobj3[i] = py_to_eterm(pobj2);
}
eobj = erl_mk_tuple(eobj3, count);
free(eobj3);
}
else {
uwsgi_log( "UNMANAGED PYTHON TYPE: %s\n", pobj->ob_type->tp_name);
}
clear:
if (eobj == NULL) {
return erl_mk_empty_list();
}
return eobj;
}
PyObject *eterm_to_py(ETERM * obj) {
int i;
int count;
ETERM *obj2;
PyObject *eobj = NULL;
if (obj == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
switch (ERL_TYPE(obj)) {
case ERL_CONS:
case ERL_NIL:
count = erl_length(obj);
eobj = PyList_New(0);
for (i = 0; i < count; i++) {
obj2 = erl_hd(obj);
PyList_Append(eobj, eterm_to_py(obj2));
obj = erl_tl(obj);
}
break;
case ERL_TUPLE:
eobj = PyTuple_New(erl_size(obj));
for (i = 1; i <= erl_size(obj); i++) {
obj2 = erl_element(i, obj);
PyTuple_SetItem(eobj, i - 1, eterm_to_py(obj2));
}
break;
case ERL_ATOM:
eobj = PyString_FromStringAndSize(ERL_ATOM_PTR(obj), ERL_ATOM_SIZE(obj));
break;
case ERL_INTEGER:
eobj = PyInt_FromLong(ERL_INT_VALUE(obj));
break;
case ERL_BINARY:
uwsgi_log( "FOUND A BINARY %.*s\n", ERL_BIN_SIZE(obj), ERL_BIN_PTR(obj));
break;
case ERL_PID:
eobj = PyDict_New();
if (PyDict_SetItemString(eobj, "node", PyString_FromString(ERL_PID_NODE(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "number", PyInt_FromLong(ERL_PID_NUMBER(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "serial", PyInt_FromLong(ERL_PID_SERIAL(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "creation", PyInt_FromLong(ERL_PID_CREATION(obj)))) {
PyErr_Print();
break;
}
default:
uwsgi_log( "UNMANAGED ETERM TYPE: %d\n", ERL_TYPE(obj));
break;
}
if (eobj == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return eobj;
}
void erlang_loop(struct wsgi_request *wsgi_req) {
ErlConnect econn;
ErlMessage em;
ETERM *eresponse;
PyObject *callable = PyDict_GetItemString(uwsgi.embedded_dict, "erlang_func");
if (!callable) {
PyErr_Print();
uwsgi_log( "- you have not defined a uwsgi.erlang_func callable, Erlang message manager will be disabled until you define it -\n");
}
PyObject *pargs = PyTuple_New(1);
if (!pargs) {
PyErr_Print();
uwsgi_log( "- error preparing arg tuple for uwsgi.erlang_func callable, Erlang message manager will be disabled -\n");
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
UWSGI_CLEAR_STATUS;
wsgi_req->poll.fd = erl_accept(uwsgi.erlangfd, &econn);
if (wsgi_req->poll.fd >= 0) {
UWSGI_SET_ERLANGING;
for (;;) {
if (erl_receive_msg(wsgi_req->poll.fd, (unsigned char *) wsgi_req->buffer, uwsgi.buffer_size, &em) == ERL_MSG) {
if (em.type == ERL_TICK)
continue;
if (!callable) {
callable = PyDict_GetItemString(uwsgi.embedded_dict, "erlang_func");
}
if (!callable) {
uwsgi_log( "- you still have not defined a uwsgi.erlang_func callable, Erlang message rejected -\n");
}
PyObject *zero = eterm_to_py(em.msg);
if (em.msg) {
erl_free_compound(em.msg);
}
if (em.to) {
erl_free_compound(em.to);
}
if (!zero) {
PyErr_Print();
continue;
}
if (PyTuple_SetItem(pargs, 0, zero)) {
PyErr_Print();
continue;
}
PyObject *erlang_result = PyEval_CallObject(callable, pargs);
//Py_DECREF(zero);
if (erlang_result) {
eresponse = py_to_eterm(erlang_result);
if (eresponse) {
erl_send(wsgi_req->poll.fd, em.from, eresponse);
erl_free_compound(eresponse);
}
Py_DECREF(erlang_result);
}
if (em.from) {
erl_free_compound(em.from);
}
uwsgi.workers[0].requests++;
uwsgi.workers[uwsgi.mywid].requests++;
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
erlang_log();
}
else {
break;
}
}
erl_close_connection(wsgi_req->poll.fd);
UWSGI_UNSET_ERLANGING;
}
}
}
static void erlang_log() {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
get_memusage();
}
else {
uwsgi.workers[uwsgi.mywid].rss_size = 0;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
}
uwsgi_log( "[Erlang worker %d pid %d] request %llu done {rss: %llu vsz: %llu}\n", uwsgi.mywid, uwsgi.mypid, uwsgi.workers[uwsgi.mywid].requests, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].vsz_size);
}
#else
#warning "*** Erlang support is disabled ***"
#endif
+880
View File
@@ -0,0 +1,880 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_USE_PORT
#include <port.h>
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int event_queue_init() {
int port = port_create();
if (port < 0) {
uwsgi_error("port_create()");
return -1;
}
return port;
}
int event_queue_del_fd(int eq, int fd, int event) {
if (port_dissociate(eq, PORT_SOURCE_FD, fd)) {
uwsgi_error("port_disassociate");
return -1;
}
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
if (pe[id].portev_events == POLLHUP || pe[id].portev_events == POLLERR) {
return 1;
}
return 0;
}
int event_queue_add_fd_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(port_event_t) * 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 (long) pe[id].portev_user;
}
return (int) pe[id].portev_object;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
uint_t nget = 1;
timespec_t ts;
port_event_t *pe;
if (timeout >= 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_getn(eq, events, nevents, &nget, &ts);
}
else {
ret = port_getn(eq, events, nevents, &nget, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
uwsgi_error("port_getn()");
return -1;
}
return 0;
}
pe = (port_event_t *) events;
return nget;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
port_event_t pe;
timespec_t ts;
if (timeout > 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_get(eq, &pe, &ts);
}
else {
ret = port_get(eq, &pe, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
uwsgi_error("port_get()");
return -1;
}
return 0;
}
if (pe.portev_source == PORT_SOURCE_FD) {
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
uwsgi_error("port_associate");
}
}
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
*interesting_fd = (long) pe.portev_user;
}
else {
*interesting_fd = (int) pe.portev_object;
}
return 1;
}
#endif
#ifdef UWSGI_EVENT_USE_EPOLL
#include <sys/epoll.h>
#define UWSGI_EVENT_IN EPOLLIN
#define UWSGI_EVENT_OUT EPOLLOUT
int event_queue_init() {
int epfd;
epfd = epoll_create(256);
if (epfd < 0) {
uwsgi_error("epoll_create()");
return -1;
}
return epfd;
}
int event_queue_add_fd_read(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_MOD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.data.fd = fd;
ee.events = event;
if (epoll_ctl(eq, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLOUT;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(struct epoll_event) * nevents);
}
int event_queue_interesting_fd(void *events, int id) {
struct epoll_event *ee = (struct epoll_event *) events;
return ee[id].data.fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct epoll_event *ee = (struct epoll_event *) events;
if (ee[id].events == EPOLLHUP || ee[id].events == EPOLLERR || (ee[id].events == (EPOLLERR|EPOLLHUP))) {
return 1;
}
return 0;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
if (timeout > 0) {
timeout = timeout*1000;
}
ret = epoll_wait(eq, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
if (errno != EINTR)
uwsgi_error("epoll_wait()");
}
return ret;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
struct epoll_event ee;
if (timeout > 0) {
timeout = timeout*1000;
}
ret = epoll_wait(eq, &ee, 1, timeout);
if (ret < 0) {
if (errno != EINTR)
uwsgi_error("epoll_wait()");
}
if (ret > 0) {
*interesting_fd = ee.data.fd;
}
return ret;
}
#endif
#ifdef UWSGI_EVENT_USE_KQUEUE
#define UWSGI_EVENT_IN EVFILT_READ
#define UWSGI_EVENT_OUT EVFILT_WRITE
int event_queue_init() {
int kfd = kqueue();
if (kfd < 0) {
uwsgi_error("kqueue()");
return -1;
}
return kfd;
}
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) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct kevent kev;
EV_SET(&kev, fd, event, EV_DELETE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_add_fd_read(int eq, int fd) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(struct kevent) * nevents);
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
struct timespec ts;
if (timeout < 0) {
ret = kevent(eq, NULL, 0, events, nevents, NULL);
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout;
ret = kevent(eq, NULL, 0, (struct kevent *)events, nevents, &ts);
}
if (ret < 0) {
uwsgi_error("kevent()");
}
return ret;
}
int event_queue_interesting_fd(void *events, int id) {
struct kevent *ev = (struct kevent *) events;
return ev[id].ident;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct kevent *ev = (struct kevent *) events;
if ( ( (ev[id].flags == EV_ERROR) || (ev[id].flags == EV_EOF) || (ev[id].flags == (EV_EOF|EV_ERROR))) ) {
return 1;
}
return 0;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
struct timespec ts;
struct kevent ev;
if (timeout <= 0) {
ret = kevent(eq, NULL, 0, &ev, 1, NULL);
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout;
ret = kevent(eq, NULL, 0, &ev, 1, &ts);
}
if (ret < 0) {
uwsgi_error("kevent()");
}
if (ret > 0) {
*interesting_fd = ev.ident;
}
return ret;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_NONE
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;}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct file_obj fo;
struct stat st;
static int fmon_id = 0xffffee00;
if (stat(filename, &st)) {
uwsgi_error("stat()");
return -1;
}
fo.fo_name = filename;
fo.fo_atime = st.st_atim;
fo.fo_mtime = st.st_mtim;
fo.fo_ctime = st.st_ctim;
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;
}
*id = fmon_id;
uwsgi_log("added new file to monitor %s [%d]\n", filename, *id);
return *id;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
int i;
struct file_obj fo;
struct stat st;
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id) {
if (stat(ushared->files_monitored[i].filename, &st)) {
uwsgi_error("stat()");
return NULL;
}
fo.fo_name = ushared->files_monitored[i].filename;
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 *)(long)id)) {
uwsgi_error("port_associate()");
return NULL;
}
return &ushared->files_monitored[i];
}
}
}
return NULL;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct kevent kev;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(filename);
return -1;
}
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE|NOTE_DELETE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_RENAME|NOTE_REVOKE, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
*id = fd;
uwsgi_log("added new file to monitor %s\n", filename);
return fd;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
int i;
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id) {
return &ushared->files_monitored[i];
}
}
}
return NULL;
}
#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) {
int ifd = -1;
int i;
int add_to_queue = 0;
for (i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
ifd = ushared->files_monitored[0].fd;
break;
}
}
if (ifd == -1) {
ifd = inotify_init();
if (ifd < 0) {
uwsgi_error("inotify_init()");
return -1;
}
add_to_queue = 1;
}
*id = inotify_add_watch(ifd, filename, IN_ATTRIB|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MODIFY|IN_MOVE_SELF|IN_MOVED_FROM|IN_MOVED_TO);
#ifdef UWSGI_DEBUG
uwsgi_log("added watch %d for filename %s\n", *id, filename);
#endif
if (add_to_queue) {
return event_queue_add_fd_read(eq, ifd);
}
else {
return ifd;
}
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
ssize_t rlen = 0;
struct inotify_event ie, *bie, *iie;
int i,j;
int items = 0;
unsigned int isize = sizeof(struct inotify_event);
struct uwsgi_fmon *uf = NULL;
if (ioctl(id, FIONREAD, &isize) < 0) {
uwsgi_error("ioctl()");
return NULL;
}
if (isize > sizeof(struct inotify_event)) {
bie = uwsgi_malloc(isize);
rlen = read(id, bie, isize);
}
else {
rlen = read(id, &ie, sizeof(struct inotify_event));
bie = &ie;
}
if (rlen < 0) {
uwsgi_error("read()");
}
else {
items = isize/(sizeof(struct inotify_event));
#ifdef UWSGI_DEBUG
uwsgi_log("inotify returned %d items\n", items);
#endif
for(j=0;j<items;j++) {
iie = &bie[j];
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id && ushared->files_monitored[i].id == iie->wd) {
uf = &ushared->files_monitored[i];
}
}
}
}
if (items > 1) {
free(bie);
}
return uf;
}
return NULL;
}
#endif
#endif
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
#ifndef UWSGI_EVENT_TIMER_USE_TIMERFD_NOINC
#include <sys/timerfd.h>
#endif
#ifndef TFD_CLOEXEC
// timerfd support
enum
{
TFD_CLOEXEC = 02000000,
#define TFD_CLOEXEC TFD_CLOEXEC
TFD_NONBLOCK = 04000
#define TFD_NONBLOCK TFD_NONBLOCK
};
/* Bits to be set in the FLAGS parameter of `timerfd_settime'. */
enum
{
TFD_TIMER_ABSTIME = 1 << 0
#define TFD_TIMER_ABSTIME TFD_TIMER_ABSTIME
};
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
int event_queue_add_timer(int eq, int *id, int sec) {
struct itimerspec it;
int tfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
if (tfd < 0) {
uwsgi_error("timerfd_create()");
return -1;
}
it.it_value.tv_sec = sec;
it.it_value.tv_nsec = 0;
it.it_interval.tv_sec = sec;
it.it_interval.tv_nsec = 0;
if (timerfd_settime(tfd, 0, &it, NULL)) {
uwsgi_error("timerfd_settime()");
close(tfd);
return -1;
}
*id = tfd;
return event_queue_add_fd_read(eq, tfd);
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
ssize_t rlen;
uint64_t counter;
struct uwsgi_timer *ut = NULL;
for(i=0;i<ushared->timers_cnt;i++) {
if (ushared->timers[i].registered) {
if (ushared->timers[i].id == id) {
ut = &ushared->timers[i];
}
}
}
rlen = read(id, &counter, sizeof(uint64_t));
if (rlen < 0) {
uwsgi_error("read()");
}
return ut;
}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_NONE
int event_queue_add_timer(int eq, int *id, int sec) { return -1; }
struct uwsgi_timer *event_queue_ack_timer(int id) { return NULL;}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_PORT
int event_queue_add_timer(int eq, int *id, int sec) {
static int timer_id = 0xffffff00;
port_notify_t pnotif;
struct sigevent sigev;
itimerspec_t it;
timer_t tid;
timer_id++;
pnotif.portnfy_port = eq;
pnotif.portnfy_user = (void *) (long) timer_id;
sigev.sigev_notify = SIGEV_PORT;
sigev.sigev_value.sival_ptr = &pnotif;
if (timer_create(CLOCK_REALTIME, &sigev, &tid) < 0) {
uwsgi_error("timer_create()");
return -1;
}
it.it_value.tv_sec = sec;
it.it_value.tv_nsec = 0;
it.it_interval.tv_sec = sec;
it.it_interval.tv_nsec = 0;
if (timer_settime(tid, 0, &it, NULL) < 0) {
uwsgi_error("timer_settime()");
return -1;
}
*id = timer_id;
return *id;
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
struct uwsgi_timer *ut = NULL;
for(i=0;i<uwsgi.shared->timers_cnt;i++) {
if (uwsgi.shared->timers[i].registered) {
if (uwsgi.shared->timers[i].id == id) {
ut = &uwsgi.shared->timers[i];
}
}
}
return ut;
}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_KQUEUE
int event_queue_add_timer(int eq, int *id, int sec) {
static int timer_id = 0xffffff00;
struct kevent kev;
*id = timer_id ;
timer_id++;
EV_SET(&kev, *id, EVFILT_TIMER, EV_ADD, 0, sec*1000, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return *id;
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
struct uwsgi_timer *ut = NULL;
for(i=0;i<uwsgi.shared->timers_cnt;i++) {
if (uwsgi.shared->timers[i].registered) {
if (uwsgi.shared->timers[i].id == id) {
ut = &uwsgi.shared->timers[i];
}
}
}
return ut;
}
#endif
inline int event_queue_read() {
return UWSGI_EVENT_IN;
}
inline int event_queue_write() {
return UWSGI_EVENT_OUT;
}
+7
View File
@@ -0,0 +1,7 @@
use POSIX;
open CONFIG,'welcome.ini';
dup2(fileno(CONFIG), 17);
exec './uwsgi','--ini','fd://17';
+47
View File
@@ -0,0 +1,47 @@
require 'fiber'
class SuspendingBody
def each
for i in 1..3
yield "number: #{i}\n"
UWSGI.async_sleep(1)
puts "sleep..."
Fiber.yield
end
fd = UWSGI.async_connect("81.174.68.52:80")
UWSGI.wait_fd_write(fd, 3)
Fiber.yield
io = IO.new(fd)
puts "connected"
io.syswrite("GET /uwsgi/export/1081%3A362d695b2f25/plugins/fiber/fiber.c HTTP/1.0\r\n")
io.syswrite("Host: projects.unbit.it\r\n")
io.syswrite("\r\n")
UWSGI.wait_fd_read(fd, 3)
Fiber.yield
puts "data available"
begin
while body = io.sysread(fd)
yield body
Fiber.yield
end
rescue
end
io.close
end
end
class RackFoo
def call(env)
[200, { 'Content-Type' => 'text/plain'}, SuspendingBody.new]
end
end
run RackFoo.new
+8
View File
@@ -0,0 +1,8 @@
uwsgi:
plugins: rack
socket: 127.0.0.1:3031
rack: fibers.ru
post-buffering: 4096
async: 10
loop: fiber
+9 -9
View File
@@ -4,28 +4,28 @@
int uwsgi_file_monitor_new() {
int inotify_fd ;
int inotify_fd;
inotify_fd = inotify_init();
if (inotify_fd < 0) {
uwsgi_error("inotify_init()");
return -1;
return -1;
}
return inotify_fd ;
return inotify_fd;
}
int uwsgi_file_monitor_add(int fd, char *what) {
int inotify_watch_fd ;
int inotify_watch_fd;
inotify_watch_fd = inotify_add_watch(fd, what, IN_ALL_EVENTS);
if (inotify_watch_fd < 0) {
uwsgi_error("inotify_add_watch()");
return -1;
return -1;
}
return inotify_watch_fd;
+12
View File
@@ -0,0 +1,12 @@
from flask import Flask, request
app = Flask(__name__)
app.debug = True
@app.route('/')
def hello_world():
return "<form method='POST' enctype='multipart/form-data' action='/upload'><input type='text' name='pippo'/><input type='file' name='ufile'/><input type='submit' value='upload'/></form>"
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
return str(len(request.form.get('pippo', 'boh'))) + request.form.get('pippo', 'boh')
return request.files['ufile'].read()
+133
View File
@@ -0,0 +1,133 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_gateway *register_fat_gateway(char *name, void (*loop)(void)) {
struct uwsgi_gateway *ug;
int num=1,i;
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<uwsgi.gateways_cnt;i++) {
if (!strcmp(name, uwsgi.gateways[i].name)) {
num++;
}
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = 0;
ug->name = name;
ug->loop = loop;
ug->num = num;
uwsgi.gateways_cnt++;
return ug;
}
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
pid_t gw_pid;
pid_t orig_pid = getpid();
struct uwsgi_gateway *ug;
int num=1,i;
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<uwsgi.gateways_cnt;i++) {
if (!strcmp(name, uwsgi.gateways[i].name)) {
num++;
}
}
gw_pid = uwsgi_fork(name);
if (gw_pid < 0) {
uwsgi_error("fork()");
return NULL;
}
if (!uwsgi.master_process) {
if (gw_pid > 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
if (!uwsgi.sockets) {
// wait for child end
//waitpid(-1, &i, 0);
}
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = orig_pid;
}
else {
if (gw_pid == 0) {
if (uwsgi.master_as_root) uwsgi_as_root();
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = gw_pid;
}
ug->name = name;
ug->loop = loop;
ug->num = num;
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
uwsgi.gateways_cnt++;
return ug;
}
void gateway_respawn(int id) {
pid_t gw_pid;
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
gw_pid = uwsgi_fork(ug->name);
if (gw_pid < 0) {
uwsgi_error("fork()");
return;
}
if (gw_pid == 0) {
if (uwsgi.master_as_root) uwsgi_as_root();
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
ug->loop();
// never here !!! (i hope)
exit(1);
}
ug->pid = gw_pid;
ug->respawns++;
if (ug->respawns == 1) {
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
else {
uwsgi_log( "respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
}
+9
View File
@@ -0,0 +1,9 @@
// http:3:GET / HTTP/1.1:192.168.173.10:80,192.168.173.11:80,192.168.173.12:80,192.168.173.13:80
/*
write(arg1);
wait_for_fd()
get_data() == 200
*/
View File
View File
View File
View File
+1
View File
@@ -0,0 +1 @@
// uwsgi:3::192.168.173.1:3031,192.168.173.2:3031,192.168.173.3:3031,192.168.173.4:3031
+27
View File
@@ -0,0 +1,27 @@
[uwsgi]
master = true
processes = 4
threads = 8
; initialize 4 sockets with 4 different protocols
socket = :3031
socket = :3032
socket = :3033
socket = :3034
socket-protocol = 0,uwsgi
socket-protocol = 1,http
socket-protocol = 2,fastcgi
socket-protocol = 3,uwsgidump
; add a cache with 1000 items of 96k
cache = 1000
cache-blocksize = 98304
log-micros = true
module = heavytest
mount = /cc=uwsgicc/__init__.py
+14
View File
@@ -0,0 +1,14 @@
import uwsgi
import werkzeug.testapp
uwsgi.cache_set("/cache/get", "HTTP 1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>I am the uWSGI cache</h1>")
def app001(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return "PATH_INFO=%s" % env['PATH_INFO']
def app002(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return "requests: %d" % uwsgi.total_requests()
uwsgi.applications = { '':werkzeug.testapp.test_app, '/app001':app001, '/app002':app002 }
+6
View File
@@ -0,0 +1,6 @@
import uwsgi
#uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
yield str(env['wsgi.input'].fileno())
yield "<h1>Hello World</h1>"
+7 -14
View File
@@ -6,20 +6,18 @@ import rrdtool
s_freq = 10
# this is a cron emulator done with the Spooler :)
def rrdtool_updater(env):
uwsgi.set_spooler_frequency(s_freq)
rrdtool.update('../test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.send_to_spooler({})
# this task will be executed every s_freq seconds
def rrdtool_updater(sig, sec):
rrdtool.update('test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.spooler = rrdtool_updater
uwsgi.register_timer(0, s_freq, uwsgi.KIND_WORKER, rrdtool_updater)
def hello_world(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain')])
yield 'Hello world !'
return 'Hello world !'
def graph(env, start_response):
@@ -27,12 +25,7 @@ def graph(env, start_response):
now = int(time.time())
graph_range = (3600*24)
rrdtool.graph('uwsgi_graph.png', '--start', str(now - graph_range), '--end', str(now), 'DEF:urequests=test.rrd:requests:AVERAGE', 'LINE2:urequests#00FF00')
fd = open('uwsgi_graph.png', 'r')
# send file to browser
return env['wsgi.file_wrapper'](fd, 4096)
# start the simil-cron
uwsgi.send_to_spooler({})
# send file to client
uwsgi.sendfile('uwsgi_graph.png')
uwsgi.applications = {'/': hello_world, '/graph':graph}
-397
View File
@@ -1,397 +0,0 @@
#include "uwsgi.h"
struct uwsgi_server uwsgi;
struct uwsgi_http_req {
pthread_t a_new_thread;
int fd;
struct sockaddr_in c_addr;
socklen_t c_len;
};
enum {
uwsgi_http_method,
uwsgi_http_uri,
uwsgi_http_protocol,
uwsgi_http_protocol_r,
uwsgi_http_header_key,
uwsgi_http_header_key_colon,
uwsgi_http_header_val,
uwsgi_http_header_val_r,
uwsgi_http_end
};
void http_end() {
uwsgi_log("closing uWSGI embedded HTTP server.\n");
exit(0);
}
void http_wait_end() {
pid_t wp_p;
int wp_c;
wp_p = waitpid(-1, &wp_c, 0);
uwsgi_log("closing uWSGI embedded HTTP server.\n");
exit(0);
}
static char *add_uwsgi_var(char *up, char *key, uint16_t keylen, char *val, uint16_t vallen, int header, char *watermark)
{
int i;
if (!header) {
if ( (up + 2 + keylen + 2 + vallen) > watermark ) return up ;
*up++ = (unsigned char) (keylen & 0xff);
*up++ = (unsigned char) ((keylen >> 8) & 0xff);
memcpy(up, key, keylen);
up += keylen;
} else {
for (i = 0; i < keylen; i++) {
if (key[i] == '-') {
key[i] = '_';
} else {
key[i] = toupper( (int) key[i]);
}
}
if (strncmp("CONTENT_TYPE", key, keylen) && strncmp("CONTENT_LENGTH", key, keylen)) {
if ( (up + 2 + keylen + 5 + 2 + vallen) > watermark ) return up ;
*up++ = (unsigned char) (((uint16_t) keylen + 5) & 0xff);
*up++ = (unsigned char) ((((uint16_t) keylen + 5) >> 8) & 0xff);
memcpy(up, "HTTP_", 5);
up += 5;
} else {
if ( (up + 2 + keylen + 2 + vallen) > watermark ) return up ;
*up++ = (unsigned char) (keylen & 0xff);
*up++ = (unsigned char) ((keylen >> 8) & 0xff);
}
memcpy(up, key, keylen);
up += keylen;
}
*up++ = (unsigned char) (vallen & 0xff);
*up++ = (unsigned char) ((vallen >> 8) & 0xff);
memcpy(up, val, vallen);
up += vallen;
return up;
}
static void *http_request(void *);
void http_loop(struct uwsgi_server * uwsgi)
{
struct uwsgi_http_req *ur;
int ret;
pthread_attr_t pa;
int stat_loc ;
ret = pthread_attr_init(&pa);
if (ret) {
uwsgi_log("pthread_attr_init() = %d\n", ret);
exit(1);
}
ret = pthread_attr_setdetachstate(&pa, PTHREAD_CREATE_DETACHED);
if (ret) {
uwsgi_log("pthread_attr_setdetachstate() = %d\n", ret);
exit(1);
}
// ignore broken pipes;
signal(SIGPIPE, SIG_IGN);
if (!uwsgi->http_only) {
signal(SIGCHLD, &http_end);
signal(SIGINT, &http_wait_end);
}
else {
signal(SIGINT, &http_end);
}
uwsgi->http_server_name = malloc(256);
if (!uwsgi->http_server_name) {
uwsgi_error("malloc()");
exit(1);
}
memset(uwsgi->http_server_name, 0, 256);
if (gethostname(uwsgi->http_server_name, 255)) {
uwsgi_error("gethostname()");
memcpy(uwsgi->http_server_name, "localhost", 9);
}
uwsgi_log("starting HTTP loop on %s (pid: %d)\n", uwsgi->http_server_name, (int) getpid());
for(;;) {
if (!uwsgi->http_only) {
if (waitpid(-1, &stat_loc, WNOHANG) != 0) {
http_end();
}
}
ur = malloc(sizeof(struct uwsgi_http_req));
if (!ur) {
uwsgi_error("malloc()");
sleep(1);
continue;
}
ur->c_len = sizeof(struct sockaddr_in) ;
ur->fd = accept(uwsgi->http_fd, (struct sockaddr *) &ur->c_addr, &ur->c_len);
if (ur->fd < 0) {
uwsgi_error("accept()");
free(ur);
continue;
}
ret = pthread_create(&ur->a_new_thread, &pa, http_request, (void *) ur);
if (ret) {
uwsgi_log("pthread_create() = %d\n", ret);
free(ur);
// sleep a bit to allow some resource gaining
sleep(1);
continue;
}
}
}
static void *http_request(void *u_h_r)
{
char buf[4096];
char tmp_buf[4096];
char uwsgipkt[4096];
struct uwsgi_http_req *ur = (struct uwsgi_http_req *) u_h_r ;
int clientfd = ur->fd;
int uwsgi_fd = -1;
int need_to_read = 1;
int state = uwsgi_http_method;
int http_body_len = 0;
size_t len;
int i, j;
char HTTP_header_key[1024];
uint16_t ulen;
char *ptr = tmp_buf;
int qs = 0;
char *up = uwsgipkt;
char *watermark = up + 4096 ;
char *watermark2 = tmp_buf + 4096 ;
int path_info_len;
char *ip;
up[0] = 0;
up[3] = 0;
up += 4;
while (need_to_read) {
len = read(clientfd, buf, 4096);
if (len <= 0) {
uwsgi_error("read()");
break;
}
for (i = 0; i < (int) len; i++) {
if (buf[i] == ' ') {
if (state == uwsgi_http_method) {
up = add_uwsgi_var(up, "REQUEST_METHOD", 14, tmp_buf, ptr - tmp_buf, 0, watermark);
ptr = tmp_buf;
state = uwsgi_http_uri;
} else if (state == uwsgi_http_uri) {
up = add_uwsgi_var(up, "REQUEST_URI", 11, tmp_buf, ptr - tmp_buf, 0, watermark);
path_info_len = ptr - tmp_buf;
for (j = 0; j < ptr - tmp_buf; j++) {
if (tmp_buf[j] == '?') {
path_info_len = j;
if (j + 1 < (ptr - tmp_buf)) {
up = add_uwsgi_var(up, "QUERY_STRING", 12, tmp_buf + j + 1, (ptr - tmp_buf) - (j + 1), 0, watermark);
qs = 1 ;
}
break;
}
}
if (!qs) {
up = add_uwsgi_var(up, "QUERY_STRING", 12, NULL, 0, 0, watermark);
}
up = add_uwsgi_var(up, "PATH_INFO", 9, tmp_buf, path_info_len, 0, watermark);
ptr = tmp_buf;
state = uwsgi_http_protocol;
} else if (state == uwsgi_http_header_key_colon) {
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
*ptr++ = 0;
memset(HTTP_header_key, 0, sizeof(HTTP_header_key));
memcpy(HTTP_header_key, tmp_buf, strlen(tmp_buf));
ptr = tmp_buf;
state = uwsgi_http_header_val;
} else {
//check for overflow
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
*ptr++ = buf[i];
}
} else if (buf[i] == '\r') {
if (state == uwsgi_http_protocol) {
state = uwsgi_http_protocol_r;
}
if (state == uwsgi_http_header_val) {
state = uwsgi_http_header_val_r;
} else if (state == uwsgi_http_header_key) {
state = uwsgi_http_end;
}
} else if (buf[i] == '\n') {
if (state == uwsgi_http_header_val_r) {
up = add_uwsgi_var(up, HTTP_header_key, strlen(HTTP_header_key), tmp_buf, ptr - tmp_buf, 1, watermark);
if (!strcmp("CONTENT_LENGTH", HTTP_header_key)) {
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
*ptr++ = 0;
http_body_len = atoi(tmp_buf);
}
ptr = tmp_buf;
state = uwsgi_http_header_key;
} else if (state == uwsgi_http_protocol_r) {
up = add_uwsgi_var(up, "SERVER_PROTOCOL", 15, tmp_buf, ptr - tmp_buf, 0, watermark);
ptr = tmp_buf;
state = uwsgi_http_header_key;
} else if (state == uwsgi_http_end) {
need_to_read = 0;
up = add_uwsgi_var(up, "SERVER_NAME", 11, uwsgi.http_server_name, strlen(uwsgi.http_server_name), 0, watermark);
up = add_uwsgi_var(up, "SERVER_PORT", 11, uwsgi.http_server_port, strlen(uwsgi.http_server_port), 0, watermark);
up = add_uwsgi_var(up, "SCRIPT_NAME", 11, "", 0, 0, watermark);
ip = inet_ntoa(ur->c_addr.sin_addr);
up = add_uwsgi_var(up, "REMOTE_ADDR", 11, ip, strlen(ip), 0, watermark);
//up = add_uwsgi_var(up, "REMOTE_ADDR", 11, "127.0.0.1", 9, 0, watermark);
//up = add_uwsgi_var(up, "REMOTE_USER", 11, "unknown", 7, 0);
for(j=0;j<uwsgi.http_vars_cnt;j++) {
char *separator;
separator = strchr(uwsgi.http_vars[j], '=');
if (separator) {
up = add_uwsgi_var(up, uwsgi.http_vars[j], separator - uwsgi.http_vars[j], separator + 1, strlen(separator + 1), 0, watermark);
}
else {
up = add_uwsgi_var(up, uwsgi.http_vars[j], strlen(uwsgi.http_vars[j]), NULL, 0, 0, watermark);
}
}
uwsgi_fd = uwsgi_connect(uwsgi.socket_name, 10);
if (uwsgi_fd >= 0) {
ulen = (up - uwsgipkt) - 4;
uwsgipkt[1] = (unsigned char) (ulen & 0xff);
uwsgipkt[2] = (unsigned char) ((ulen >> 8) & 0xff);
if (write(uwsgi_fd, uwsgipkt, ulen + 4) < 0) {
uwsgi_error("write()");
}
if (http_body_len > 0) {
if (http_body_len >= (int) len - (i + 1)) {
if (write(uwsgi_fd, buf + i + 1, len - (i + 1)) < 0) {
uwsgi_error("write()");
}
http_body_len -= len - (i + 1);
} else {
if (write(uwsgi_fd, buf + i, http_body_len) < 0) {
uwsgi_error("write()");
}
http_body_len = 0;
}
while (http_body_len > 0) {
int to_read = 4096;
if (http_body_len < to_read) {
to_read = http_body_len;
}
len = read(clientfd, uwsgipkt, to_read);
if (write(uwsgi_fd, uwsgipkt, len) < 0) {
uwsgi_error("write()");
}
http_body_len -= len;
}
}
while ((len = read(uwsgi_fd, uwsgipkt, 4096)) > 0) {
if (write(clientfd, uwsgipkt, len) < 0) {
uwsgi_error("write()");
}
}
close(uwsgi_fd);
}
else {
close(uwsgi_fd);
goto clear;
}
}
} else if (buf[i] == ':') {
if (state == uwsgi_http_header_key) {
state = uwsgi_http_header_key_colon;
} else {
//check for overflow
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
*ptr++ = buf[i];
}
} else {
//check for overflow
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
*ptr++ = buf[i];
}
}
}
clear:
close(clientfd);
free(ur);
pthread_exit(NULL);
return NULL;
}
+45 -70
View File
@@ -2,19 +2,16 @@
#include "uwsgi.h"
/*
ini file must be read ALL into memory.
This memory must not be freed for all the server lifecycle
*/
extern struct uwsgi_server uwsgi;
enum {
ini_key_start,
ini_val_start,
};
/*
ini file must be read ALL into memory.
This memory must not be freed for all the server lifecycle
*/
void ini_rstrip(char *line) {
off_t i ;
off_t i;
for(i = strlen(line)-1;i>=0; i--) {
if (line[i] == ' ' || line[i] == '\t') {
@@ -22,12 +19,12 @@ void ini_rstrip(char *line) {
continue;
}
break;
}
}
}
char *ini_lstrip(char *line) {
off_t i ;
off_t i;
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
@@ -44,10 +41,10 @@ char *ini_lstrip(char *line) {
char *ini_get_key(char *key) {
off_t i;
char *ptr = key ;
char *ptr = key;
for(i=0;i< (int) strlen(key);i++) {
ptr++ ;
ptr++;
if (key[i] == '=') {
key[i] = 0;
return ptr;
@@ -59,9 +56,9 @@ char *ini_get_key(char *key) {
char *ini_get_line(char *ini, off_t size) {
off_t i ;
off_t i;
char *ptr = ini;
for(i=0;i<size;i++) {
ptr++;
if (ini[i] == '\n') {
@@ -70,16 +67,19 @@ char *ini_get_line(char *ini, off_t size) {
}
}
// check if it is a stupid file without \n at the end
if (ptr > ini) {
return ptr;
}
return NULL;
}
void uwsgi_ini_config(char *file, struct option *long_options) {
void uwsgi_ini_config(char *file, char *magic_table[]) {
int fd;
ssize_t len;
int len = 0;
char *ini;
struct stat sb;
char *ini_line;
@@ -87,48 +87,34 @@ void uwsgi_ini_config(char *file, struct option *long_options) {
char *key;
char *val;
int lines = 1 ;
int lines = 1;
struct option *lopt, *aopt;
char *section_asked = "uwsgi";
char *colon ;
char *colon;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
colon = strchr(file, ':');
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
section_asked = colon+1 ;
section_asked = colon+1;
}
}
fd = open(file, O_RDONLY);
if (fd < 0) {
uwsgi_error("open()");
exit(1);
}
if (fstat(fd, &sb)) {
uwsgi_error("fstat()");
exit(1);
if (file[0] != 0) {
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
}
ini = malloc(sb.st_size+1);
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
if (!ini) {
uwsgi_error("malloc()");
exit(1);
}
len = read(fd, ini, sb.st_size);
if (len != sb.st_size) {
uwsgi_error("read()");
exit(1);
}
ini[sb.st_size+1] = 0 ;
while(sb.st_size) {
ini_line = ini_get_line(ini, sb.st_size);
while(len) {
ini_line = ini_get_line(ini, len);
if (ini_line == NULL) {
break;
}
@@ -153,33 +139,22 @@ void uwsgi_ini_config(char *file, struct option *long_options) {
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
lopt = long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(key, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
}
else {
manage_opt(aopt->val, val);
}
}
lopt++;
}
add_exported_option((char *)key, val, 0);
}
}
}
sb.st_size -= (ini_line - ini);
len -= (ini_line - ini);
ini += (ini_line - ini);
}
close(fd);
if (colon) {
colon[0] = ':';
}
}
#endif
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>it.unbit.uwsgi.emperor</string>
<key>ProgramArguments</key>
<array>
<string>/Users/roberta/uwsgi/uwsgi</string>
<string>--emperor</string>
<string>/Users/*/Library/uwsgi/*.{xml,ini,yml,yaml,js}</string>
</array>
</dict>
</plist>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>it.unbit.uwsgi</string>
<key>ProgramArguments</key>
<array>
<string>/Users/roberta/uwsgi/uwsgi</string>
<string>--socket</string>
<string>:3032</string>
<string>--module</string>
<string>welcome</string>
<string>--master</string>
<string>--die-on-term</string>
</array>
</dict>
</plist>
+111
View File
@@ -0,0 +1,111 @@
#ifdef UWSGI_JSON
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#include <jansson.h>
/*
I really love the jansson library...
*/
void uwsgi_json_config(char *file, char *magic_table[]) {
int len = 0;
char *json_data;
const char *key;
json_t *root;
json_error_t error;
json_t *config;
json_t *config_value, *config_array_item;
void *config_iter;
char *object_asked = "uwsgi";
char *colon;
int i;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
object_asked = colon+1;
}
}
uwsgi_log("[uWSGI] getting JSON configuration from %s\n", file);
json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
#ifdef JANSSON_MAJOR_VERSION
root = json_loads(json_data, 0, &error);
#else
root = json_loads(json_data, &error);
#endif
if (!root) {
uwsgi_log("error parsing JSON data: line %d %s\n", error.line, error.text);
exit(1);
}
config = json_object_get(root, object_asked);
if (!json_is_object(config)) {
uwsgi_log("you must define a object named %s in your JSON data\n", object_asked);
exit(1);
}
config_iter = json_object_iter(config);
while(config_iter) {
key = json_object_iter_key(config_iter);
config_value = json_object_iter_value(config_iter);
if (json_is_string(config_value)) {
add_exported_option((char *)key, (char *) json_string_value(config_value), 0);
}
else if (json_is_true(config_value)) {
add_exported_option((char *)key, strdup("1"), 0);
}
else if (json_is_false(config_value) || json_is_null(config_value)) {
add_exported_option((char *)key, strdup("0"), 0);
}
else if (json_is_integer(config_value)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_value)), 0);
}
else if (json_is_array(config_value)) {
for(i=0;i<(int)json_array_size(config_value);i++) {
config_array_item = json_array_get(config_value, i);
if (json_is_string(config_array_item)) {
add_exported_option((char *)key, (char *) json_string_value(config_array_item), 0);
}
else if (json_is_true(config_array_item)) {
add_exported_option((char *)key, strdup("1"), 0);
}
else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
add_exported_option((char *)key, strdup("0"), 0);
}
else if (json_is_integer(config_array_item)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
}
}
}
config_iter = json_object_iter_next(config, config_iter);
}
}
#endif
+228 -187
View File
@@ -1,22 +1,31 @@
#ifdef UWSGI_LDAP
#ifdef UWSGI_LDAP
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#include <ldap.h>
void ldap2uwsgi(char *ldapname, char *uwsginame) {
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
char *ptr = uwsginame ;
#ifndef ldap_unbind_ext_s
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
int i;
for(i=0;i< (int) strlen(ldapname);i++) {
if (isupper( (int)ldapname[i])) {
*ptr++= '-';
*ptr++= tolower( (int) ldapname[i]);
*ptr++ = '-';
*ptr++ = tolower( (int) ldapname[i]);
}
else {
*ptr++= ldapname[i] ;
*ptr++ = ldapname[i];
}
}
@@ -24,7 +33,6 @@ void ldap2uwsgi(char *ldapname, char *uwsginame) {
}
int calc_ldap_name(char *name) {
int i;
int counter = 0;
@@ -34,192 +42,223 @@ int calc_ldap_name(char *name) {
}
}
return strlen(name) + counter ;
return strlen(name) + counter;
}
void uwsgi_ldap_schema_dump_ldif(struct option *lo) {
struct uwsgi_ldap_entry {
int num;
char names[1024];
int has_arg;
};
struct option *aopt, *lopt ;
lopt = lo;
int i;
int counter = 30000;
void uwsgi_name_to_ldap(char *src, char *dst) {
int pythonpath_found = 0 ;
int i;
char *ptr = dst;
memset(dst, 0, 1024);
strcat(dst, " 'uWSGI");
ptr+= 7;
for(i=0;i< (int)strlen(src);i++) {
if (src[i] == '-') {
i++;
*ptr++= toupper( (int) src[i]);
}
else {
*ptr++= src[i];
}
}
strcat(dst, "'");
}
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (uwsgi_list_has_str(ule->names, name+1)) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct option *aopt, *lopt;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
static int counter = 30000000;
*count = 0;
lopt = uwsgi.long_options;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
while( (aopt = lopt) ) {
if (!aopt->name)
break;
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry) goto next;
if (aopt->flag) {
entry = &ule[*count] ;
entry->num = counter;
strcpy(entry->names, ldap_name);
counter++;
*count = *count+1;
}
else {
entry = get_ldap_by_num(ule, aopt->val, *count);
if (entry) {
strcat(entry->names, ldap_name);
}
else {
entry = &ule[*count] ;
entry->num = aopt->val;
strcpy(entry->names, ldap_name);
*count = *count+1;
}
}
entry->has_arg = aopt->has_arg;
next:
lopt++;
}
return ule;
}
void uwsgi_ldap_schema_dump_ldif() {
int i;
int items;
uwsgi_log("\n");
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
uwsgi_log("objectClass: olcSchemaConfig\n");
uwsgi_log("cn: uwsgi\n");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
if (aopt->val == LONG_ARGS_PYTHONPATH) {
if (pythonpath_found) {
goto next;
}
pythonpath_found = 1;
for(i=0;i<items;i++) {
entry = &ule[i];
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
if (aopt->flag) {
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter) ;
counter++;
}
else {
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val) ;
}
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
if (aopt->has_arg) {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
next:
lopt++;
}
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n") ;
lopt = lo;
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
pythonpath_found = 0;
while( (aopt = lopt) ) {
if (!aopt->name)
break;
if (aopt->val == LONG_ARGS_PYTHONPATH) {
if (pythonpath_found) {
goto next2;
}
pythonpath_found = 1;
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("uWSGI");
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
uwsgi_log(" $ ");
next2:
lopt++;
}
uwsgi_log("uWSGInull ))\n");
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for(i=0;i<items;i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGInull ))\n");
uwsgi_log("\n");
exit(0);
exit(0);
}
void uwsgi_ldap_schema_dump() {
void uwsgi_ldap_schema_dump(struct option *lo) {
struct option *aopt, *lopt ;
lopt = lo;
int i;
int counter = 30000;
int pythonpath_found = 0;
int items;
while( (aopt = lopt) ) {
if (!aopt->name)
break;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
if (aopt->val == LONG_ARGS_PYTHONPATH) {
if (pythonpath_found) {
goto next;
}
pythonpath_found = 1;
}
if (aopt->flag) {
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter) ;
counter++;
}
else {
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val) ;
}
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
if (aopt->has_arg) {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
next:
lopt++;
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n") ;
lopt = lo;
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
pythonpath_found = 0;
while( (aopt = lopt) ) {
if (!aopt->name)
break;
for(i=0;i<items;i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
}
if (aopt->val == LONG_ARGS_PYTHONPATH) {
if (pythonpath_found) {
goto next2;
}
pythonpath_found = 1;
}
uwsgi_log("uWSGI");
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
uwsgi_log(" $ ");
next2:
lopt++;
}
uwsgi_log("uWSGInull ))\n");
exit(0);
}
void uwsgi_ldap_config(struct uwsgi_server *uwsgi, struct option *long_options) {
void uwsgi_ldap_config() {
LDAP *ldp;
LDAPMessage *results, *entry;
@@ -234,12 +273,10 @@ void uwsgi_ldap_config(struct uwsgi_server *uwsgi, struct option *long_options)
int desired_version = LDAP_VERSION3;
int ret;
struct option *aopt, *lopt;
LDAPURLDesc *ldap_url;
if (uwsgi->ldap) {
url = uwsgi->ldap;
if (uwsgi.ldap) {
url = uwsgi.ldap;
}
if (!ldap_is_ldap_url(url)) {
@@ -251,6 +288,8 @@ void uwsgi_ldap_config(struct uwsgi_server *uwsgi, struct option *long_options)
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
url_slash = strchr(url, '/');
url_slash = strchr(url_slash + 1, '/');
@@ -265,21 +304,28 @@ void uwsgi_ldap_config(struct uwsgi_server *uwsgi, struct option *long_options)
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
#endif
#if LDAP_API_VERSION >= 3000
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ( (ldp = ldap_init( ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
if ( (ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
exit(1);
}
#ifdef UWSGI_DEBUG
@@ -287,7 +333,7 @@ void uwsgi_ldap_config(struct uwsgi_server *uwsgi, struct option *long_options)
#endif
free(ldap_url);
if (ldap_count_entries(ldp, results) < 1) {
uwsgi_log("no LDAP entry found\n");
exit(1);
@@ -295,9 +341,11 @@ void uwsgi_ldap_config(struct uwsgi_server *uwsgi, struct option *long_options)
entry = ldap_first_entry(ldp, results);
int found = 0;
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr,"uWSGI",5)) {
found = 1;
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
if (!uwsgi_attr) {
uwsgi_error("malloc()");
@@ -311,7 +359,7 @@ void uwsgi_ldap_config(struct uwsgi_server *uwsgi, struct option *long_options)
#endif
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_val;
// do not free uwsgi_attr/uwsgi_val;
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
if (!uwsgi_val) {
uwsgi_error("malloc()");
@@ -321,32 +369,25 @@ void uwsgi_ldap_config(struct uwsgi_server *uwsgi, struct option *long_options)
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
lopt = long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(uwsgi_attr, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
}
else {
manage_opt(aopt->val, uwsgi_val);
}
}
lopt++;
}
add_exported_option((char*) uwsgi_attr, uwsgi_val, 0);
free(bervalues);
}
else {
free(uwsgi_attr);
}
free(bervalues);
free(uwsgi_attr);
}
free(attr);
}
if (!found) {
uwsgi_log("no uWSGI LDAP entry found\n");
exit(1);
}
free(ber);
free(results);
ldap_unbind_ext_s(ldp, NULL, NULL);
}
#endif
+806
View File
@@ -0,0 +1,806 @@
#include "../uwsgi.h"
#define AMQP_CONNECTION_HEADER "AMQP\0\0\x09\x01"
#ifdef __BIG_ENDIAN__
#define ntohll(x) x
#else
#define ntohll(x) ( ( (uint64_t)(ntohl( (uint32_t)((x << 32) >> 32) )) << 32) | ntohl( ((uint32_t)(x >> 32)) ) )
#endif
#define htonll(x) ntohll(x)
#define amqp_send(a, b, c) if (send(a, b, c, 0) < 0) { uwsgi_error("send()"); return -1; }
struct amqp_frame_header {
char type;
uint16_t channel;
uint32_t size;
} __attribute__((__packed__));
struct amqp_frame_method {
uint16_t class_id;
uint16_t method_id;
} __attribute__((__packed__));
static char *amqp_simple_get_frame(int, struct amqp_frame_header *);
static char *amqp_get_method(int, uint16_t, uint16_t, uint32_t *);
/*
static char *amqp_get_longstr(char *ptr, char *watermark) {
uint32_t longstr_size;
if (ptr+4 > watermark) return NULL;
memcpy(&longstr_size, ptr, 4);
longstr_size = ntohl(longstr_size);
if (ptr+4+longstr_size > watermark) return NULL;
return ptr+4+longstr_size;
}
*/
static char *amqp_get_str(char *ptr, char *watermark) {
uint8_t str_size;
// over engeneering...
if (ptr+1 > watermark) return NULL;
str_size = *ptr;
if (ptr+1+str_size > watermark) return NULL;
return ptr+1+str_size;
}
/*
static char *amqp_get_table(char *ptr, char *watermark) {
uint32_t table_size;
if (ptr+4 > watermark) return NULL;
memcpy(&table_size, ptr, 4);
table_size = ntohl(table_size);
if (ptr+4+table_size > watermark) return NULL;
return ptr+4+table_size;
}
*/
static char *amqp_get_short(char *ptr, char *watermark, uint16_t *sv) {
uint16_t tmp_short;
if (ptr+2 > watermark) return NULL;
memcpy(&tmp_short, ptr, 2);
*sv = ntohs(tmp_short);
return ptr+2;
}
static char *amqp_get_long(char *ptr, char *watermark, uint32_t *lv) {
uint32_t tmp_long;
if (ptr+4 > watermark) return NULL;
memcpy(&tmp_long, ptr, 4);
*lv = ntohl(tmp_long);
return ptr+4;
}
static char *amqp_get_longlong(char *ptr, char *watermark, uint64_t *llv) {
uint64_t tmp_longlong;
if (ptr+8 > watermark) return NULL;
memcpy(&tmp_longlong, ptr, 8);
*llv = ntohll(tmp_longlong);
return ptr+8;
}
static int amqp_send_ack(int fd, uint64_t delivery_tag) {
uint32_t size = 4 + 8 + 1;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 60 method 80
amqp_send(fd, "\x00\x3C\x00\x50", 4);
// set delivery_tag
delivery_tag = htonll(delivery_tag);
amqp_send(fd, &delivery_tag, 8);
// empty bits
amqp_send(fd, "\0", 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
uint32_t size;
struct amqp_frame_header fh;
uint64_t delivery_tag;
uint64_t current_size = 0;
char *ptr;
char *watermark;
uint16_t sv;
char *frame = amqp_get_method(fd, 60, 60, &size);
if (!frame) return NULL;
ptr = frame+4;
watermark = frame+size;
// consumer_tag
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
// delivery_tag (needed for ack)
ptr = amqp_get_longlong(ptr, watermark, &delivery_tag); if (!ptr) goto clear;
// redelivered
if (ptr+1 > watermark) goto clear;
ptr++;
// exchange
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
// routing_key
if (ptr+1 > watermark) goto clear;
uint8_t rk_size = (uint8_t) *ptr;
ptr++;
if (ptr+rk_size > watermark) goto clear;
if (rk_size > 0) {
char *rkey = uwsgi_concat2n(ptr, rk_size, "", 0);
ptr+=rk_size;
*routing_key = rkey;
}
else {
*routing_key = NULL;
}
char *header = amqp_simple_get_frame(fd, &fh);
if (!header) goto clear;
if (fh.type != 2) goto clear2;
ptr = header;
watermark = ptr+fh.size;
// header class_id
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
// header weight
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
// message size;
ptr = amqp_get_longlong(ptr, watermark, msgsize); if (!ptr) goto clear2;
free(frame);
free(header);
char *fullbody = uwsgi_malloc(*msgsize);
char *message;
while(current_size < *msgsize) {
message = amqp_simple_get_frame(fd, &fh);
if (!message) goto clear;
if (fh.type != 3) {
free(message);
goto clear3;
}
if (fh.size+current_size > *msgsize) {
free(message);
goto clear3;
}
memcpy(fullbody+current_size, message, fh.size);
current_size+=fh.size;
free(message);
}
if (amqp_send_ack(fd, delivery_tag) < 0) {
goto clear3;
}
return fullbody;
clear3:
free(fullbody);
return NULL;
clear2:
free(header);
clear:
free(frame);
return NULL;
}
static int amqp_send_exchange_declare( int fd, char *exchange, char *exchange_type) {
uint32_t size = 4 + 2 + (1 +strlen(exchange)) + (1 +strlen(exchange_type)) + 1 + 4;
uint8_t shortsize = strlen(exchange) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 40 method 10
amqp_send(fd, "\x00\x28\x00\x0A", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set exchange name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange, shortsize);
// set exchange type
shortsize = strlen(exchange_type);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange_type, shortsize);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_bind( int fd, char *queue, char *exchange) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + (1 +strlen(exchange)) + 1 + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 50 method 20
amqp_send(fd, "\x00\x32\x00\x14", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// set exchange name
shortsize = strlen(exchange);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange, shortsize);
// set empty routing-key
amqp_send(fd, "\0", 1);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_consume( int fd, char *queue) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 60 method 20
amqp_send(fd, "\x00\x3C\x00\x14", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// set tag name
amqp_send(fd, "\0", 1);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_wait_connection_start(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 10, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_exchange_declare_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 40, 11, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_basic_consume_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 60, 21, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_channel_open_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 20, 11, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_queue_bind_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 50, 21, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static char *amqp_wait_queue_declare_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 50, 11, &size);
char *queue = NULL;
char *ptr;
char *watermark;
if (frame) {
ptr = frame+4;
watermark = frame+size;
ptr = amqp_get_str(ptr, watermark); if (!ptr) { free(frame); return NULL; }
queue = uwsgi_concat2n(frame+5, *(frame+4), "", 0);
free(frame);
return queue;
}
return NULL;
}
static int amqp_wait_connection_open_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 41, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_connection_tune(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 30, &size);
uint16_t sv;
uint32_t lv;
char *watermark ;
char *ptr;
if (frame) {
ptr = frame+4;
watermark = frame+size;
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP max channels: %d\n", sv);
ptr = amqp_get_long(ptr, watermark, &lv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP max frame size: %d\n", lv);
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP heartbeath: %d\n", sv);
free(frame);
return 0;
}
return -1;
}
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
char *ptr = (char *) fh;
size_t len = 0, rlen;
while(len < 7) {
rlen = recv(fd, ptr, 7-len, 0);
if (rlen <= 0) {
uwsgi_error("recv()");
return NULL;
}
len += rlen;
ptr += rlen;
}
fh->channel = ntohs(fh->channel);
fh->size = ntohl(fh->size);
len = 0;
char *frame = malloc(fh->size+1);
ptr = frame;
while(len < fh->size+1) {
rlen = recv(fd, ptr, (fh->size+1)-len, 0);
if (rlen <= 0) {
uwsgi_error("recv()");
return NULL;
}
len += rlen;
ptr += rlen;
}
return frame;
}
static char *amqp_get_method(int fd, uint16_t class_id, uint16_t method_id, uint32_t *size) {
struct amqp_frame_header fh;
struct amqp_frame_method *fm;
char *frame = amqp_simple_get_frame(fd, &fh);
if (!frame) return NULL;
if (fh.type != 1) goto clear;
fm = (struct amqp_frame_method *) frame;
fm->class_id = ntohs(fm->class_id);
fm->method_id = ntohs(fm->method_id);
if (fm->class_id != class_id) goto clear;
if (fm->method_id != method_id) goto clear;
*size = fh.size;
return frame;
clear:
free(frame);
return NULL;
}
static int amqp_send_channel_open(int fd, uint16_t id) {
uint32_t size = 4 + 1;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 20 method 10
amqp_send(fd, "\x00\x14\x00\x0A", 4);
amqp_send(fd, "\0", 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int amqp_send_connection_open(int fd, char *vhost) {
uint8_t shortsize = strlen(vhost);
uint32_t size = 4 + 1 +strlen(vhost) + 2;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 28
amqp_send(fd, "\x00\x0A\x00\x28", 4);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, vhost, strlen(vhost));
shortsize = 0;
amqp_send(fd, &shortsize, 1);
amqp_send(fd, &shortsize, 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int amqp_send_connection_tune_ok(int fd, uint16_t max_chan, uint32_t max_frame_size, uint16_t heartbeat) {
uint32_t size = 4 + 2 + 4 + 2;
size = htonl(size);
max_chan = htons(max_chan);
max_frame_size = htonl(max_frame_size);
heartbeat = htons(heartbeat);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 15
amqp_send(fd, "\x00\x0A\x00\x1F", 4);
amqp_send(fd, &max_chan, 2);
amqp_send(fd, &max_frame_size, 4);
amqp_send(fd, &heartbeat, 2);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_declare(int fd, char *queue) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 50 method 10
amqp_send(fd, "\x00\x32\x00\x0A", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static char *amqp_get_queue(int fd, char *queue) {
if (amqp_send_queue_declare(fd, queue) < 0) {
return NULL;
}
return amqp_wait_queue_declare_ok(fd);
}
static int amqp_send_connection_start_ok(int fd, char *mech, char *sasl_response, int sasl_response_size, char *locale) {
uint32_t size = 4 + 4 + (1 +strlen(mech)) + (4 + sasl_response_size) + (1 + strlen(locale));
uint8_t shortsize ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 11
amqp_send(fd, "\x00\x0A\x00\x0B", 4);
// send empty client properties
amqp_send(fd, "\0\0\0\0", 4);
// send mechanism short string
shortsize = strlen(mech);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, mech, strlen(mech));
// send sasl response
size = htonl(sasl_response_size);
amqp_send(fd, &size, 4);
amqp_send(fd, sasl_response, sasl_response_size);
// send locale
shortsize = strlen(locale);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, locale, strlen(locale));
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int uwsgi_amqp_consume_queue(int fd, char *vhost, char *username, char *password, char *queue, char *exchange, char *exchange_type) {
char *auth = uwsgi_concat4n("\0",1, username, strlen(username), "\0",1, password, strlen(password));
if (send(fd, AMQP_CONNECTION_HEADER, 8, 0) < 0) {
uwsgi_error("send()");
return -1;
}
if (amqp_wait_connection_start(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.start\n");
return -1;
}
uwsgi_log("sending Connection.start-ok\n");
if (amqp_send_connection_start_ok(fd, "PLAIN", auth, strlen(username)+strlen(password)+2, "en_US") < 0) {
free(auth);
uwsgi_log("AMQP error sending Connection.start-ok\n");
return -1;
}
free(auth);
if (amqp_wait_connection_tune(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.tune\n");
return -1;
}
uwsgi_log("sending Connection.tune-ok\n");
if (amqp_send_connection_tune_ok(fd, 0, 0xffff, 0) < 0) {
uwsgi_log("AMQP error sending Connection.tune-ok\n");
return -1;
}
uwsgi_log("sending Connection.open\n");
if (amqp_send_connection_open(fd, vhost) < 0) {
uwsgi_log("AMQP error sending Connection.open\n");
return -1;
}
if (amqp_wait_connection_open_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.open-ok\n");
return -1;
}
uwsgi_log("sending Channel.open\n");
if (amqp_send_channel_open(fd, 1) < 0) {
uwsgi_log("AMQP error sending Channel.open\n");
return -1;
}
if (amqp_wait_channel_open_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Channel.open-ok\n");
return -1;
}
queue = amqp_get_queue(fd, queue);
if (!queue) {
uwsgi_log("AMQP error sending Queue.declare\n");
return -1;
}
if (exchange) {
if (amqp_send_exchange_declare(fd, exchange, exchange_type) < 0) {
uwsgi_log("AMQP error sending Exchange.declare\n");
free(queue);
return -1;
}
if (amqp_wait_exchange_declare_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Exchange.declare-ok\n");
free(queue);
return -1;
}
if (amqp_send_queue_bind(fd, queue, exchange) < 0) {
uwsgi_log("AMQP error sending Queue.bind\n");
free(queue);
return -1;
}
if (amqp_wait_queue_bind_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Queue.bind-ok\n");
free(queue);
return -1;
}
}
if (amqp_send_queue_consume(fd, queue) < 0) {
uwsgi_log("AMQP error sending Basic.consume\n");
free(queue);
return -1;
}
if (amqp_wait_basic_consume_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Basic.consume-ok\n");
free(queue);
return -1;
}
free(queue);
uwsgi_log("AMQP subscription done, waiting for events...\n");
return 0;
}
+149
View File
@@ -0,0 +1,149 @@
#include "../uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifndef CLONE_NEWUTS
#define CLONE_NEWUTS 0x04000000
#endif
#ifndef CLONE_NEWPID
#define CLONE_NEWPID 0x20000000
#endif
#ifndef CLONE_NEWIPC
#define CLONE_NEWIPC 0x08000000
#endif
#ifndef CLONE_NEWNET
#define CLONE_NEWNET 0x40000000
#endif
void linux_namespace_start(void *argv) {
for (;;) {
char stack[PTHREAD_STACK_MIN];
int waitpid_status;
uwsgi_log("*** jailing uWSGI in %s ***\n", uwsgi.ns);
int clone_flags = SIGCHLD | CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS;
if (uwsgi.ns_net) {
clone_flags |= CLONE_NEWNET;
}
pid_t pid = clone(uwsgi_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
if (pid == -1) {
uwsgi_error("clone()");
exit(1);
}
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
pid = waitpid(pid, &waitpid_status, 0);
if (pid < 0) {
uwsgi_error("waitpid()");
exit(1);
}
// in Linux this is reliable
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == 1) {
exit(1);
}
uwsgi_log("pid %d ended. Respawning...\n", (int) pid);
}
// never here
}
void linux_namespace_jail() {
char *ns_tmp_mountpoint = NULL, *ns_tmp_mountpoint2 = NULL;
if (getpid() != 1) {
uwsgi_log("your kernel does not support linux pid namespace\n");
exit(1);
}
char *ns_hostname = strchr(uwsgi.ns, ':');
if (ns_hostname) {
ns_hostname[0] = 0;
ns_hostname++;
if (sethostname(ns_hostname, strlen(ns_hostname))) {
uwsgi_error("sethostname()");
}
}
FILE *procmounts;
char line[1024];
int unmounted = 1;
char *delim0, *delim1;
if (chdir(uwsgi.ns)) {
uwsgi_error("chdir()");
exit(1);
}
if (strcmp(uwsgi.ns, "/")) {
ns_tmp_mountpoint = uwsgi_concat2(uwsgi.ns, "/.uwsgi_ns_tmp_mountpoint");
mkdir(ns_tmp_mountpoint, S_IRWXU);
ns_tmp_mountpoint2 = uwsgi_concat2(ns_tmp_mountpoint, "/.uwsgi_ns_tmp_mountpoint");
mkdir(ns_tmp_mountpoint2, S_IRWXU);
if (mount(uwsgi.ns, ns_tmp_mountpoint, "none", MS_BIND, NULL)) {
uwsgi_error("mount()");
}
if (chdir(ns_tmp_mountpoint)) {
uwsgi_error("chdir()");
}
if (pivot_root(".", ns_tmp_mountpoint2)) {
uwsgi_error("pivot_root()");
exit(1);
}
if (chdir("/")) {
uwsgi_error("chdir()");
exit(1);
}
}
uwsgi_log("remounting /proc\n");
if (mount("proc", "/proc", "proc", 0, NULL)) {
uwsgi_error("mount()");
}
while (unmounted) {
unmounted = 0;
procmounts = fopen("/proc/self/mounts", "r");
while (fgets(line, 1024, procmounts) != NULL) {
delim0 = strchr(line, ' ');
delim0++;
delim1 = strchr(delim0, ' ');
*delim1 = 0;
if (!strcmp(delim0, "/") || !strcmp(delim0, "/proc"))
continue;
if (!umount(delim0)) {
unmounted++;
}
}
fclose(procmounts);
}
if (rmdir("/.uwsgi_ns_tmp_mountpoint/.uwsgi_ns_tmp_mountpoint")) {
uwsgi_error("rmdir()");
}
if (rmdir("/.uwsgi_ns_tmp_mountpoint")) {
uwsgi_error("rmdir()");
}
if (strcmp(uwsgi.ns, "/")) {
free(ns_tmp_mountpoint2);
free(ns_tmp_mountpoint);
}
}
+397
View File
@@ -0,0 +1,397 @@
#include "../uwsgi.h"
#ifdef OBSOLETE_LINUX_KERNEL
#ifndef __u16
#define __u16 u_int16_t
#endif
#ifndef __u32
#define __u32 u_int32_t
#endif
#ifndef __s32
#define __s32 int32_t
#endif
#ifndef __u8
#define __u8 u_int8_t
#endif
#endif
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#ifdef CLONE_NEWNET
#define NLMSG_TAIL(nmsg) \
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
#ifndef VETH_INFO_PEER
# define VETH_INFO_PEER 1
#endif
struct uwsgi_nl_req {
struct nlmsghdr nlmsg;
struct ifinfomsg ifinfomsg;
};
struct uwsgi_nl_ipreq {
struct nlmsghdr nlmsg;
struct ifaddrmsg ifaddrmsg;
};
struct uwsgi_nl_rtreq {
struct nlmsghdr nlmsg;
struct rtmsg rtmsg;
};
int uwsgi_nl_send(struct nlmsghdr *);
struct nlmsghdr *uwsgi_netlink_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
unr->ifinfomsg.ifi_family = AF_UNSPEC;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
nlmsg->nlmsg_type = RTM_NEWLINK;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
return nlmsg;
}
struct nlmsghdr *uwsgi_netlink_ip_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
uni->ifaddrmsg.ifa_family = AF_INET;
uni->ifaddrmsg.ifa_scope = 0;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
nlmsg->nlmsg_type = RTM_NEWADDR;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
return nlmsg;
}
struct nlmsghdr *uwsgi_netlink_rt_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
unr->rtmsg.rtm_family = AF_INET;
unr->rtmsg.rtm_table = RT_TABLE_MAIN;
unr->rtmsg.rtm_protocol = RTPROT_STATIC;
unr->rtmsg.rtm_scope = RT_SCOPE_UNIVERSE;
unr->rtmsg.rtm_type = RTN_UNICAST;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
nlmsg->nlmsg_type = RTM_NEWROUTE;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
return nlmsg;
}
int uwsgi_netlink_rt(char *src, char *dst, int dst_prefix, char *gw) {
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
struct rtattr *rta;
struct in_addr ia;
struct in_addr oa;
struct in_addr ga;
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
if (inet_pton(AF_INET, src, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
if (inet_pton(AF_INET, dst, &oa) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
if (inet_pton(AF_INET, gw, &ga) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_PREFSRC;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_DST;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &oa.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_GATEWAY;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ga.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
unr->rtmsg.rtm_src_len = 0;
unr->rtmsg.rtm_dst_len = dst_prefix;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_gw(char *iface, char *ip) {
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
struct rtattr *rta;
struct in_addr ia;
uint32_t zero = 0;
int index = if_nametoindex(iface);
if (!index) return -1;
if (inet_pton(AF_INET, ip, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_GATEWAY;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_DST;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &zero, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_OIF;
rta->rta_len = RTA_LENGTH(sizeof(int));
memcpy(RTA_DATA(rta), &index, sizeof(int));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_ip(char *iface, char *ip, int prefix) {
struct nlmsghdr *nlmsg = uwsgi_netlink_ip_alloc();
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
struct rtattr *rta;
struct in_addr ia;
int index = if_nametoindex(iface);
if (!index) return -1;
uni->ifaddrmsg.ifa_index = index;
uni->ifaddrmsg.ifa_prefixlen = prefix;
if (inet_pton(AF_INET, ip, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFA_LOCAL;
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFA_ADDRESS;
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_veth_attach(char *veth1, pid_t pid) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
struct rtattr *rta;
int index = if_nametoindex(veth1);
if (!index) return -1;
unr->ifinfomsg.ifi_index = index;
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_NET_NS_PID;
rta->rta_len = RTA_LENGTH(sizeof(pid_t));
memcpy(RTA_DATA(rta), &pid, sizeof(pid_t));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_ifup(char *iface) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
int index = if_nametoindex(iface);
if (!index) return -1;
unr->ifinfomsg.ifi_index = index;
unr->ifinfomsg.ifi_change |= IFF_UP;
unr->ifinfomsg.ifi_flags |= IFF_UP;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_del(char *iface) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
int index = if_nametoindex(iface);
if (!index) return -1;
nlmsg->nlmsg_type = RTM_DELLINK;
unr->ifinfomsg.ifi_index = index;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_veth(char *veth0, char *veth1) {
struct rtattr *rta, *rta0, *rta1, *rta2;
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
nlmsg->nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
// IFLA_LINKINFO
rta0 = NLMSG_TAIL(nlmsg);
rta0->rta_type = IFLA_LINKINFO;
rta0->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta0->rta_len);
// IFLA_INFO_KIND
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_INFO_KIND;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), "veth", 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
// IFLA_INFO_DATA
rta1 = NLMSG_TAIL(nlmsg);
rta1->rta_type = IFLA_INFO_DATA;
rta1->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta1->rta_len);
// VETH_INFO_PEER
rta2 = NLMSG_TAIL(nlmsg);
rta2->rta_type = VETH_INFO_PEER;
rta2->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta2->rta_len);
nlmsg->nlmsg_len += sizeof(struct ifinfomsg);
// IFLA_IFNAME
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_IFNAME;
rta->rta_len = RTA_LENGTH(strlen(veth1));
memcpy(RTA_DATA(rta), veth1, strlen(veth1));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta2->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta2;
rta1->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta1;
rta0->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta0;
// IFLA_IFNAME
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_IFNAME;
rta->rta_len = RTA_LENGTH(strlen(veth0));
memcpy(RTA_DATA(rta), veth0, strlen(veth0));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_nl_send(struct nlmsghdr *nlmsg) {
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = (void*)nlmsg,
.iov_len = nlmsg->nlmsg_len,
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
int ret;
int nlfd;
memset(&nladdr, 0, sizeof(struct sockaddr_nl));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (nlfd < 0) {
uwsgi_error("socket()");
free(nlmsg);
return -1;
}
ret = sendmsg(nlfd, &msg, 0);
if (ret < 0) {
uwsgi_error("sendmsg()");
free(nlmsg);
close(nlfd);
return -1;
}
ret = recvmsg(nlfd, &msg, 0);
if (ret < 0) {
uwsgi_error("recvmsg()");
free(nlmsg);
close(nlfd);
return -1;
}
if (nlmsg->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlmsg);
ret = err->error;
}
free(nlmsg);
close(nlfd);
return ret;
}
#endif
+309
View File
@@ -0,0 +1,309 @@
/*
*** uWSGI, stripped down version of Linux rbtree ***
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
(C) 2002 David Woodhouse <dwmw2@infradead.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../uwsgi.h"
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
struct rb_node *right = node->rb_right;
struct rb_node *parent = rb_parent(node);
if ((node->rb_right = right->rb_left))
rb_set_parent(right->rb_left, node);
right->rb_left = node;
rb_set_parent(right, parent);
if (parent)
{
if (node == parent->rb_left)
parent->rb_left = right;
else
parent->rb_right = right;
}
else
root->rb_node = right;
rb_set_parent(node, right);
}
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{
struct rb_node *left = node->rb_left;
struct rb_node *parent = rb_parent(node);
if ((node->rb_left = left->rb_right))
rb_set_parent(left->rb_right, node);
left->rb_right = node;
rb_set_parent(left, parent);
if (parent)
{
if (node == parent->rb_right)
parent->rb_right = left;
else
parent->rb_left = left;
}
else
root->rb_node = left;
rb_set_parent(node, left);
}
void rb_insert_color(struct rb_node *node, struct rb_root *root)
{
struct rb_node *parent, *gparent;
while ((parent = rb_parent(node)) && rb_is_red(parent))
{
gparent = rb_parent(parent);
if (parent == gparent->rb_left)
{
{
register struct rb_node *uncle = gparent->rb_right;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_right == node)
{
register struct rb_node *tmp;
__rb_rotate_left(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_right(gparent, root);
} else {
{
register struct rb_node *uncle = gparent->rb_left;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_left == node)
{
register struct rb_node *tmp;
__rb_rotate_right(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_left(gparent, root);
}
}
rb_set_black(root->rb_node);
}
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
struct rb_root *root)
{
struct rb_node *other;
while ((!node || rb_is_black(node)) && node != root->rb_node)
{
if (parent->rb_left == node)
{
other = parent->rb_right;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_left(parent, root);
other = parent->rb_right;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_right || rb_is_black(other->rb_right))
{
rb_set_black(other->rb_left);
rb_set_red(other);
__rb_rotate_right(other, root);
other = parent->rb_right;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_right);
__rb_rotate_left(parent, root);
node = root->rb_node;
break;
}
}
else
{
other = parent->rb_left;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_right(parent, root);
other = parent->rb_left;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_left || rb_is_black(other->rb_left))
{
rb_set_black(other->rb_right);
rb_set_red(other);
__rb_rotate_left(other, root);
other = parent->rb_left;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_left);
__rb_rotate_right(parent, root);
node = root->rb_node;
break;
}
}
}
if (node)
rb_set_black(node);
}
void rb_erase(struct rb_node *node, struct rb_root *root)
{
struct rb_node *child, *parent;
int color;
if (!node->rb_left)
child = node->rb_right;
else if (!node->rb_right)
child = node->rb_left;
else
{
struct rb_node *old = node, *left;
node = node->rb_right;
while ((left = node->rb_left) != NULL)
node = left;
if (rb_parent(old)) {
if (rb_parent(old)->rb_left == old)
rb_parent(old)->rb_left = node;
else
rb_parent(old)->rb_right = node;
} else
root->rb_node = node;
child = node->rb_right;
parent = rb_parent(node);
color = rb_color(node);
if (parent == old) {
parent = node;
} else {
if (child)
rb_set_parent(child, parent);
parent->rb_left = child;
node->rb_right = old->rb_right;
rb_set_parent(old->rb_right, node);
}
node->rb_parent_color = old->rb_parent_color;
node->rb_left = old->rb_left;
rb_set_parent(old->rb_left, node);
goto color;
}
parent = rb_parent(node);
color = rb_color(node);
if (child)
rb_set_parent(child, parent);
if (parent)
{
if (parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
}
else
root->rb_node = child;
color:
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
#ifdef __clang__
void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#else
inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#endif
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
+56
View File
@@ -0,0 +1,56 @@
/*
*** uWSGI, stripped down version of Linux rbtree ***
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
struct rb_node
{
unsigned long rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
/* The alignment might seem pointless, but allegedly CRIS needs it */
struct rb_root
{
struct rb_node *rb_node;
};
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(r) (!rb_color(r))
#define rb_is_black(r) rb_color(r)
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
void rb_insert_color(struct rb_node *, struct rb_root *);
void rb_erase(struct rb_node *, struct rb_root *);
#ifdef __clang__
void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
#else
inline void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
#endif
+29
View File
@@ -0,0 +1,29 @@
/* function written by Ben Taylor (found in the qemu-devel list) */
#include "../uwsgi.h"
time_t timegm(struct tm *t) {
time_t tl, tb;
struct tm *tg;
tl = mktime (t);
if (tl == -1) {
t->tm_hour--;
tl = mktime (t);
if (tl == -1)
return -1; /* can't deal with output from strptime */
tl += 3600;
}
tg = gmtime (&tl);
tg->tm_isdst = 0;
tb = mktime (tg);
if (tb == -1) {
tg->tm_hour--;
tb = mktime (tg);
if (tb == -1)
return -1; /* can't deal with output from gmtime */
tb += 3600;
}
return (tl - (tb - tl));
}
+229 -229
View File
@@ -47,7 +47,7 @@
#ifdef __BIG_ENDIAN__
static uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
#endif
@@ -64,7 +64,7 @@ typedef struct __attribute__((packed)) {
uint8_t modifier1;
uint16_t pktsize;
uint8_t modifier2;
} uwsgi_header ;
} uwsgi_header;
typedef struct {
array *extensions;
@@ -394,7 +394,7 @@ static int uwsgi_establish_connection(server *srv, handler_ctx *hctx) {
static void uwsgi_add_var(buffer *b, char * key, uint16_t keylen, char *val, uint16_t vallen) {
#ifdef __BIG_ENDIAN__
uint16_t uwlen ;
uint16_t uwlen;
uwlen = uwsgi_swap16(keylen);
buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, key, keylen);
@@ -405,19 +405,19 @@ static void uwsgi_add_var(buffer *b, char * key, uint16_t keylen, char *val, uin
buffer_append_memory(b, (char *) &vallen, 2); buffer_append_memory(b, val, vallen);
#endif
}
static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
size_t i;
char buf[32];
uwsgi_header *uh ;
uwsgi_header *uh;
const char *s;
#ifdef HAVE_IPV6
char b2[INET6_ADDRSTRLEN + 1];
#endif
connection *con = hctx->remote_conn;
server_socket *srv_sock = con->srv_socket;
@@ -436,57 +436,57 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
if (!buffer_is_empty(con->uri.query)) {
uwsgi_add_var(b, "QUERY_STRING", 12, con->uri.query->ptr, con->uri.query->used-1);
} else {
} else {
uwsgi_add_var(b, "QUERY_STRING", 12, "", 0);
}
}
s = get_http_version_name(con->request.http_version);
uwsgi_add_var(b, "SERVER_PROTOCOL", 15, (char *) s, strlen(s));
if (con->server_name->used) {
size_t len = con->server_name->used - 1;
char *colon = strchr(con->server_name->ptr, ':');
if (colon) len = colon - con->server_name->ptr;
size_t len = con->server_name->used - 1;
char *colon = strchr(con->server_name->ptr, ':');
if (colon) len = colon - con->server_name->ptr;
uwsgi_add_var(b, "SERVER_NAME", 11, con->server_name->ptr, len);
} else {
} else {
#ifdef HAVE_IPV6
s = inet_ntop(srv_sock->addr.plain.sa_family,
srv_sock->addr.plain.sa_family == AF_INET6 ?
(const void *) &(srv_sock->addr.ipv6.sin6_addr) :
(const void *) &(srv_sock->addr.ipv4.sin_addr),
b2, sizeof(b2)-1);
s = inet_ntop(srv_sock->addr.plain.sa_family,
srv_sock->addr.plain.sa_family == AF_INET6 ?
(const void *) &(srv_sock->addr.ipv6.sin6_addr) :
(const void *) &(srv_sock->addr.ipv4.sin_addr),
b2, sizeof(b2)-1);
#else
s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
#endif
uwsgi_add_var(b, "SERVER_NAME", 11, (char *)s, strlen(s));
}
}
LI_ltostr(buf,
#ifdef HAVE_IPV6
ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
#else
ntohs(srv_sock->addr.ipv4.sin_port)
ntohs(srv_sock->addr.ipv4.sin_port)
#endif
);
);
uwsgi_add_var(b, "SERVER_PORT", 11, buf, strlen(buf));
uwsgi_add_var(b, "REQUEST_URI", 11, con->request.orig_uri->ptr, con->request.orig_uri->used-1);
LI_ltostr(buf,
#ifdef HAVE_IPV6
ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
#else
ntohs(con->dst_addr.ipv4.sin_port)
ntohs(con->dst_addr.ipv4.sin_port)
#endif
);
);
uwsgi_add_var(b, "REMOTE_PORT", 11, buf, strlen(buf));
if (!buffer_is_empty(con->authed_user)) {
uwsgi_add_var(b, "REMOTE_USER", 11,
CONST_BUF_LEN(con->authed_user));
}
uwsgi_add_var(b, "REMOTE_USER", 11,
CONST_BUF_LEN(con->authed_user));
}
@@ -503,11 +503,11 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
}
}
else {
uwsgi_add_var(b, "SCRIPT_NAME", 11, "", 0) ;
uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr, strlen(con->uri.path->ptr)) ;
uwsgi_add_var(b, "SCRIPT_NAME", 11, "", 0);
uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr, strlen(con->uri.path->ptr));
}
for (i = 0; i < con->request.headers->used; i++) {
data_string *ds;
ds = (data_string *)con->request.headers->data[i];
@@ -524,7 +524,7 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
}
for (j = 0; j < ds->key->used - 1; j++) {
srv->tmp_buf->ptr[srv->tmp_buf->used++] = light_isalpha(ds->key->ptr[j]) ? ds->key->ptr[j] & ~32 : '_';
}
}
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
uwsgi_add_var(b, srv->tmp_buf->ptr, srv->tmp_buf->used-1, ds->value->ptr, ds->value->used-1);
}
@@ -546,19 +546,19 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
}
}
uh = (uwsgi_header *) b->ptr ;
uh->modifier1 = (uint8_t) 0 ;
uh = (uwsgi_header *) b->ptr;
uh->modifier1 = (uint8_t) 0;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16((uint16_t) b->used - 4) ;
uh->pktsize = uwsgi_swap16((uint16_t) b->used - 4);
#else
uh->pktsize = b->used - 4 ;
uh->pktsize = b->used - 4;
#endif
uh->modifier2 = (uint8_t) 0 ;
uh->modifier2 = (uint8_t) 0;
b->used++; /* fix size */
hctx->wb->bytes_in += b->used -1 ;
hctx->wb->bytes_in += b->used -1;
/* body */
if (con->request.content_length) {
@@ -576,37 +576,37 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
* */
switch (req_c->type) {
case FILE_CHUNK:
weHave = req_c->file.length - req_c->offset;
case FILE_CHUNK:
weHave = req_c->file.length - req_c->offset;
if (weHave > weWant) weHave = weWant;
if (weHave > weWant) weHave = weWant;
chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
req_c->offset += weHave;
req_cq->bytes_out += weHave;
req_c->offset += weHave;
req_cq->bytes_out += weHave;
hctx->wb->bytes_in += weHave;
hctx->wb->bytes_in += weHave;
break;
case MEM_CHUNK:
/* append to the buffer */
weHave = req_c->mem->used - 1 - req_c->offset;
break;
case MEM_CHUNK:
/* append to the buffer */
weHave = req_c->mem->used - 1 - req_c->offset;
if (weHave > weWant) weHave = weWant;
if (weHave > weWant) weHave = weWant;
b = chunkqueue_get_append_buffer(hctx->wb);
buffer_append_memory(b, req_c->mem->ptr + req_c->offset, weHave);
b->used++; /* add virtual \0 */
b = chunkqueue_get_append_buffer(hctx->wb);
buffer_append_memory(b, req_c->mem->ptr + req_c->offset, weHave);
b->used++; /* add virtual \0 */
req_c->offset += weHave;
req_cq->bytes_out += weHave;
req_c->offset += weHave;
req_cq->bytes_out += weHave;
hctx->wb->bytes_in += weHave;
hctx->wb->bytes_in += weHave;
break;
default:
break;
break;
default:
break;
}
offset += weHave;
@@ -677,29 +677,29 @@ static int uwsgi_response_parse(server *srv, connection *con, plugin_data *p, bu
copy_header = 1;
switch(key_len) {
case 4:
if (0 == strncasecmp(key, "Date", key_len)) {
con->parsed_response |= HTTP_DATE;
}
break;
case 8:
if (0 == strncasecmp(key, "Location", key_len)) {
con->parsed_response |= HTTP_LOCATION;
}
break;
case 10:
if (0 == strncasecmp(key, "Connection", key_len)) {
copy_header = 0;
}
break;
case 14:
if (0 == strncasecmp(key, "Content-Length", key_len)) {
con->response.content_length = strtol(value, NULL, 10);
con->parsed_response |= HTTP_CONTENT_LENGTH;
}
break;
default:
break;
case 4:
if (0 == strncasecmp(key, "Date", key_len)) {
con->parsed_response |= HTTP_DATE;
}
break;
case 8:
if (0 == strncasecmp(key, "Location", key_len)) {
con->parsed_response |= HTTP_LOCATION;
}
break;
case 10:
if (0 == strncasecmp(key, "Connection", key_len)) {
copy_header = 0;
}
break;
case 14:
if (0 == strncasecmp(key, "Content-Length", key_len)) {
con->response.content_length = strtol(value, NULL, 10);
con->parsed_response |= HTTP_CONTENT_LENGTH;
}
break;
default:
break;
}
if (copy_header) {
@@ -737,7 +737,7 @@ static int uwsgi_demux_response(server *srv, handler_ctx *hctx) {
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "sd",
"uwsgi - have to read:", b);
"uwsgi - have to read:", b);
}
if (b > 0) {
@@ -791,7 +791,7 @@ static int uwsgi_demux_response(server *srv, handler_ctx *hctx) {
/* enable chunked-transfer-encoding */
if (con->request.http_version == HTTP_VERSION_1_1 &&
!(con->parsed_response & HTTP_CONTENT_LENGTH)) {
!(con->parsed_response & HTTP_CONTENT_LENGTH)) {
con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
}
@@ -830,127 +830,127 @@ static handler_t uwsgi_write_request(server *srv, handler_ctx *hctx) {
int ret;
if (!host ||
(!host->host->used || !host->port)) return -1;
(!host->host->used || !host->port)) return -1;
switch(hctx->state) {
case UWSGI_STATE_INIT:
case UWSGI_STATE_INIT:
#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON)
if (strstr(host->host->ptr,":")) {
if (-1 == (hctx->fd = socket(AF_INET6, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
} else
if (strstr(host->host->ptr,":")) {
if (-1 == (hctx->fd = socket(AF_INET6, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
} else
#endif
{
if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
}
hctx->fde_ndx = -1;
{
if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
}
hctx->fde_ndx = -1;
srv->cur_fds++;
srv->cur_fds++;
fdevent_register(srv->ev, hctx->fd, uwsgi_handle_fdevent, hctx);
fdevent_register(srv->ev, hctx->fd, uwsgi_handle_fdevent, hctx);
if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
return HANDLER_ERROR;
}
/* fall through */
case UWSGI_STATE_CONNECT:
/* try to finish the connect() */
if (hctx->state == UWSGI_STATE_INIT) {
/* first round */
switch (uwsgi_establish_connection(srv, hctx)) {
case 1:
uwsgi_set_state(srv, hctx, UWSGI_STATE_CONNECT);
/* connection is in progress, wait for an event and call getsockopt() below */
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_WAIT_FOR_EVENT;
case -1:
/* if ECONNREFUSED choose another connection -> FIXME */
hctx->fde_ndx = -1;
if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
return HANDLER_ERROR;
default:
/* everything is ok, go on */
break;
}
} else {
int socket_error;
socklen_t socket_error_len = sizeof(socket_error);
/* we don't need it anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
/* fall through */
case UWSGI_STATE_CONNECT:
/* try to finish the connect() */
if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"getsockopt failed:", strerror(errno));
if (hctx->state == UWSGI_STATE_INIT) {
/* first round */
switch (uwsgi_establish_connection(srv, hctx)) {
case 1:
uwsgi_set_state(srv, hctx, UWSGI_STATE_CONNECT);
return HANDLER_ERROR;
/* connection is in progress, wait for an event and call getsockopt() below */
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_WAIT_FOR_EVENT;
case -1:
/* if ECONNREFUSED choose another connection -> FIXME */
hctx->fde_ndx = -1;
return HANDLER_ERROR;
default:
/* everything is ok, go on */
break;
}
} else {
int socket_error;
socklen_t socket_error_len = sizeof(socket_error);
/* we don't need it anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
/* try to finish the connect() */
if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"getsockopt failed:", strerror(errno));
return HANDLER_ERROR;
}
if (socket_error != 0) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"establishing connection failed:", strerror(socket_error),
"port:", hctx->host->port);
return HANDLER_ERROR;
}
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "s", "uwsgi - connect - delayed success");
}
}
if (socket_error != 0) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"establishing connection failed:", strerror(socket_error),
"port:", hctx->host->port);
return HANDLER_ERROR;
}
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "s", "uwsgi - connect - delayed success");
}
}
uwsgi_set_state(srv, hctx, UWSGI_STATE_PREPARE_WRITE);
/* fall through */
case UWSGI_STATE_PREPARE_WRITE:
uwsgi_create_env(srv, hctx);
uwsgi_set_state(srv, hctx, UWSGI_STATE_PREPARE_WRITE);
/* fall through */
case UWSGI_STATE_PREPARE_WRITE:
uwsgi_create_env(srv, hctx);
uwsgi_set_state(srv, hctx, UWSGI_STATE_WRITE);
uwsgi_set_state(srv, hctx, UWSGI_STATE_WRITE);
/* fall through */
case UWSGI_STATE_WRITE:;
ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
/* fall through */
case UWSGI_STATE_WRITE:;
ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
chunkqueue_remove_finished_chunks(hctx->wb);
chunkqueue_remove_finished_chunks(hctx->wb);
if (-1 == ret) { /* error on our side */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
if (-1 == ret) { /* error on our side */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
return HANDLER_WAIT_FOR_EVENT;
} else if (-2 == ret) { /* remote close */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed, remote connection close:", strerror(errno), errno);
return HANDLER_WAIT_FOR_EVENT;
} else if (-2 == ret) { /* remote close */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed, remote connection close:", strerror(errno), errno);
return HANDLER_WAIT_FOR_EVENT;
}
return HANDLER_WAIT_FOR_EVENT;
}
if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
uwsgi_set_state(srv, hctx, UWSGI_STATE_READ);
if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
uwsgi_set_state(srv, hctx, UWSGI_STATE_READ);
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
} else {
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
} else {
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_WAIT_FOR_EVENT;
}
return HANDLER_WAIT_FOR_EVENT;
}
return HANDLER_WAIT_FOR_EVENT;
case UWSGI_STATE_READ:
/* waiting for a response */
return HANDLER_WAIT_FOR_EVENT;
default:
log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
return HANDLER_ERROR;
return HANDLER_WAIT_FOR_EVENT;
case UWSGI_STATE_READ:
/* waiting for a response */
return HANDLER_WAIT_FOR_EVENT;
default:
log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
return HANDLER_ERROR;
}
return HANDLER_GO_ON;
@@ -1006,36 +1006,36 @@ SUBREQUEST_FUNC(mod_uwsgi_handle_subrequest) {
/* ok, create the request */
switch(uwsgi_write_request(srv, hctx)) {
case HANDLER_ERROR:
log_error_write(srv, __FILE__, __LINE__, "sbdd", "uwsgi-server disabled:",
host->host,
host->port,
hctx->fd);
case HANDLER_ERROR:
log_error_write(srv, __FILE__, __LINE__, "sbdd", "uwsgi-server disabled:",
host->host,
host->port,
hctx->fd);
/* disable this server */
host->is_disabled = 1;
host->disable_ts = srv->cur_ts;
/* disable this server */
host->is_disabled = 1;
host->disable_ts = srv->cur_ts;
uwsgi_connection_close(srv, hctx);
uwsgi_connection_close(srv, hctx);
/* reset the enviroment and restart the sub-request */
buffer_reset(con->physical.path);
con->mode = DIRECT;
/* reset the enviroment and restart the sub-request */
buffer_reset(con->physical.path);
con->mode = DIRECT;
joblist_append(srv, con);
joblist_append(srv, con);
/* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
* and hope that the childs will be restarted
*
*/
/* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
* and hope that the childs will be restarted
*
*/
return HANDLER_WAIT_FOR_FD;
case HANDLER_WAIT_FOR_EVENT:
return HANDLER_WAIT_FOR_EVENT;
case HANDLER_WAIT_FOR_FD:
return HANDLER_WAIT_FOR_FD;
default:
break;
return HANDLER_WAIT_FOR_FD;
case HANDLER_WAIT_FOR_EVENT:
return HANDLER_WAIT_FOR_EVENT;
case HANDLER_WAIT_FOR_FD:
return HANDLER_WAIT_FOR_FD;
default:
break;
}
if (con->file_started == 1) {
@@ -1053,7 +1053,7 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
if ((revents & FDEVENT_IN) &&
hctx->state == UWSGI_STATE_READ) {
hctx->state == UWSGI_STATE_READ) {
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "sd",
@@ -1061,29 +1061,29 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
}
switch (uwsgi_demux_response(srv, hctx)) {
case 0:
break;
case 1:
hctx->host->usage--;
case 0:
break;
case 1:
hctx->host->usage--;
/* we are done */
uwsgi_connection_close(srv, hctx);
/* we are done */
uwsgi_connection_close(srv, hctx);
joblist_append(srv, con);
return HANDLER_FINISHED;
case -1:
if (con->file_started == 0) {
/* nothing has been send out yet, send a 500 */
connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
con->http_status = 500;
con->mode = DIRECT;
} else {
/* response might have been already started, kill the connection */
connection_set_state(srv, con, CON_STATE_ERROR);
}
joblist_append(srv, con);
return HANDLER_FINISHED;
case -1:
if (con->file_started == 0) {
/* nothing has been send out yet, send a 500 */
connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
con->http_status = 500;
con->mode = DIRECT;
} else {
/* response might have been already started, kill the connection */
connection_set_state(srv, con, CON_STATE_ERROR);
}
joblist_append(srv, con);
return HANDLER_FINISHED;
joblist_append(srv, con);
return HANDLER_FINISHED;
}
}
@@ -1094,7 +1094,7 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
}
if (hctx->state == UWSGI_STATE_CONNECT ||
hctx->state == UWSGI_STATE_WRITE) {
hctx->state == UWSGI_STATE_WRITE) {
/* we are allowed to send something out
*
* 1. in a unfinished connect() call
@@ -1195,7 +1195,7 @@ static handler_t mod_uwsgi_check_extension(server *srv, connection *con, void *p
/* check extension in the form "/uwsgi_pattern" */
if (*(ext->key->ptr) == '/') {
if (strncmp(fn->ptr, ext->key->ptr, ct_len) == 0) {
path_info_offset = ct_len ;
path_info_offset = ct_len;
extension = ext;
break;
}
@@ -1320,7 +1320,7 @@ TRIGGER_FUNC(mod_uwsgi_trigger) {
data_uwsgi *host = (data_uwsgi *)extension->value->data[n];
if (!host->is_disabled ||
srv->cur_ts - host->disable_ts < 5) continue;
srv->cur_ts - host->disable_ts < 5) continue;
log_error_write(srv, __FILE__, __LINE__, "sbd",
"uwsgi - re-enabled:",
+217
View File
@@ -0,0 +1,217 @@
#include "uwsgi.h"
#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) {
if (pthread_mutexattr_init((pthread_mutexattr_t *) lock)) {
uwsgi_log("unable to allocate mutexattr structure\n");
exit(1);
}
if (pthread_mutexattr_setpshared((pthread_mutexattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share mutex\n");
exit(1);
}
if (pthread_mutex_init((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t), (pthread_mutexattr_t *) lock)) {
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
}
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) {
pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
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);
}
if (pthread_rwlockattr_setpshared((pthread_rwlockattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share rwlock\n");
exit(1);
}
if (pthread_rwlock_init((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t), (pthread_rwlockattr_t *) lock)) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
#endif
}
#endif
#ifdef UWSGI_LOCK_USE_UMTX
#include <machine/atomic.h>
#include <sys/umtx.h>
#define UWSGI_LOCK_SIZE sizeof(struct umtx)
#define UWSGI_RWLOCK_SIZE sizeof(struct umtx)
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
void uwsgi_lock_init(void *lock) {
umtx_init((struct umtx*) lock);
}
void uwsgi_lock(void *lock) {
umtx_lock(lock, 1);
}
void uwsgi_unlock(void *lock) {
umtx_unlock(lock, 1);
}
#endif
#ifdef UWSGI_LOCK_USE_OSX_SPINLOCK
#define UWSGI_LOCK_SIZE sizeof(OSSpinLock)
#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock)
void uwsgi_lock_init(void *lock) {
memset(lock, 0, sizeof(OSSpinLock));
}
void uwsgi_lock(void *lock) {
OSSpinLockLock((OSSpinLock *) lock);
}
void uwsgi_unlock(void *lock) {
OSSpinLockUnlock((OSSpinLock *) lock);
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
#endif
#ifdef UWSGI_LOCK_USE_FLOCK
#define UWSGI_LOCK_SIZE 8
#define UWSGI_RWLOCK_SIZE 8
void uwsgi_lock_init(void *lock) {
FILE *tf = tmpfile();
int fd;
if (!tf) {
uwsgi_error_open("temp lock file");
exit(1);
}
fd = fileno(tf);
memcpy(lock, &fd, sizeof(int));
}
void uwsgi_lock(void *lock) {
int fd;
memcpy(&fd, lock, sizeof(int));
if (flock(fd, LOCK_EX)) { uwsgi_error("flock()"); }
}
void uwsgi_unlock(void *lock) {
int fd;
memcpy(&fd, lock, sizeof(int));
if (flock(fd, LOCK_UN)) { uwsgi_error("flock()"); }
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
#endif
void *uwsgi_mmap_shared_lock() {
void *addr = NULL;
addr = mmap(NULL, UWSGI_LOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (addr == NULL) {
uwsgi_error("mmap()");
exit(1);
}
return addr;
}
void *uwsgi_mmap_shared_rwlock() {
void *addr = NULL;
addr = mmap(NULL, UWSGI_RWLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (addr == NULL) {
uwsgi_error("mmap()");
exit(1);
}
return addr;
}
+92 -62
View File
@@ -1,3 +1,4 @@
#define _NO_UWSGI_RB
#include "uwsgi.h"
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
@@ -31,150 +32,178 @@ void log_request(struct wsgi_request *wsgi_req) {
char mempkt[4096];
char logpkt[4096];
struct iovec logvec[4] ;
int logvecpos = 0 ;
struct iovec logvec[4];
int logvecpos = 0;
const char *msecs = "msecs";
const char *micros = "micros";
long int rt;
char *tsize = (char *) msecs;
#ifdef UWSGI_SENDFILE
char *msg1 = " via sendfile() ";
#endif
char *msg3 = " via route() ";
struct uwsgi_app *wi;
if (wsgi_req->do_not_log) return ;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi.wsgi_apps[wsgi_req->app_id];
wi = &uwsgi_apps[wsgi_req->app_id];
if (wi->requests > 0) {
app_req = wi->requests;
}
}
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
via = msg1;
}
#endif
// mark route() requests
if (wsgi_req->status == -17) {
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;
if (uwsgi.vhost) {
logvec[logvecpos].iov_base = wsgi_req->host ;
logvec[logvecpos].iov_len = wsgi_req->host_len ;
logvecpos++;
rt = (long int) (microseconds - microseconds2);
logvec[logvecpos].iov_base = " " ;
logvec[logvecpos].iov_len = 1 ;
logvecpos++;
if (uwsgi.log_micros) {
tsize = (char *) micros;
}
else {
rt /= 1000;
}
if (uwsgi.vhost) {
logvec[logvecpos].iov_base = wsgi_req->host;
logvec[logvecpos].iov_len = wsgi_req->host_len;
logvecpos++;
logvec[logvecpos].iov_base = " ";
logvec[logvecpos].iov_len = 1;
logvecpos++;
}
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
#ifndef UNBIT
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ",
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
#else
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ",
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
#endif
logvec[logvecpos].iov_base = mempkt ;
logvec[logvecpos].iov_len = rlen ;
logvec[logvecpos].iov_base = mempkt;
logvec[logvecpos].iov_len = rlen;
logvecpos++;
}
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld msecs%s(%.*s %d) %d headers in %d bytes (%d async switches on async core %d)\n",
(int) uwsgi.mypid,
wsgi_req->app_id,
app_req,
(unsigned long long ) uwsgi.workers[0].requests,
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
wsgi_req->remote_user_len, wsgi_req->remote_user,
wsgi_req->var_cnt,
wsgi_req->uh.pktsize,
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(unsigned long long) wsgi_req->response_size,
(long int) (microseconds - microseconds2) / 1000,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
wsgi_req->status,
wsgi_req->header_cnt,
wsgi_req->headers_size,
wsgi_req->async_switches, wsgi_req->async_id);
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n",
(int) uwsgi.mypid,
wsgi_req->app_id,
app_req,
(unsigned long long ) uwsgi.workers[0].requests,
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
wsgi_req->remote_user_len, wsgi_req->remote_user,
wsgi_req->var_cnt,
wsgi_req->uh.pktsize,
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(unsigned long long) wsgi_req->response_size,
rt, tsize,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
wsgi_req->status,
wsgi_req->header_cnt,
(unsigned long long) wsgi_req->headers_size,
wsgi_req->switches, wsgi_req->async_id);
logvec[logvecpos].iov_base = logpkt ;
logvec[logvecpos].iov_len = rlen ;
logvec[logvecpos].iov_base = logpkt;
logvec[logvecpos].iov_len = rlen;
// do not check for errors
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 ;
int procfd;
procfd = open("/proc/self/psinfo", O_RDONLY);
if (procfd >= 0) {
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024 ;
uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024 ;
*rss = (uint64_t) info.pr_rssize * 1024;
*vsz = (uint64_t) info.pr_size * 1024;
}
close(procfd);
}
#elif defined( __APPLE__)
#elif defined(__APPLE__)
/* darwin documentation says that the value are in pages, but they are bytes !!! */
struct task_basic_info t_info;
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size;
uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size;
*rss = t_info.resident_size;
*vsz = t_info.virtual_size;
}
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
kvm_t *kv;
int cnt;
#if defined(__FreeBSD__)
kv = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, NULL);
#elif defined(__NetBSD__) || defined(__OpenBSD__)
kv = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
#else
kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
#endif
if (kv) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
struct kinfo_proc *kproc;
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
if (kproc && cnt > 0) {
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
*vsz = kproc->ki_size;
*rss = kproc->ki_rssize * uwsgi.page_size;
}
#elif defined(__NetBSD__) || defined(__OpenBSD__)
struct kinfo_proc2 *kproc2;
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
if (kproc2 && cnt > 0) {
#ifdef __OpenBSD__
uwsgi.workers[uwsgi.mywid].vsz_size = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
*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
@@ -183,14 +212,15 @@ void get_memusage() {
#elif defined(__HAIKU__)
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
}
+241
View File
@@ -0,0 +1,241 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct wsgi_request *threaded_current_wsgi_req() {
return pthread_getspecific(uwsgi.tur_key);
}
struct wsgi_request *simple_current_wsgi_req() {
return uwsgi.wsgi_req;
}
void uwsgi_register_loop(char *name, void *loop) {
if (uwsgi.loops_cnt >= MAX_LOOPS) {
uwsgi_log("you can define %d loops at max\n", MAX_LOOPS);
exit(1);
}
uwsgi.loops[uwsgi.loops_cnt].name = name;
uwsgi.loops[uwsgi.loops_cnt].loop = loop;
uwsgi.loops_cnt++;
}
void *uwsgi_get_loop(char *name) {
int i;
for (i = 0; i < uwsgi.loops_cnt; i++) {
if (!strcmp(name, uwsgi.loops[i].name)) {
return uwsgi.loops[i].loop;
}
}
return NULL;
}
void *simple_loop(void *arg1) {
long core_id = (long) arg1;
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
int i;
#ifdef UWSGI_THREADING
//PyThreadState *pts;
sigset_t smask;
if (uwsgi.threads > 1) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
}
}
#endif
// initialize the main event queue to monitor sockets
int main_queue = event_queue_init();
uwsgi_add_sockets_to_queue(main_queue);
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(main_queue, uwsgi.signal_socket);
event_queue_add_fd_read(main_queue, uwsgi.my_signal_socket);
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
wsgi_req_setup(wsgi_req, core_id, NULL);
if (wsgi_req_accept(main_queue, wsgi_req)) {
continue;
}
if (wsgi_req_recv(wsgi_req)) {
uwsgi_destroy_request(wsgi_req);
continue;
}
uwsgi_close_request(wsgi_req);
}
// end of the loop
if (uwsgi.workers[uwsgi.mywid].destroy && uwsgi.workers[0].pid > 0) {
#ifdef __APPLE__
kill(uwsgi.workers[0].pid, SIGTERM);
#else
if (uwsgi.propagate_touch) {
kill(uwsgi.workers[0].pid, SIGHUP);
}
else {
gracefully_kill(0);
}
#endif
}
return NULL;
}
#ifdef UWSGI_ZEROMQ
void *zeromq_loop(void *arg1) {
sigset_t smask;
int i;
long core_id = (long) arg1;
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
uwsgi.zeromq_recv_flag = 0;
zmq_pollitem_t zmq_poll_items[3];
char uwsgi_signal;
if (uwsgi.threads > 1) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
if (tmp_zmq_pull == NULL) {
uwsgi_error("zmq_socket()");
exit(1);
}
if (zmq_connect(tmp_zmq_pull, uwsgi.zmq_receiver) < 0) {
uwsgi_error("zmq_connect()");
exit(1);
}
pthread_setspecific(uwsgi.zmq_pull, tmp_zmq_pull);
}
}
if (uwsgi.signal_socket > -1) {
zmq_poll_items[0].socket = pthread_getspecific(uwsgi.zmq_pull);
zmq_poll_items[0].fd = -1;
zmq_poll_items[0].events = ZMQ_POLLIN;
zmq_poll_items[1].socket = NULL;
zmq_poll_items[1].fd = uwsgi.signal_socket;
zmq_poll_items[1].events = ZMQ_POLLIN;
zmq_poll_items[2].socket = NULL;
zmq_poll_items[2].fd = uwsgi.my_signal_socket;
zmq_poll_items[2].events = ZMQ_POLLIN;
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
wsgi_req_setup(wsgi_req, core_id, NULL);
uwsgi.edge_triggered = 1;
wsgi_req->socket = uwsgi.zmq_socket;
if (uwsgi.signal_socket > -1) {
if (zmq_poll(zmq_poll_items, 3, -1) < 0) {
uwsgi_error("zmq_poll()");
continue;
}
if (zmq_poll_items[1].revents & ZMQ_POLLIN) {
if (read(uwsgi.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);
}
}
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);
}
}
continue;
}
if (zmq_poll_items[2].revents & ZMQ_POLLIN) {
if (read(uwsgi.my_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);
}
}
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);
}
}
continue;
}
if (zmq_poll_items[0].revents & ZMQ_POLLIN) {
wsgi_req->poll.fd = wsgi_req->socket->proto_accept(wsgi_req, uwsgi.zmq_socket->fd);
}
}
else {
wsgi_req->poll.fd = wsgi_req->socket->proto_accept(wsgi_req, uwsgi.zmq_socket->fd);
}
if (wsgi_req->poll.fd >= 0) {
wsgi_req_recv(wsgi_req);
}
uwsgi_close_request(wsgi_req);
}
// end of the loop
return NULL;
}
#endif
+1628
View File
File diff suppressed because it is too large Load Diff
+412
View File
@@ -0,0 +1,412 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void worker_wakeup() {}
void master_check_cluster_nodes() {
int i;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_STATIC && ucn->status == UWSGI_NODE_FAILED) {
// should i retry ?
if (uwsgi.master_cycles % ucn->errors == 0) {
if (!uwsgi_ping_node(i, uwsgi.wsgi_req)) {
ucn->status = UWSGI_NODE_OK;
uwsgi_log("re-enabled cluster node %d/%s\n", i, ucn->name);
}
else {
ucn->errors++;
}
}
}
else if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_DYNAMIC) {
// if the last_seen attr is higher than 30 secs ago, mark the node as dead
if ((uwsgi.current_time - ucn->last_seen) > 30) {
uwsgi_log_verbose("no presence announce in the last 30 seconds by node %s, i assume it is dead.\n", ucn->name);
ucn->name[0] = 0;
}
}
}
}
void uwsgi_fixup_fds(int wid, int muleid) {
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;
pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
if (pid == 0) {
signal(SIGWINCH, worker_wakeup);
signal(SIGTSTP, worker_wakeup);
uwsgi.mywid = wid;
uwsgi.mypid = getpid();
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
// do not reset worker counters on reload !!!
//uwsgi.workers[uwsgi.mywid].requests = 0;
// ...but maintain a delta counter (yes this is racy in multithread)
uwsgi.workers[uwsgi.mywid].delta_requests = 0;
//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
uwsgi.workers[uwsgi.mywid].cheaped = 0;
uwsgi.workers[uwsgi.mywid].busy = 0;
uwsgi.workers[uwsgi.mywid].suspended = 0;
uwsgi.workers[uwsgi.mywid].sig = 0;
// reset the apps count with a copy from the master
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
uwsgi_fixup_fds(wid, 0);
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
if (uwsgi.master_process) {
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
}
}
return 1;
}
else if (pid < 1) {
uwsgi_error("fork()");
}
else {
if (respawns > 0) {
uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
}
else {
uwsgi_log("spawned uWSGI worker %d (pid: %d, cores: %d)\n", wid, pid, uwsgi.cores);
}
}
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi.current_time = now;
uwsgi_cron_delta = localtime(&uwsgi.current_time);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = ucron->minute;
uc_hour = ucron->hour;
uc_day = ucron->day;
uc_month = ucron->month;
uc_week = ucron->week;
if (ucron->minute == -1)
uc_minute = uwsgi_cron_delta->tm_min;
if (ucron->hour == -1)
uc_hour = uwsgi_cron_delta->tm_hour;
if (ucron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (ucron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
int run_task = 0;
// mday and wday are ORed
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 (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, signal it ?
if (uwsgi.current_time - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = uwsgi.current_time;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uwsgi.current_time = now;
uwsgi_cron_delta = localtime(&uwsgi.current_time);
if (!uwsgi_cron_delta) {
uwsgi_error("localtime()");
return;
}
while (current_cron) {
uc_minute = current_cron->minute;
uc_hour = current_cron->hour;
uc_day = current_cron->day;
uc_month = current_cron->month;
uc_week = current_cron->week;
if (current_cron->minute == -1)
uc_minute = uwsgi_cron_delta->tm_min;
if (current_cron->hour == -1)
uc_hour = uwsgi_cron_delta->tm_hour;
if (current_cron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (current_cron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (current_cron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
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 (run_task == 1) {
// date match, run command ?
if (uwsgi.current_time - current_cron->last_job > 60) {
//call command
if (current_cron->command) {
if (uwsgi_run_command(current_cron->command) >=0) {
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
}
}
current_cron->last_job = uwsgi.current_time;
}
}
current_cron = current_cron->next;
}
}
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
void uwsgi_send_stats(int fd) {
int i,j;
struct sockaddr_un client_src;
struct uwsgi_app *ua;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
#ifdef __linux__
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
#endif
stats_send_llu("\"load\": %llu,\n", uwsgi.shared->load);
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
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);
}

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