Compare commits

...
770 Commits
Author SHA1 Message Date
roberto@quantal64 a932937adf use new uwsgi_buffer structure for zeromq headers 2012-09-01 11:41:40 +02:00
roberto@quantal64 23bd924ace fixed remote cache_get for non existent keys 2012-09-01 11:34:44 +02:00
roberto@quantal64 e8f39685cc added the router_http plugin 2012-09-01 11:17:20 +02:00
roberto@quantal64 2122bacb33 fixed router_uwsgi in http/fastcgi and buffered modes 2012-09-01 08:18:43 +02:00
roberto@quantal64 3cb3c83442 added --if-opt/--if-not-opt 2012-09-01 07:45:28 +02:00
roberto@quantal64 d552d5257c add support for value check in if-env/if-not-env 2012-09-01 07:38:29 +02:00
roberto@quantal64 0aff486a73 added --spooler-external 2012-09-01 07:23:16 +02:00
roberto@quantal64 b887f3fc27 removed regexp-mount 2012-08-31 12:18:39 +02:00
roberto@freebsd64 b30e2c4ad8 added cpu affinity support for freebsd 2012-08-31 11:46:53 +02:00
roberto@openindiana64 040b17e5eb openindiana 64bit fixes 2012-08-31 11:08:51 +02:00
roberto@quantal64 770114a21c solaris fixes 2012-08-31 11:01:12 +02:00
roberto@quantal64 2864568f09 oops, forgot to remove debug :P 2012-08-31 10:49:13 +02:00
roberto@quantal64 56eaa88dd7 completed socket initialization refactoring 2012-08-31 10:47:33 +02:00
roberto@quantal64 bb54b90640 refactored mapped sockets and cpu affinity 2012-08-31 09:43:02 +02:00
roberto@quantal64 34502eeabe moved workers shared memory initialization to init.c 2012-08-31 09:34:01 +02:00
roberto@quantal64 ae90f29fa3 refactored mules and farms initialization 2012-08-31 09:30:33 +02:00
roberto@quantal64 1eeda4faaa moved buffer, post_buffers and hvec to shared uwsgi_core 2012-08-31 09:18:02 +02:00
roberto@quantal64 18046c976e first phase of main() refactory 2012-08-31 08:42:56 +02:00
roberto@quantal64 530bf85cf9 get rid of another series of gettimeofday 2012-08-30 20:23:32 +02:00
roberto@quantal64 5261a9fed5 report per-core requests in stats 2012-08-30 20:16:34 +02:00
roberto@quantal64 26d0d8dfdc improved clock usage in logging subsystem 2012-08-30 20:11:27 +02:00
roberto@quantal64 eddf494b07 big commit for allowing full access to workers/cores/requests data from the api/stats 2012-08-30 16:54:13 +02:00
roberto@quantal64 689a4ef6d4 added support for lua table in the WSAPI plugin, patch by Aaron B. 2012-08-30 08:54:25 +02:00
roberto@quantal64 9398304c60 fixed fastcgi support for response bigger than 64k 2012-08-28 18:31:45 +02:00
roberto@quantal64 e904f9f76e improved gevent graceful reload 2012-08-27 17:52:56 +02:00
roberto@quantal64 5df34ecfd8 fixed nanoseconds/microseconds conversion 2012-08-26 10:33:00 +02:00
roberto@quantal64 a96951880d added router_rewrite plugin 2012-08-26 09:11:42 +02:00
roberto@quantal64 c4425627ee added clock realtime plugin 2012-08-25 17:23:38 +02:00
roberto@quantal64 7033a0b5d2 added monotonic clock plugin 2012-08-25 17:15:58 +02:00
roberto@quantal64 a491be3975 added --clock and --clock-list options 2012-08-25 17:04:28 +02:00
roberto@quantal64 c664ac21bb added uwsgi pluggable clock infrastructure 2012-08-25 16:54:49 +02:00
roberto@quantal64 2205c0c33d fixed goodbye_cruel_world in gevent mode 2012-08-24 10:55:30 +02:00
roberto@quantal64 e9c54a4228 fixed emperor blacklist removal 2012-08-24 10:39:43 +02:00
roberto@quantal64 a38427944c fixed a series of typo 2012-08-23 17:06:03 +02:00
roberto@quantal64 124db58683 applied big Lukasz patch for busyness cheaper algo and improved carbon support 2012-08-23 17:02:15 +02:00
roberto@quantal64 aa075f9aaa added listing options for showing internal loaded features 2012-08-23 16:51:56 +02:00
roberto@quantal64 305f8a0667 auto-formatting of json output 2012-08-23 12:46:26 +02:00
roberto@quantal64 9d8238a2bb fixed json output 2012-08-23 11:37:15 +02:00
roberto@quantal64 3fccd4c5c0 fix early error reporting 2012-08-23 11:21:44 +02:00
roberto@quantal64 1a330e49f6 fixed reference counting in wrr 2012-08-20 20:37:02 +02:00
roberto@quantal64 7c09f294bf added content-length report on http body reading errors 2012-08-20 20:32:58 +02:00
roberto@quantal64 22c520043f improved/fixed wrr 2012-08-19 07:53:03 +02:00
roberto@quantal64 859c1eed0e try to fix subscription wrr 2012-08-18 20:40:28 +02:00
roberto@quantal64 e942668613 fixed a typo 2012-08-14 15:35:11 +02:00
roberto@quantal64 169c3a7970 added debug logging for busyness algo 2012-08-14 14:29:25 +02:00
roberto@quantal64 22892ce550 fixed carbon no_workers check 2012-08-14 14:15:35 +02:00
roberto@quantal64 2f5132c539 supports partial-write in linux sendfile 2012-08-13 19:08:17 +02:00
roberto@quantal64 d737bd0d35 applied Aarni Koskela patch for mod_uwsgi 2012-08-13 10:32:05 +02:00
roberto@quantal64 665958f1f5 fixed https write queue 2012-08-10 14:59:25 +02:00
roberto@quantal64 4bf86892ab another fix for write queue [2] 2012-08-10 13:04:26 +02:00
roberto@quantal64 bab89d1152 another fix for write queue 2012-08-10 12:49:23 +02:00
roberto@quantal64 4322c3b538 added support for better/true non-blocking write in http router 2012-08-10 11:12:59 +02:00
roberto@quantal64 9fabfd77ee added --so-keepalive 2012-08-10 09:11:01 +02:00
roberto@quantal64 94ce4187c9 added pam plugin 2012-08-09 18:21:02 +02:00
roberto@quantal64 e78388e287 added limit-nproc 2012-08-09 17:31:11 +02:00
roberto@quantal64 e3014bd0dc prepare for before_privileges_drop plugins 2012-08-09 17:25:05 +02:00
roberto@quantal64 36c79b100e improved build system reporting (by Łukasz Mierzwa) 2012-08-09 15:00:19 +02:00
roberto@quantal64 f6641aeca1 honour --add-header in php,rack and psgi plugins 2012-08-09 11:41:51 +02:00
roberto@quantal64 278187e738 added experimental 'busyness' cheaper algo 2012-08-09 11:06:45 +02:00
roberto@quantal64 668831d437 added --cheaper-initial 2012-08-09 07:36:41 +02:00
unbit 340f1e24ae Merge pull request #10 from xtfxme/defect-emperor-amqp-transient-queues
AMQP Emperor: Auto-delete transient queues
2012-07-26 22:12:55 -07:00
C Anthony Risinger 44e773f737 AMQP Emperor: Auto-delete transient queues
uWSGI requests a transient queue but does not set the `auto-delete` bit
resulting in unbounded creation of new -> abandonded queues.
2012-07-25 12:19:35 -05:00
roberto@quantal64 03aae347b0 allows ugreen with threads 2012-07-22 11:43:39 +02:00
roberto@mrspurr e393f36f0a fixed env clear in async mode 2012-07-22 11:21:08 +02:00
roberto@quantal64 b169193723 --json must be IMMEDIATE 2012-07-20 08:56:01 +02:00
roberto@quantal64 2de9b9d5c7 try to fix paste usage in python 3 2012-07-19 07:41:00 +02:00
roberto@quantal64 bde43ee7b2 added python logger 2012-07-17 11:20:16 +02:00
roberto@quantal64 4921e676d3 allows multiple loggers for the same instance 2012-07-17 10:40:39 +02:00
roberto@quantal64 b76a47231c fixed per-request chdir management 2012-07-17 10:06:38 +02:00
roberto@quantal64 2561d26b95 added --privileged-binary-patch-arg and --unprivileged-binary-patch-arg [2] 2012-07-16 12:22:28 +02:00
roberto@quantal64 4492bf517b added --privileged-binary-patch-arg and --unprivileged-binary-patch-arg 2012-07-16 12:12:47 +02:00
roberto@quantal64 c195e7e8ea added --privileged-binary-patch and --unprivileged-binary-patch, useful for running non-uwsgi apps using the Emperor 2012-07-16 11:55:40 +02:00
roberto@quantal64 667b418e28 improved IOVEC management in http router 2012-07-15 07:53:27 +02:00
roberto@quantal64 0ee7ba6aae save mountpoint,chdir and touch-reload valies of dynamic apps in shared memory 2012-07-13 21:44:16 +02:00
roberto@quantal64 8a656908e1 improved emperor stats and added emperormon.ru 2012-07-13 16:52:11 +02:00
roberto@quantal64 4f05d04c7f export blacklist in emperor stats 2012-07-13 16:18:36 +02:00
roberto@quantal64 c0fcbb7b85 fixed casting in wsgi.input (web3/pump part) 2012-07-13 13:23:30 +02:00
roberto@quantal64 fe36479d5c fixed casting in wsgi.input 2012-07-13 13:00:17 +02:00
roberto@quantal64 849829d6c0 correctly raise exception when the first iteration in a generator fails 2012-07-13 08:11:14 +02:00
roberto@quantal64 a77e9d3241 support for dir:// and glob:// in emperor configs 2012-07-12 20:44:43 +02:00
roberto@quantal64 fe26d41215 added support for vassal's heartbeat 2012-07-12 14:39:45 +02:00
roberto@quantal64 4d86712d4d if --harakiri and --py-tracebacker are both specified you will get a python traceback on harakiri 2012-07-12 05:25:24 +02:00
roberto@quantal64 006197a7c3 re-added support for emperor_amqp 2012-07-11 08:32:49 +02:00
roberto@quantal64 434aeb9761 improved emperor_pg plugin 2012-07-11 06:48:48 +02:00
roberto@quantal64 b1ca831269 fixed vassals removal 2012-07-11 06:43:45 +02:00
roberto@quantal64 8fc9b14db4 smarter config management in the emperor 2012-07-10 18:16:20 +02:00
roberto@quantal64 36cc5434fd added emperor postgresql plugin 2012-07-10 17:57:01 +02:00
roberto@quantal64 70c30a62e6 added --emperor-pidfile 2012-07-10 14:46:13 +02:00
roberto@quantal64 56827398d1 reindented the emperor and added some comment 2012-07-10 12:59:51 +02:00
roberto@quantal64 bd5cc93872 added preliminary support for vassal's heartbeat 2012-07-10 12:46:47 +02:00
roberto@quantal64 88be144a81 fixed a race condition in graceful reload 2012-07-10 12:34:57 +02:00
roberto@quantal64 8046194696 added --emperor-freq 2012-07-10 12:07:46 +02:00
roberto@quantal64 3012cb6bf9 new throttling system for the emperor 2012-07-10 11:53:34 +02:00
roberto@quantal64 cf74ccaaef new emperor infrastructure
--HG--
rename : lib/amqp.c => plugins/emperor_amqp/amqp.c
2012-07-10 09:32:50 +02:00
roberto@quantal64 8749053f30 removed websockets.py 2012-07-09 19:12:37 +02:00
roberto@quantal64 8368ce0e4c moved config files example to examples/ dir
--HG--
rename : debug.ini => examples/debug.ini
rename : fibers.yml => examples/fibers.yml
rename : heavytest.ini => examples/heavytest.ini
rename : logic.ini => examples/logic.ini
rename : mega.xml => examples/mega.xml
rename : multi.ini => examples/multi.ini
rename : multi.xml => examples/multi.xml
rename : protected.ini => examples/protected.ini
rename : sites.xml => examples/sites.xml
rename : uwsgi.xml => examples/uwsgi.xml
rename : welcome.ini => examples/welcome.ini
rename : werkzeug.yml => examples/werkzeug.yml
rename : werkzeug_strict.yml => examples/werkzeug_strict.yml
rename : zmqgevent.ini => examples/zmqgevent.ini
2012-07-09 19:10:47 +02:00
roberto@quantal64 c6c2157c1d moved all of the c files to the core directory
--HG--
rename : async.c => core/async.c
rename : cache.c => core/cache.c
rename : cluster.c => core/cluster.c
rename : event.c => core/event.c
rename : gateway.c => core/gateway.c
rename : ini.c => core/ini.c
rename : json.c => core/json.c
rename : ldap.c => core/ldap.c
rename : lock.c => core/lock.c
rename : logging.c => core/logging.c
rename : loop.c => core/loop.c
rename : mule.c => core/mule.c
rename : notify.c => core/notify.c
rename : plugins.c => core/plugins.c
rename : protocol.c => core/protocol.c
rename : queue.c => core/queue.c
rename : rb_timers.c => core/rb_timers.c
rename : regexp.c => core/regexp.c
rename : routing.c => core/routing.c
rename : rpc.c => core/rpc.c
rename : sendfile.c => core/sendfile.c
rename : setup_utils.c => core/setup_utils.c
rename : signal.c => core/signal.c
rename : skel.c => core/skel.c
rename : snmp.c => core/snmp.c
rename : socket.c => core/socket.c
rename : spooler.c => core/spooler.c
rename : sqlite3.c => core/sqlite3.c
rename : stats.c => core/stats.c
rename : subscription.c => core/subscription.c
rename : utils.c => core/utils.c
rename : xmlconf.c => core/xmlconf.c
rename : yaml.c => core/yaml.c
2012-07-09 19:08:51 +02:00
roberto@quantal64 4740c81280 updated uwsgiconfig.py 2012-07-09 19:01:13 +02:00
roberto@quantal64 f4f6e628b8 moved uwsgi.c to core
--HG--
rename : uwsgi.c => core/uwsgi.c
2012-07-09 19:00:39 +02:00
roberto@quantal64 55239207f4 started moving sources to core directory
--HG--
rename : emperor.c => core/emperor.c
rename : master.c => core/master.c
rename : master_utils.c => core/master_utils.c
2012-07-09 19:00:08 +02:00
unbit d912e951a0 Merge pull request #8 from skywave/zeromq3
Make compatible with zeroMQ-3.x
2012-07-08 22:24:16 -07:00
skywave b0c3184565 Make compatible with zeroMQ-3.x
In the 3.x versions of ZeroMQ some definitions were refactored, this
commit makes uwsgi compatible again with newer versions. Without this
patch compiliation of uwsgi will fail
2012-07-09 00:19:30 +02:00
roberto@quantal64 b3c9c5057f fixed a typo and an fd leak spotted by riccardo 2012-07-08 21:31:09 +02:00
roberto@quantal64 1c022ee01d added --lazy-apps as a more 'gentle' --lazy mode 2012-07-08 21:25:48 +02:00
roberto@quantal64 18589d86ff report system info on startup 2012-07-08 21:19:50 +02:00
roberto@quantal64 5a7b5d37b4 fix #138 2012-07-08 20:18:56 +02:00
roberto@quantal64 3e2115aa21 added proto logvar 2012-07-08 19:10:40 +02:00
roberto@quantal64 3f4a041e07 added time and ctime logvars 2012-07-08 19:03:44 +02:00
roberto@quantal64 59eb46895c first part of --logformat support 2012-07-08 18:29:51 +02:00
roberto@quantal64 2f452cc6f6 preliminary support for --worker-mount 2012-07-08 15:47:05 +02:00
roberto@quantal64 770bb1d122 reindented master.c 2012-07-08 07:20:31 +02:00
roberto@quantal64 4a036fb2ad refactored snmp and udp master support 2012-07-08 07:17:52 +02:00
roberto@quantal64 2ef72ad80f refactored master emperor manager 2012-07-08 07:06:22 +02:00
roberto@quantal64 c9088067d5 refactored master snapshot restore 2012-07-08 07:02:45 +02:00
roberto@quantal64 6f772f77c9 reindented master.c 2012-07-08 07:00:22 +02:00
roberto@quantal64 2430617427 refactored master mercy 2012-07-08 07:00:00 +02:00
roberto@quantal64 28888720bd refactored clusterbuf allocation 2012-07-08 06:52:32 +02:00
roberto@quantal64 32a1ba27ba refactored deadlock detector 2012-07-08 06:44:06 +02:00
roberto@quantal64 b750ee2aa3 fixed lazy reload + cheaper 2012-07-08 06:13:53 +02:00
roberto@quantal64 86aa5190b1 better waitpid usage 2012-07-08 05:07:07 +02:00
roberto@quantal64 55288af936 fixed async + threading support 2012-07-07 10:04:50 +02:00
roberto@quantal64 827d2e461b fixed cheap mode for routers 2012-07-01 16:56:30 +02:00
roberto@sirius 8400bcf8bc improved subscription system using a hash table 2012-07-01 14:27:15 +02:00
roberto@wuantal64 4dcfde541a added --rb-threads option and postinit_apps hook 2012-06-27 16:51:25 +02:00
roberto@quantal64 cf04a87688 preparing for ruby threads: add warnings if native threads are enabled 2012-06-27 16:24:55 +02:00
roberto@quantal64 65f88593b8 report mule pid when it cripples 2012-06-26 07:59:35 +02:00
roberto@quantal64 dbdf453724 fixed mongrel2 tnetstring JSON method 2012-06-25 13:41:33 +02:00
roberto@quantal64 e7f157b102 added an example config file for zeromq+gevent 2012-06-24 13:30:06 +02:00
roberto@quantal64 d30a5a4a50 little optimization for mongrel2 + gevent 2012-06-24 11:59:52 +02:00
roberto@quantal64 b0cfb0ca1f fixed a typo in gevent plugin 2012-06-24 08:59:58 +02:00
roberto@quantal64 c150f8c793 improved zeromq + threading 2012-06-23 19:54:11 +02:00
roberto@quantal64 46733c0673 started refactory of zeromq protocol handler 2012-06-23 16:59:17 +02:00
roberto@quantal64 772d1c8a5a refactored a bunch of initializing functions and allows zeromq+gevent 2012-06-23 10:00:43 +02:00
roberto@goyle 3f4bbdebe5 added a test for gevent+spooler 2012-06-21 10:52:36 +02:00
roberto@goyle 0394977658 allows greenlets to send jobs to the spooler 2012-06-21 10:24:28 +02:00
roberto@quantal64 33c9d01baf goodbye_cruel_world hook for gevent 2012-06-19 08:00:32 +02:00
roberto@quantal64 1367ee1e40 reporting correct python threads status 2012-06-17 19:08:17 +02:00
roberto@quantal64 8ddeed80cf the http router is now websocket friendly 2012-06-17 18:06:53 +02:00
roberto@quantal64 e796a57f14 fixed WSGI headers sending in websocket mode 2012-06-17 13:10:34 +02:00
roberto@sirius 839962370a trying to avoid OSX mess with universal binaries 2012-06-13 14:59:07 +02:00
roberto@quantal64 0a993c10e0 improved (and stabilized) auto-snapshotting 2012-06-13 12:44:36 +02:00
roberto@quantal64 aaaef51f2a be sure brained/patched mules are killed when the master dies 2012-06-13 11:04:35 +02:00
roberto@quantal64 8e10efd027 added options for setting Expires based on REQUEST_URI and PATH_INFO 2012-06-13 10:53:21 +02:00
roberto@quantal64 13c112430d fixed logfile inheritance 2012-06-13 08:04:05 +02:00
roberto@quantal64 05a40e786c fixed a typo 2012-06-12 14:36:48 +02:00
roberto@quantal64 64e05bed38 added support for graceful reloads in gevent plugin 2012-06-11 09:33:16 +02:00
roberto@quantal64 6f39909cd4 added support for multiple sockets in gevent plugin 2012-06-11 08:44:56 +02:00
roberto@mrspurr b4e41532eb dynamic modifier management for the rack plugin 2012-06-10 11:50:14 +02:00
roberto@mrspurr 4ca33d3f88 moved lib/rbtree.h to uwsgi.h 2012-06-10 11:28:32 +02:00
roberto@quantal64 b40cdfbe66 fixed spooler with chdir 2012-06-08 20:55:15 +02:00
roberto@quantal64 e775b18fd5 added http-to-https 2012-06-07 11:38:04 +02:00
roberto@quantal64 b1506712c9 added uwsgi.cache_clear api function 2012-06-07 08:02:29 +02:00
roberto@quantal64 7af2be5f1c reindenting a bunch of messy files 2012-06-06 09:32:34 +02:00
roberto@quantal64 27b1c63563 allows ipv6 socket to be inherited 2012-06-06 09:15:35 +02:00
roberto@quantal64 7b8fbf0f96 added binder.pl 2012-06-05 16:52:03 +02:00
roberto@quantal64 a748686349 added support for fd:// syntax in sockets options 2012-06-05 16:51:03 +02:00
roberto@quantal64 e2a0173d36 ready for the first 1.3 snapshot 2012-06-03 18:51:47 +02:00
roberto@quantal64 4d25e05986 fixed ruby rvm support 2012-06-03 18:32:05 +02:00
roberto@quantal64 c2091c52eb completed the python tracebacker 2012-06-03 10:58:34 +02:00
roberto@quantal64 d74928fa0f added @harakiri decorator for new uwsgi.set_user_harakiri option 2012-06-02 13:46:37 +02:00
roberto@quantal64 dc8bf75b73 implemented user defined harakiri via uwsgi.set_user_harakiri 2012-06-02 11:24:55 +02:00
roberto@quantal64 cc5ae8bf31 fixed a leak in uwsgi.workers() 2012-06-02 09:59:21 +02:00
roberto@quantal64 f62f7f9282 thread-safe wsgi env behaviour 2012-06-02 09:43:24 +02:00
roberto@quantal64 c3cbcbb0d5 added --wsgi-env-behaviour for choosing the WSGI environ allocator/destroyer policy 2012-06-02 07:37:52 +02:00
roberto@quantal64 ec2889b202 fixed python3 compilation 2012-06-01 19:57:07 +02:00
roberto@quantal64 474d04d6a1 added a security check in the http router 2012-05-31 18:53:09 +02:00
roberto@quantal64 18f535413f fixed signed subscription filenames 2012-05-31 16:25:07 +02:00
roberto@quantal64 85ca80f7ea added --extra-plugin build option for simplified plugin development 2012-05-31 15:24:07 +02:00
roberto@quantal64 097d10439d print cflags to stdout 2012-05-31 13:36:53 +02:00
roberto@quantal64 209d96131d fixed psgi post buffering in memory 2012-05-31 13:23:00 +02:00
roberto@quantal64 4baed7b7b8 added support for --cflags 2012-05-31 10:03:17 +02:00
roberto@precise64 9f02286018 fixed a typo in psgi.input 2012-05-30 14:44:56 +02:00
roberto@precise64 1b7d3b5fe9 fixed httprouter and rawrouter requests count 2012-05-29 19:02:07 +02:00
roberto@precise64 a6d7aa7da3 fixed waitpid() usage when in cheap mode 2012-05-29 16:40:45 +02:00
roberto@precise64 11fe76f26d improved --namespace-keep-mount with Lukasz ideas 2012-05-29 15:09:52 +02:00
roberto@precise64 1b6fdf6093 completed server side security of new subscription system 2012-05-29 14:37:26 +02:00
robert@mrspurr fa3badcfd0 improved security of secure subscription server 2012-05-29 14:36:04 +02:00
roberto@precise64 ce1b022025 added --namespace-keep-mount 2012-05-29 10:40:08 +02:00
roberto@precise64 6e81548daa allows building without ssl 2012-05-28 14:46:34 +02:00
roberto@precise64 bb7271ec17 another ifdef for older openssl versions 2012-05-28 14:42:58 +02:00
roberto@precise64 f6ca42a4b0 fixed locking reporting on older systems 2012-05-28 13:51:05 +02:00
roberto@precise64 bcf5d3a480 fixed yaml reporting 2012-05-28 13:46:17 +02:00
roberto@precise64 fffe26ceac added configuration report at the end of uWSGI compilation 2012-05-28 13:44:08 +02:00
roberto@centos64 fd17bdf963 fixed for older openssl versions 2012-05-28 13:08:31 +02:00
roberto@precise64 a168009382 implemented the 'secure' subscription system 2012-05-28 13:02:09 +02:00
roberto@precise64 f624f92e4d refactored keepalive support in http/https router 2012-05-27 15:25:53 +02:00
roberto@precise64 f065171aa1 export HTTPS_DN and HTTPS_CC 2012-05-27 13:28:19 +02:00
roberto@precise64 b7532abcc8 added support for SSL client certificate 2012-05-27 10:07:34 +02:00
roberto@precise64 59aa0308c7 fully disable ssl caching 2012-05-26 16:26:29 +02:00
roberto@precise64 6b5708a563 added a big WARNING for users forgetting to load plugins 2012-05-26 09:46:25 +02:00
roberto@precise64 c1a4834624 allows shared sockets to be subscribed 2012-05-26 09:05:30 +02:00
roberto@precise64 35ce3630c6 allows custom socket to be subscribed 2012-05-26 08:44:15 +02:00
roberto@precise64 c686912707 added rawrouter 2012-05-25 21:23:57 +02:00
roberto@precise64 963964afef custom options can now define commandline options too 2012-05-25 07:40:55 +02:00
roberto@precise64 53666dd289 allows multicast to be used as a subscription server 2012-05-24 20:59:15 +02:00
roberto@precise64 d8d292348e refactored snmp 2012-05-24 20:40:56 +02:00
roberto@precise64 678726859c applied Łukasz Mierzwa patch for carbon no workers 2012-05-24 20:34:10 +02:00
roberto@precise64 bedafceac3 applied riccardo's patch 2012-05-24 20:29:07 +02:00
roberto@precise64 a3635bc45f another master refactoring 2012-05-24 14:30:27 +02:00
roberto@precise64 8cc8394676 removed SCTP support 2012-05-24 12:24:29 +02:00
roberto@precise64 e5124093ff do not check for died processes if diedpid is invalid 2012-05-24 12:05:26 +02:00
roberto@precise64 6d1d5d6bf8 applied riccardo's patch for correct perror report 2012-05-23 20:39:34 +02:00
roberto@precise64 8964b45558 do not disable waitpid() calls during cheap mode 2012-05-23 20:37:13 +02:00
roberto@precise64 eb0e9e7d1a openssl session caching is a problem, no way to make non-blocking io call in callbacks... 2012-05-20 20:51:46 +02:00
roberto@precise64 17254ee863 added support for ssl session caching 2012-05-20 20:31:20 +02:00
roberto@backup 85fdfdd81f protect from SSL beast attack 2012-05-20 08:44:59 +02:00
roberto@precise64 3d194cd8cc added --declare-option 2012-05-19 10:59:40 +02:00
roberto@precise64 3cc591fd8b clang fix 2012-05-18 20:39:58 +02:00
roberto@precise64 3bb43745b8 remove HTTP_CONTENT_LENGTH and HTTP_CONTENT_TYPE from rack/psgi automatically 2012-05-18 16:08:23 +02:00
roberto@precise64 beb12b6804 better DH support based on stud 2012-05-18 11:09:49 +02:00
roberto@mrspurr 9a9cb2f8fe disable ssl2 2012-05-18 08:08:20 +02:00
roberto@centos4 6b7fed814c fixed support for centos4 2012-05-16 15:38:35 +02:00
roberto@precise64 47e26d93c0 ladies and gentleman, https support in the http router/load-balancer 2012-05-16 17:16:26 +02:00
roberto@precise64 de51c46fd8 allows graceful reloads on shared sockets 2012-05-16 11:09:25 +02:00
roberto@precise64 d342bdaf72 added --log-master-bufsize 2012-05-15 08:59:08 +02:00
roberto@precise64 7ee0150e2b force master mode in cheap/idle 2012-05-15 04:24:58 +02:00
roberto@precise64 cd5b0e7e58 ported corerouter stats to the new infrastructure 2012-05-14 21:04:29 +02:00
roberto@precise64 aebda4aced fixed a regression with http pipelined requests 2012-05-14 18:52:27 +02:00
roberto@sirius 26b7e6aabf improved wait_for_threads 2012-05-14 17:42:34 +02:00
roberto@precise64 9b16859c33 ported emperor stats to the new infrastructure 2012-05-14 16:21:16 +02:00
roberto@precise64 d662bf6064 new stats generator subsystem 2012-05-14 15:47:05 +02:00
roberto@precise64 a695a27b9c leave http-keepalive as experimental/useless/broken 2012-05-14 13:20:21 +02:00
roberto@precise64 e46077f576 httprouter keepalive preliminary support 2012-05-13 23:47:32 +02:00
roberto@precise64 6ec3b05ce5 fixed uwsgi signals in async mode 2012-05-13 19:49:00 +02:00
roberto@precise64.local f9d561993a added contrib/uwsgisubscribers.ru 2012-05-13 11:13:11 +02:00
roberto@precise64 c0b59234d0 report exceptions before stacktrace in psgi 2012-05-13 08:50:54 +02:00
roberto@precise64 f041509f15 another big merge of routers 2012-05-13 07:44:05 +02:00
roberto@precise64 06b4300d09 uwsgi.sendfile is for raw usage 2012-05-13 06:46:48 +02:00
roberto@precise64 7bf2194a08 a first series of solaris fixes 2012-05-12 19:48:12 +02:00
roberto@precise64 b6bdf37a1d merged http and fastrouter 2012-05-12 19:37:44 +02:00
roberto@precise64 4060436099 allows subscription system via unix socket 2012-05-12 18:22:44 +02:00
roberto@precise64 406b6098c5 unsubscribe/resubscribe on suspend/resume 2012-05-12 17:48:25 +02:00
roberto@precise64 a5606098aa implemented psgix.logger 2012-05-12 17:36:24 +02:00
roberto@precise64 ff9bab4b4e fixed psgi fileno() support 2012-05-12 17:02:21 +02:00
roberto@precise64 6e881293ff fixed async mode in non-linux systems 2012-05-12 11:23:37 +02:00
roberto@precise64 5fac82cfee fixed wsgi.file_wrapper 2012-05-12 10:54:35 +02:00
roberto@precise64 83da420cfc added corerouter 2012-05-12 10:50:19 +02:00
roberto@precise64 b2abccd302 fixed uwsgi.sendfile() 2012-05-12 10:47:04 +02:00
roberto@precise64 99d9e8cd67 applied atexit patch from 1.2.2 2012-05-11 21:15:58 +02:00
roberto@precise64 9fe275141f added preliminary python tracebacker 2012-05-11 20:44:56 +02:00
roberto@precise64 8c833101d8 let's start 1.3 development cycle 2012-05-10 09:58:09 +02:00
roberto@precise64 0c6f9faaf1 the installer now wants absolute binary path 2012-05-10 08:35:17 +02:00
roberto@precise64 a93ff5bf1f allows multiple start_response without leaks 2012-05-08 19:14:25 +02:00
roberto@precise64 d258c1b417 avoid WSGI status_line to be decref'ed 2012-05-08 18:47:49 +02:00
roberto@precise64 6e473a75bd added UWSGI_BIN_NAME support 2012-05-08 17:17:54 +02:00
roberto@precise64 433de267a6 added redislog plugin 2012-05-06 16:04:56 +02:00
roberto@precise64 2beca32c36 do not run cheaper algos or subscriptions on suspended instances 2012-05-06 14:04:43 +02:00
roberto@precise64 15aaddb4d3 allows embedding the psgi plugin 2012-05-05 10:23:26 +02:00
roberto@precise64 35ddb777b4 added interpolation support in build profile 2012-05-05 10:06:44 +02:00
roberto@precise64 b15a0a2d4b added --disable-write-exception 2012-05-05 09:30:43 +02:00
roberto@precise64 95bda63c40 added --exec-as-user-atexit (patch by Łukasz Mierzwa) 2012-05-05 09:11:40 +02:00
roberto@precise64 62b24fcd2a another python headers management optimization 2012-05-05 09:00:52 +02:00
roberto@precise64 df0406902e fixed static file offloading 2012-05-05 07:44:10 +02:00
roberto@precise64 71d57274e5 fixed optional pargs management 2012-05-05 07:11:35 +02:00
roberto@debian32 08c6258459 tolerate php wrong sign-compare 2012-05-04 16:26:06 +02:00
roberto@precise64 9a4e950480 added a fallback for pthread robust mutexes 2012-05-03 20:19:58 +02:00
roberto@precise64 e2dcdba5a7 fixed headers sent 2012-05-02 11:34:10 +02:00
roberto@precise64 c39cf848de better implementation of start_response() 2012-05-02 09:30:37 +02:00
roberto@precise64 5ccf2254eb added preliminary version of mod_proxy_uwsgi for apache2 2012-05-01 15:59:42 +02:00
roberto@precise64 dd291b9b71 fixed streaming in mod_uwsgi 2012-05-01 09:07:20 +02:00
roberto@precise64 0515fbb2d6 Added tag 1.2 for changeset c3cdecbf2bac 2012-04-30 11:05:16 +02:00
roberto@precise64 6692276472 uWSGI 1.2 2012-04-30 11:05:08 +02:00
roberto@mrspurr 81c09a9c9c report signum in worker's death 2012-04-29 05:04:19 +02:00
roberto@precise64 6a0a367ec3 added a test for gevent + threads 2012-04-26 15:11:52 +02:00
roberto@precise64 bdf533d62b fixed auto-reloading 2012-04-26 14:51:39 +02:00
roberto@precise64 1aba0bc26c completed --if-reload//--if-not-reload 2012-04-26 09:40:20 +02:00
roberto@precise64 aac6e9a365 fixed ruby -bash 2012-04-26 09:26:33 +02:00
roberto@precise64 9da732d96c added --if-reload/--if-not-reload and --unenv 2012-04-26 09:17:45 +02:00
roberto@precise64 328ba43ed2 fix uninitialzied structure 2012-04-25 17:55:47 +02:00
roberto@freebsd9 62d3253b02 fix kqueue() usage 2012-04-25 15:02:19 +02:00
roberto@mrspurr e5ba01e707 fixed socket in non-blocking mode 2012-04-25 14:18:40 +02:00
roberto@openbsd51 82c25f7f8c better execinfo detection 2012-04-25 11:00:25 +02:00
roberto@precise64 8791866ea0 added ebug infos for touch checks 2012-04-25 08:37:23 +02:00
roberto@opensuse12 8f10b8fece fix python version printing on freeky systems 2012-04-25 08:11:12 +02:00
roberto@opensuse12 0d28d210d4 another opensuse-related fix, build mimedict only if needed 2012-04-25 08:02:24 +02:00
roberto@precise 2368a5a050 fixed bug 121 2012-04-25 07:21:28 +02:00
roberto@precise64 74a9b1b41d added uwsgi.ready() 2012-04-24 21:50:00 +02:00
roberto@precise64 672c49e8eb refactored signal handling 2012-04-24 21:27:43 +02:00
roberto@precise64 225db32636 threading support for gevent 2012-04-24 19:23:14 +02:00
roberto@opensuse12 01541e4a50 fixed bug #120 2012-04-24 18:53:38 +02:00
roberto@precise64 357e260b45 some minor cleanup spotted by marcin deranek 2012-04-20 16:27:00 +02:00
roberto@centos32 a2513b1851 put a \0 at the end of process name 2012-04-20 16:11:16 +02:00
roberto@precise64 bbe8604054 added hack for ruby -bash 2012-04-20 14:11:08 +02:00
roberto@precise64 58a33de7f7 Added tag 1.2-rc2 for changeset 29de0fb320bc 2012-04-20 10:11:59 +02:00
roberto@precise64 ab7abc6a48 added upstart socket activation support and applied git001 patch for additional include paths 2012-04-20 09:59:59 +02:00
roberto@mrspurr 4986bdf202 added --static-map2 2012-04-20 07:04:02 +02:00
roberto@precise64 11aaddac98 fixed --static-map to a file 2012-04-19 19:44:35 +02:00
roberto@precise64 da9b2b4378 added static-expires/static-expires-mtime 2012-04-19 19:22:00 +02:00
roberto@freebsd9 9771a98bc6 fixed a typecast in rack plugin 2012-04-18 15:47:55 +02:00
roberto@precise64 033ee5f4e9 fixed a typo 2012-04-18 14:38:30 +02:00
roberto@precise64 1383163627 import dummy_threading whenever threads are in place 2012-04-18 10:14:41 +02:00
roberto@precise64 1d31b35c4f export static_offload_threads in statistics 2012-04-18 08:01:48 +02:00
roberto@precise64 7b2cc757b2 fixed SERVER_PORT in zeromq 2012-04-18 00:54:43 +02:00
roberto@precise64 68cddd1c2e fixed REMOTE_ADDR in mongrel2 when protocol is tnetstring 2012-04-17 23:41:04 +02:00
roberto@goyle b2a9fbbc5c set offload threading stacksize to 512k 2012-04-17 22:26:32 +02:00
roberto@goyle 0fcb13b9f1 implemented offload static file serving 2012-04-17 22:01:54 +02:00
roberto@goyle 938a22ce2e multiple mime file support 2012-04-17 20:04:48 +02:00
roberto@goyle 2df5dbfe52 added support for expires header 2012-04-17 19:24:13 +02:00
roberto@goyle feed0d0faa fixed get_mime_type 2012-04-15 22:33:05 +02:00
roberto@goyle c8373d20a9 added a check for strlen in the cgi plugin 2012-04-15 17:42:28 +02:00
roberto@mrspurr 170267a04a fixed mod_Ruwsgi 2012-04-15 07:11:45 +02:00
roberto@precise64 bd5969db67 fix initial messages 2012-04-15 07:06:33 +02:00
roberto@precise64 02256c013c added --carbon-no-workers 2012-04-14 13:54:41 +02:00
roberto@precise64 89be9a0d4a Added tag 1.2-rc1 for changeset 24c8fe5a26e5 2012-04-14 12:55:03 +02:00
roberto@precise64 4e57a6e145 uWSGI 1.2-rc1 2012-04-14 12:54:48 +02:00
roberto@openindiana64 784434ef3e opeinindiana fixes 2012-04-14 12:24:04 +02:00
roberto@precise64 91273b2301 py-auto-reload-ignore 2012-04-14 11:48:27 +02:00
roberto@precise64 2bcc85a99f added support for REMOTE_ADDR in mongrel2/zeromq 2012-04-14 10:08:34 +02:00
roberto@precise64 b7e6da3392 added --write-errors-tolerance and --write-errors-exception-only 2012-04-14 09:11:52 +02:00
roberto@precise64 d934270a27 merge 2012-04-14 08:22:54 +02:00
roberto@fiorenzo ed5a268e1f fix reloading of gateways 2012-04-13 19:01:05 +02:00
roberto@fiorenzo 95beaa0a86 merge 2012-04-13 17:09:22 +02:00
roberto@fiorenzo 0d3bf93c76 fixed fd leak in daemonize 2012-04-13 17:08:52 +02:00
roberto@sirius 50fb43066a ported fastcgi and zeromq to the new api 2012-04-13 16:23:55 +02:00
roberto@centos4 c33ec8ff56 ported locking to obsolete kernels 2012-04-13 14:09:03 +02:00
roberto@mrspurr e6afeec8af fixed return value in cache sweeper thread 2012-04-13 15:57:07 +02:00
roberto@sirius 57b9bdb958 better write()/writev() management 2012-04-13 11:36:43 +02:00
roberto@precise64 315bcb72c9 applied nagios patch from github 2012-04-11 07:23:00 +02:00
roberto@precise64 6b2460c02f improved syslog 2012-04-11 07:20:58 +02:00
roberto@precise64 35bc999a59 correctly set bin_name in setup.py 2012-04-09 08:41:27 +02:00
roberto@precise64 f00ad75e45 added --emperor-magic-exec 2012-04-08 09:13:07 +02:00
roberto@openbsd51 6bfe8e5b41 openBSD fixes 2012-04-08 08:24:51 +02:00
roberto@precise64 d7e8fd7d06 a couple of typo 2012-04-07 21:17:09 +02:00
roberto@precise64 949a0c35d5 improve cache reliability and performance of the sweeper 2012-04-07 21:08:42 +02:00
roberto@precise64 d193d5572f add --cache-expire-freq 2012-04-06 16:09:58 +02:00
roberto@precise64 f79f7e44a7 fixed cache and queue locking 2012-04-06 15:54:29 +02:00
roberto@mrspurr 26db55aafd fixed --pyargv 2012-04-06 11:39:48 +02:00
roberto@mrspurr 9d405c6cb2 fixed locking in uwsgi.cache_exists 2012-04-06 10:28:02 +02:00
roberto@mrspurr cceee511f2 added support for reload-on-exception on PyPy and interval-based cron syntax 2012-04-06 07:40:21 +02:00
roberto@freebsd9 e2024ed2fd merge 2012-04-05 12:28:30 +02:00
roberto@freebsd9 add7e2ee0e added execinfo support for FreeBSD 2012-04-05 12:28:10 +02:00
roberto@precise64 0458aa8eb4 use ctime_r instead of ctime 2012-04-05 12:15:04 +02:00
roberto@freebsd9 9ff6be783a use posix semaphores on freebsd9 2012-04-05 06:22:02 +02:00
roberto@mrspurr 14c558559b pypy now has PyFile_FromFile 2012-04-05 05:52:58 +02:00
roberto@centos64 92c5dcb6f2 allows robust mutexes on older linux systems 2012-04-04 22:54:56 +02:00
roberto@precise64 ae31f349f7 added robust mutexes 2012-04-04 22:53:07 +02:00
roberto@centos64 ce2846d04f first pthread robust implementation 2012-04-04 21:48:34 +02:00
roberto@mrspurr 7a6c9a5fe4 merge 2012-04-04 17:29:39 +02:00
roberto@mrspurr 43c258ad48 support for virtualenv in pypy 2012-04-04 17:29:00 +02:00
roberto@precise64 8ba032adb2 added --spooler-max-tasks 2012-04-03 17:59:37 +02:00
roberto@precise64 1a61dfd4e0 ported mod_Ruwsgi to apache 2.4 2012-04-03 09:02:00 +02:00
roberto@precise64 8e150e77a8 ported mod_uwsgi to apache 2.4 2012-04-03 08:47:09 +02:00
roberto@goyle 729fa753fa remove unneded pypy ifdef 2012-04-02 19:33:33 +02:00
roberto@longshot bf6c552189 fixed python 2.4 2012-04-02 07:55:22 +02:00
roberto@precise64 e9dc987a95 revert wsgi.url_scheme 2012-04-02 07:48:20 +02:00
roberto@precise64 35d9a39100 fixed autoload 2012-04-01 06:14:09 +02:00
roberto@mrspurr a864c8d6ed fix pypy when no app is loaded 2012-03-31 18:06:03 +02:00
roberto@precise64 c2df8a099e added --python-auto-reload 2012-03-31 17:55:09 +02:00
roberto@precise64 878e9cb9ba reports microseconds in python profilers 2012-03-31 15:48:22 +02:00
roberto@precise64 3612ea2186 fixed a deadlock in get_mime_type 2012-03-30 21:15:14 +02:00
roberto@precise64 81f0f93d96 improved module aliasing 2012-03-30 10:17:30 +02:00
roberto@precise64 c2d7b65145 better error management in pymodule-alias 2012-03-29 12:59:50 +02:00
roberto@precise64 6274e82cea fix fastrouter subscription refcnt 2012-03-29 11:26:35 +02:00
roberto@precise64 66655c9429 php append options 2012-03-28 18:28:24 +02:00
roberto@precise64 f47c8553d5 added uwsgi_expand_path() 2012-03-28 16:48:17 +02:00
roberto@precise64 f2802d3332 gevent current_req fix 2012-03-28 16:22:18 +02:00
roberto@precise64 1a173c849f minor fixes for test suite 2012-03-28 12:40:20 +02:00
roberto@precise64 57d4cd9fc9 gevent fixes 2012-03-28 11:08:04 +02:00
roberto@precise64 f6b9345716 fixed a garbage in python_call 2012-03-28 10:21:20 +02:00
roberto@freebsd64 792cd01320 fixed daemonize 2012-03-28 09:34:37 +02:00
roberto@mrspurr 03bc7d0399 close bug 85 2012-03-28 09:00:53 +02:00
roberto@mrspurr ed8f0812d7 PyPy SUPPORT 2012-03-27 13:58:27 +02:00
roberto@precise64 196dc45d0b fixed zero socket (2) 2012-03-26 14:28:18 +02:00
roberto@precise64 f8ff906d1b fixed zero socket 2012-03-26 14:20:08 +02:00
roberto@precise64 bbf1b0eda5 merged pypy 2012-03-26 13:41:50 +02:00
roberto@precise64 6f811a4899 better realpath for static docroot 2012-03-26 13:41:18 +02:00
roberto@mrspurr c66957d685 first round of pypy patches 2012-03-26 10:46:12 +02:00
roberto@goyle 282b2d5ace lua fixes 2012-03-23 21:22:17 +01:00
roberto@precise64 6a73e3ae05 fixed rack.input read 2012-03-22 16:25:27 +01:00
roberto@precise64 5856d410fd second part of zerg fixes 2012-03-22 11:14:41 +01:00
roberto@precise64 08d9de54f0 uniq zerg sockets 2012-03-22 10:05:00 +01:00
roberto@precise64 af1f98131a --perl-no-die-catch 2012-03-22 08:32:11 +01:00
roberto@precise64 9cef49ec57 fixed perl caching, added uwsgi::signal 2012-03-22 08:26:33 +01:00
roberto@precise64 d60c6d50ec fixed plugin loading by symlink 2012-03-22 07:35:27 +01:00
roberto@precise64 f3fdec2739 completed --reload-on-exception* options 2012-03-21 20:37:03 +01:00
roberto@precise64 1a20f57b73 fixed --spooler-quiet 2012-03-21 20:28:08 +01:00
roberto@precise64 0fc74dac4d better GIL usage 2012-03-21 20:21:51 +01:00
roberto@precise64 4117dd91fc ported psycopg2 example to the new api 2012-03-21 19:53:40 +01:00
roberto@precise64 508ca0df39 add realpath() for php DOCUMENT_ROOT 2012-03-21 19:28:24 +01:00
roberto@precise64 a50e356beb more verbose php debug 2012-03-21 07:50:27 +01:00
roberto@precise64 a0b7237083 added --spooler-quiet 2012-03-20 15:42:10 +01:00
roberto@precise64 08afa73e69 spooler multiprocess fixes 2012-03-20 10:58:48 +01:00
roberto@precise64 b386317921 fixed python3 reload-on-exception 2012-03-19 13:39:07 +01:00
roberto@precise64 2043127f22 fixed snmp support 2012-03-19 07:29:39 +01:00
roberto@precise64 c297a9415b started 1.2 development cycle 2012-03-18 09:03:14 +01:00
roberto@precise64 f9f9f25a01 added exception detection 2012-03-18 08:21:45 +01:00
roberto@precise64 9001af1beb better uuid detection 2012-03-17 11:01:01 +01:00
roberto@debian32 4b03f17186 python 3.x fix 2012-03-17 10:36:06 +01:00
roberto@precise64 3dbab36b91 uWSGI 1.1 2012-03-17 07:56:09 +01:00
roberto@precise64 056c890845 Added tag 1.1 for changeset e1568fd16b7b 2012-03-17 07:39:33 +01:00
roberto@precise64 4f43cd74ad env must not be immediate 2012-03-16 20:53:03 +01:00
roberto@precise64 6585b7b13d fixed pifile 2012-03-16 13:38:26 +01:00
roberto@precise64 e55048b574 fixed logdate 2012-03-16 13:07:06 +01:00
roberto@mercury 570dcde654 report listen_queue_errors 2012-03-16 06:52:48 +01:00
roberto@precise64 3cb16ee29b ready for 1.1 release 2012-03-15 20:42:41 +01:00
roberto@mailcop3 bb453da5b5 added support for SIOBKLGQ 2012-03-15 20:40:26 +01:00
roberto@precise64 1a93b68664 fixed expire_timeouts in fastrouter 2012-03-15 17:44:56 +01:00
roberto@precise64 2ce2494a50 bumped to -rc4 2012-03-15 17:36:59 +01:00
roberto@precise64 0a1e451289 Added tag 1.1-rc4 for changeset ef99144291f0 2012-03-15 17:31:05 +01:00
roberto@precise64 8ef7819080 re-included WSGI iterator close() 2012-03-15 17:29:55 +01:00
roberto@precise64 319ad13af2 allows plugin 255 to be used 2012-03-15 08:58:41 +01:00
roberto@precise4 fe28e90ae3 fixed a bug in spooler and signal plugin 2012-03-15 08:48:26 +01:00
roberto f604a0a533 bumped to 1.1-rc3 2012-03-14 18:30:19 +01:00
roberto@precise64 4ab78d42a3 Added tag 1.1-rc3 for changeset ede5c664978b 2012-03-14 18:30:02 +01:00
roberto@precise64 c631e7dae6 fixed multiple touch-reload 2012-03-14 18:29:04 +01:00
roberto@precise da8e88d638 Added tag 1.1-rc2 for changeset 901f0cb5de36 2012-03-14 12:08:58 +01:00
roberto@precise64 4707d9250d queue/cache fix 2012-03-14 11:34:51 +01:00
roberto@precise64 d719960411 fixed emperor amqp 2012-03-14 10:03:54 +01:00
roberto@precise64 734818c995 fixed shared sockets 2012-03-14 08:28:25 +01:00
roberto@precise64 a35335a820 fixed lua plugin 2012-03-12 18:54:04 +01:00
roberto@precise64 aca4dbfbe7 fixed threading rpc 2012-03-12 14:54:59 +01:00
roberto@precise64 b036029b32 another locking fix 2012-03-12 09:58:02 +01:00
roberto@freebsd64 52f3e757ed added --ftok 2012-03-12 09:40:56 +01:00
roberto@precise64 c4ce1cf7d8 appliead Riccardo's patches 2012-03-11 20:10:04 +01:00
roberto@icarus 48175d0759 various fixed for php and cgi plugins, added notfound plugin 2012-03-11 17:21:53 +00:00
roberto@precise64 2932168db7 Added tag 1.1-rc1 for changeset 1d1702789710 2012-03-10 15:23:47 +01:00
roberto@precise64 e8d96b8f84 completed ldap support 2012-03-10 15:21:08 +01:00
roberto@precise64 bd15fd9da1 fixed ldap support 2012-03-10 14:30:48 +01:00
roberto@precise64 6e98eda963 set version to 1.1, only LDAP missing 2012-03-10 13:34:17 +01:00
roberto@precise64 ec9bb3601e added --flock/--flock2/--flock-wait/--flock-wait2 2012-03-10 13:26:45 +01:00
roberto@precise64 02e4840b29 re-added --ignore-sigpipe 2012-03-10 12:34:45 +01:00
roberto@precise64 d7e8523fcf do not call atexit hooks in async mode 2012-03-10 12:06:19 +01:00
roberto@precise64 41464c3bfa fr sctp fix 2012-03-10 11:35:05 +01:00
roberto@goyle a3617d0b5a fastrouter heavy optimization 2012-03-10 11:25:19 +01:00
roberto@centos6 10ff849ebd fixed permissions of files 2012-03-07 15:06:38 +01:00
roberto@centos6 c2f7d487d0 initgroups() usage 2012-03-07 04:40:16 +01:00
roberto@centos6 395cf57e21 added stats for sctp fastrouter 2012-03-07 02:55:48 +01:00
roberto@centos6 4c854a83c9 SCTP improvements, rack optimizations 2012-03-07 01:40:57 +01:00
roberto@centos6 881b3b7e0c another series of SCTP fixes 2012-03-06 16:43:41 +01:00
roberto@openbsd50 bb28e4279b fixed cgi cast of FILE 2012-03-06 15:22:38 +01:00
roberto@openbsd50 c65b8ce162 various fixes 2012-03-06 15:20:25 +01:00
roberto@openindiana 8a303b1965 solaris fixes 2012-03-06 12:19:29 +01:00
roberto@centos6 adca811941 fixed 105 2012-03-06 11:34:56 +01:00
roberto@goyle f79e9d8773 fixed a typo 2012-03-05 16:22:20 +01:00
roberto@precise64 629fbf4f07 another series of sctp patch 2012-03-05 04:29:11 +01:00
roberto@precise64 da9ce52294 little refactoring for the fastrouter 2012-03-04 16:10:35 +01:00
roberto@precise64 205605a3c4 fixed PATH_INFO in php 2012-03-03 17:34:44 +01:00
roberto@precise64 e39127be92 ready for rc 2012-03-03 16:31:26 +01:00
roberto@precise64 0b2458d74a SCTP is experimenta, stop development til 1.1 release 2012-03-03 16:17:16 +01:00
roberto@precise64 9d661122bd added experimental SCTP/persistent connections support 2012-03-03 13:46:21 +01:00
roberto@precise64 8518747a51 try to reduce spooler wait 2012-03-03 09:35:46 +01:00
roberto@precise64 2f6450a560 <app> tag usage will be removed in uWSGI 1.2 2012-03-02 08:27:52 +01:00
roberto@precise64 c72889c10f added --daemonize2 2012-03-02 07:31:20 +01:00
roberto@precise64 bb7456e3f8 gateways structure is again shared 2012-03-01 21:27:17 +01:00
roberto@precise64 5aff13543e another fastrouter fix 2012-03-01 20:11:06 +01:00
roberto@precise64 c7d967d43c fixed python 3 2012-03-01 18:30:32 +01:00
roberto@precise64 1a42194304 added ruby rvm/gemset support 2012-03-01 18:22:25 +01:00
roberto@precise64 312563437c multiprocess spooler 2012-03-01 14:54:10 +01:00
roberto@precise64 5972ac1ed7 fixed permission in ipcsem 2012-03-01 11:11:51 +01:00
roberto@precise64 75d4123b34 added locking test 2012-03-01 11:06:53 +01:00
roberto@precise64 89ef4f68a9 added ipcsem 2012-03-01 11:06:00 +01:00
roberto@precise64 ed72677e52 even fcntl is broken 2012-03-01 09:51:31 +01:00
roberto@precise64 08ab27c36c cache_get optimization 2012-03-01 09:15:43 +01:00
roberto@precise64 af8bb8fd05 fixed locking in multithread 2012-03-01 09:06:02 +01:00
roberto@precise64 57bade7eae close stdin in vassals 2012-02-29 14:57:44 +01:00
roberto@mishmash 3c6de0e84d various fastrouter fixes 2012-02-29 10:14:44 +01:00
roberto@precise64 24e3fea334 added fd:// to corerouter bind subsystem 2012-02-29 08:47:52 +01:00
roberto@precise64 6af77aab8b added --fastrouter-gracetime 2012-02-29 07:46:24 +01:00
roberto@precise64 12325633ed fastrouter improvements 2012-02-29 07:04:14 +01:00
roberto@sirius 3a108b61ee fixed pause reporting 2012-02-28 18:56:32 +01:00
roberto@goyle b2eaf384ac --fastrouter-fallback 2012-02-28 18:08:40 +01:00
roberto@precise64 3d17ef9603 lockf for sun 2012-02-28 10:31:24 +01:00
roberto@precise64 3b031872f7 lockf for sun 2012-02-28 10:30:07 +01:00
roberto@precise64 e97d39f37c prepared umtx for future implementations 2012-02-28 09:21:44 +01:00
roberto@sirius 763f715279 ported locking api to OSX 2012-02-28 09:18:41 +01:00
roberto@precise64 af9f79f3eb ported new locking api to linux 2012-02-28 09:14:08 +01:00
roberto@freebsd64 01ab3e2895 broken commit for new locking api 2012-02-28 09:05:37 +01:00
roberto@precise64 7a34344632 fixed a bug in setrlimit 2012-02-27 20:21:55 +01:00
roberto@precise64 9714cb6790 fixed log flush 2012-02-27 19:48:35 +01:00
roberto@precise64 aa981d03e8 reintroduce the remote spooler plugin [2] 2012-02-27 15:59:47 +01:00
roberto@precise64 9a09164fc3 reintroduce the remote spooler plugin 2012-02-27 15:59:07 +01:00
roberto@precise64 9674a81323 added --forkbomb-delay 2012-02-27 14:38:49 +01:00
roberto@precise64 aba7280691 added --need-app 2012-02-27 14:27:34 +01:00
roberto@precise64 ef9908b058 fixed --cluster-reload and --cluster-log 2012-02-26 12:35:05 +01:00
roberto@precise64 4da4fb4cbd completed clustering porting 2012-02-26 12:30:35 +01:00
roberto@precise64 b4f8a3b179 fixed bug #62 2012-02-26 09:07:14 +01:00
roberto@precise64 b48a955848 fixed paste logging 2012-02-26 08:57:43 +01:00
roberto@precise64 5ea4e3bcc3 removed url from setup.py 2012-02-26 08:26:21 +01:00
roberto@precise64 6732cb01a8 free libxml2 resources on exit 2012-02-26 08:05:39 +01:00
roberto@precise64 0b5ca736d4 re-added expat support 2012-02-25 20:26:17 +01:00
roberto@precise64 a2358c6bec completed porting of the http plugin to the new api 2012-02-25 18:36:04 +01:00
roberto@precise64 10775dd2ac another series of http ports 2012-02-25 18:24:56 +01:00
roberto@precise64 d33d12c642 ported --http-var 2012-02-25 18:20:59 +01:00
roberto@precise64 af3ccfeed4 added negative configlogic 2012-02-25 09:24:07 +01:00
roberto@precise64 1d64267aba added --check-static-docroot 2012-02-25 08:44:00 +01:00
roberto@cable 9bbef9b0c5 various condition build fixes 2012-02-25 08:34:11 +01:00
roberto@precise64 c95ec82b03 a series of php/cgi fixes 2012-02-24 12:12:19 +01:00
roberto@precise64 46108a00f0 fixed startup time in rack plugin 2012-02-24 09:37:33 +01:00
roberto@precise64 d6c3fd7771 --php-app added 2012-02-24 09:26:57 +01:00
roberto@precise64 ad783ccaf0 added script for external app loading 2012-02-24 06:49:54 +01:00
roberto@precise64 f58be4241f added cheaper_backlog2 example 2012-02-23 21:46:27 +01:00
roberto@precise64 cb1d22d88b added pluggable cheaper algorithms 2012-02-23 21:38:53 +01:00
roberto@precise64 6c8453d98e another logging refactoring 2012-02-23 20:42:00 +01:00
roberto@colossus 061de3b037 merge 2012-02-23 18:16:38 +01:00
roberto@colossus ded065ef38 php-server-software 2012-02-23 18:16:18 +01:00
roberto@precise64 822959238c fixed a bug with --set 2012-02-23 16:58:36 +01:00
roberto@precise64 4ebb9d7b46 faster restart thanks to single getrlimit call 2012-02-23 14:13:38 +01:00
roberto@precise64 cc49964c43 fixed a lost null pointer 2012-02-23 07:51:36 +01:00
roberto@precise64 3787d5e84a flush logs on exit 2012-02-23 07:48:54 +01:00
roberto@precise64 7329606a6a added a cast (just to be sure) 2012-02-22 17:11:12 +01:00
roberto@precise64 5facafadea added uwsgi api support for php 2012-02-22 16:44:56 +01:00
roberto@precise64 d3102df2bf added a signal handler for FPE 2012-02-22 12:00:32 +01:00
roberto@precise64 87860da238 better loaded app reporting 2012-02-22 11:55:06 +01:00
roberto@precise64 4a8aa01f40 added startup time for apps 2012-02-22 11:39:19 +01:00
roberto@longshot 9d35067b4b allows custom php-config path 2012-02-22 10:33:45 +01:00
roberto@precise64 1c29be3745 fix php uwsgi.h include 2012-02-20 04:07:16 +01:00
roberto@centos6 bf3c3a3768 another php update 2012-02-19 17:52:17 +01:00
roberto@fedora32 b25de79ae4 completed new php plugin 2012-02-19 15:44:23 +01:00
roberto@precise64 ba663ef2cc ready for new php plugin 2012-02-19 11:08:52 +01:00
roberto@precise64 19185640a5 fixed a typo 2012-02-18 16:29:21 +01:00
roberto@precise64 eafe8c4fff new cheaper implementation 2012-02-18 16:28:01 +01:00
roberto@precise64 bdd3e69024 removed some funny debug log 2012-02-18 11:40:25 +01:00
roberto@precise64 b5a7ab3688 fixed paste logging 2012-02-18 09:32:39 +01:00
roberto@centos64 cc0fa8dee6 fixed rack build 2012-02-18 08:55:35 +01:00
roberto@precise64 14941cc1c0 deprecate <app> 2012-02-18 08:40:36 +01:00
roberto@precise64 910cb3a790 fixed single-intepreter mode 2012-02-18 08:32:53 +01:00
roberto@precise64 355e989eea refactored xmlconf 2012-02-18 08:07:48 +01:00
roberto@precise64 bfcd9dad25 removed useless makefiles 2012-02-18 07:37:48 +01:00
roberto@precise64 73ed5fd7cf added --auto-weight 2012-02-18 07:25:11 +01:00
roberto@netbsd64 d21cc0970c NetBSD fixes 2012-02-18 08:16:37 +01:00
roberto@precise64 eb8b03139d master_loop function is becoming extremely huge, time to refactor it... 2012-02-17 20:36:04 +01:00
roberto@precise64 1558145985 refactored uwsgi_reload() 2012-02-17 20:23:29 +01:00
roberto@precise64 4ea9a29e62 fixed some typo in comments 2012-02-17 20:09:54 +01:00
roberto@precise64 72c8d9cd5e refactored/reimplemented cheaper mode 2012-02-17 19:04:32 +01:00
roberto@precise64 fb4fc38f14 better umask handling 2012-02-17 17:58:46 +01:00
roberto@precise64 de25db9e75 fixed shared sockets for http and fastrouter plugins 2012-02-17 17:48:57 +01:00
roberto@precise64 4ba558430d added wrr to fastrouter/subscription 2012-02-17 13:57:46 +01:00
roberto@precise64 e4711484ac fixed a stupid deadlock 2012-02-17 11:21:08 +01:00
roberto@precise64 5081a3f635 placed a mutex in threaded logger trying to fix #84 2012-02-17 09:50:56 +01:00
roberto@precise64 b31fa366a2 make older gcc happy for gevent 2012-02-17 07:05:26 +01:00
roberto@precise64 c1b24b390a fixed unsubscribe 2012-02-16 20:13:36 +01:00
roberto@precise64 b7461442b0 added a report on unsubscribe 2012-02-16 16:56:08 +01:00
roberto@precise64 c072e9b609 added stacktrace to perl errors 2012-02-16 11:31:52 +01:00
roberto@precise64 5236c58255 added new routing rules 2012-02-16 09:04:59 +01:00
roberto@precise64 4f5280ea2b zeromq/mongrel2 improvements 2012-02-16 07:33:31 +01:00
roberto@precise64 4d1c3fcaea added UWSGI_APPID management in router_uwsgi 2012-02-16 07:22:13 +01:00
roberto@precise64 310acaf4cc do not inizialize request plugins if not needed 2012-02-15 21:28:12 +01:00
roberto@precise64 8111acaad1 completed new perl infrastructure 2012-02-15 20:34:52 +01:00
roberto@mrspurr c80b10d2b2 fixes for non ithreads perl 2012-02-15 19:55:43 +01:00
roberto@precise64 9807192bd1 thread-safe perl multi-app support 2012-02-15 18:10:22 +01:00
roberto@precise64 9386c97851 added perl multiple interpreter support (non-thread-safe) 2012-02-15 14:10:33 +01:00
roberto@precise64 7f3e9b10c4 merge 2012-02-15 05:03:56 +01:00
roberto@precise64 360719582b fix #91 2012-02-15 05:03:15 +01:00
roberto@sirius a1a6d4a248 fxed the carbon plugin 2012-02-14 16:20:34 +01:00
roberto@precise64 015ea78927 set correct status in routers 2012-02-13 19:27:42 +01:00
roberto@precise64 ad32841aaa fixed wrong definition of --route option 2012-02-13 19:22:32 +01:00
roberto@precise64 2a3771dccf added blacklist/whitelist support for options 2012-02-13 16:55:48 +01:00
roberto@precise64 26af8af48f fixed port handling in fastrouter stats 2012-02-13 11:54:03 +01:00
roberto@precise64 5829c3a843 new plugin infrastructure 2012-02-13 11:40:06 +01:00
roberto@goyle c723d6d9d5 non-linux fix 2012-02-13 07:56:59 +01:00
roberto@oneiric64 2c0c9a918a fixed a stupid bug in uniq_warning 2012-02-13 06:41:27 +01:00
roberto@precise64 8f9bc7170e added zergpool pluin 2012-02-12 17:20:51 +01:00
roberto@precise64 ee002167d4 improved zergpool 2012-02-12 17:17:19 +01:00
roberto@precise64 4ddeb26cca extended zerg mode to support an unlimited number of sockets 2012-02-12 13:16:58 +01:00
roberto@precise64 a1514e2eaf added another config style for basicauth 2012-02-12 10:11:39 +01:00
roberto@precise64 5d1c7ab8b0 fixed a race condition in cheaper + threads 2012-02-12 09:42:17 +01:00
roberto@precise64 27698e34f5 added protected.ini 2012-02-12 09:28:19 +01:00
roberto@precise64 c06b4773c7 thread-safe basicauth 2012-02-12 09:26:38 +01:00
roberto@mrspurr e431936a8e python set() is not good 2012-02-12 08:43:21 +01:00
roberto@precise64 de3d22a401 preliminary support for http basic auth (real) 2012-02-12 08:35:21 +01:00
roberto@precise64 22778d9de7 preliminary support for http basic auth 2012-02-12 08:34:14 +01:00
roberto@precise64 069f517b04 added --zerg-fallback 2012-02-11 21:02:15 +01:00
roberto@precise64 1017dda1ec merge 2012-02-11 17:50:20 +01:00
roberto@centos64 581b4a4216 off by one fix 2012-02-11 17:40:41 +01:00
roberto@precise64 e1f00cbf96 better erlang detection 2012-02-11 17:20:47 +01:00
roberto@centos64 32ad0a7b87 build improvements 2012-02-11 14:17:00 +01:00
roberto@oneiric64 aa4b9b16fb fixed magic_table handling 2012-02-10 16:14:44 +01:00
roberto@oneiric64 73721ab73a disable write-strings 2012-02-10 15:27:02 +01:00
roberto@oneiric64 90cc3dc389 fixed rack build 2012-02-10 12:37:07 +01:00
roberto@oneiric64 f4f4d5a6c0 python atexit improvements from mod_wsgi 2012-02-10 11:18:53 +01:00
roberto@oneiric64 4bd2410ee7 added support for logic in config directives with a first 'for' implementation 2012-02-10 09:06:09 +01:00
roberto@gambit 6bc264d33b various fixes for better cgi routing support 2012-02-09 13:00:27 +01:00
roberto@gambit c7d1c6818b fixed touch-reload 2012-02-09 12:32:31 +01:00
roberto@oneiric64 937e68bf67 another lock fix 2012-02-08 12:56:46 +01:00
roberto@oneiric64 434fb96be7 another fix in locking subsystem 2012-02-08 12:49:06 +01:00
roberto@oneiric64 e2fe86027c improved pyargv management 2012-02-08 12:19:14 +01:00
roberto@oneiric64 06ca891d94 fixed threading in command mode 2012-02-08 11:54:15 +01:00
roberto@oneiric64 57c00c9b12 set to_hell in command mode 2012-02-08 11:41:01 +01:00
roberto@sirius b320e1e222 disable master process in command mode 2012-02-08 11:15:29 +01:00
roberto@sirius c72ddc9dd8 added command mode 2012-02-08 11:01:04 +01:00
roberto@oneiric64 c37a386674 added uwsgi.is_locked 2012-02-07 16:40:25 +01:00
roberto@oneiric64 ad6a79b5b7 remove -Wwrite-strings 2012-02-07 16:09:45 +01:00
roberto@oneiric64 ff733cd50b fixed logto 2012-02-07 15:37:19 +01:00
roberto@oneiric64 53128a2391 fixed daemonize and cron 2012-02-07 15:32:34 +01:00
roberto@oneiric64 d01fc8804c fixed a stupid bug in cron management 2012-02-07 14:36:26 +01:00
roberto@oneiric64 e520d7a58f fixed mules signal handling 2012-02-07 12:38:37 +01:00
roberto@freebsd64 7846ea636c ported new locking api to freebsd 2012-02-07 12:09:20 +01:00
roberto@mrspurr 0025ad8329 ported new lock api to OSX 2012-02-07 12:03:50 +01:00
roberto@oneiric64 1a1f270f4e completed locking refactoring on linux 2012-02-07 11:56:19 +01:00
roberto@oneiric64 517f4498f5 another locking refactoring 2012-02-07 11:10:20 +01:00
roberto@oneiric64 87a165477f fixed disable logging 2012-02-07 05:34:28 +01:00
roberto@oneiric64 1e657f0b77 plugins loading fix 2012-02-07 05:26:51 +01:00
roberto@oneiric64 a8e399db1e psgi fixes 2012-02-07 05:08:53 +01:00
roberto@oneiric64 66f9607404 various fixes reported by Lukasz Mierzwa 2012-02-07 03:20:10 +01:00
roberto@oneiric64 27319c2da3 ported --http-manage-expect to new options api 2012-02-06 17:23:22 +01:00
roberto@oneiric64 de21abb21c ported jvm plugin to the new options api 2012-02-06 17:17:26 +01:00
roberto@oneiric64 94cae4ac17 completed php porting to the new api 2012-02-06 17:01:16 +01:00
roberto@oneiric64 3b5e1f98f5 completed fastrouter porting to the new options api 2012-02-06 16:56:06 +01:00
roberto@oneiric64 594f67c6d7 added support for paste loggers 2012-02-06 16:29:04 +01:00
roberto@oneiric64 f1b415df2f completed python plugin porting to the new options api 2012-02-06 16:14:15 +01:00
roberto@oneiric64 c07e0ef581 --touch-logreopen and --touch-logrotate 2012-02-06 16:00:51 +01:00
roberto@goyle 0d4f6501b0 ported backtrace to osx 2012-02-06 11:38:56 +01:00
roberto@goyle d2cbb7eea2 allow non-pcre build 2012-02-06 11:02:57 +01:00
roberto@oneiric64 f4cb3c67c1 a series of stupid fixes 2012-02-05 11:56:50 +01:00
roberto@oneiric64 a51877cd1d another series of options fixes/porting 2012-02-05 11:50:33 +01:00
roberto@oneiric64 c0c3287f74 fully ported cgi plugin to the new options api 2012-02-05 11:44:18 +01:00
roberto@oneiric64 83378802af completed porting perl/psgi to new options api 2012-02-05 11:25:39 +01:00
roberto f05d712923 completed ruby/rack porting to the new options api 2012-02-05 11:20:19 +01:00
roberto@freebsd64 5b2df55b8e ported freebsd to the new locking api 2012-02-05 11:07:40 +01:00
roberto@oneiric64 865ec4dd8f added internal routing subsystem 2012-02-05 10:43:03 +01:00
roberto@oneiric64 6ddf1afc81 ported --http-use-cache to the new api 2012-02-04 16:20:37 +01:00
roberto@mrspurr 7bd44f4f14 added internal routing infrastructure 2012-02-04 16:10:32 +01:00
roberto@goyle a92c2003ee prepare for new routing system 2012-02-02 18:20:10 +01:00
roberto@debian64 97a8c5e4b6 another fix for pyargv 2012-02-02 11:40:52 +01:00
roberto@debian64 a5aa31f13e applied ticket #82 2012-02-02 11:25:44 +01:00
roberto@debian64 1a0161cb6b fixed pyargv 2012-02-02 11:14:34 +01:00
roberto@debian64 b8c17baf7c fixed pythonpath 2012-02-02 11:08:02 +01:00
roberto@debian64 e161ea3f0a another fix for locking 2012-02-02 11:04:51 +01:00
roberto@debian64 fb827a274b started porting rack plugin to the new options api 2012-02-02 10:29:31 +01:00
roberto@debian64 7281318ef6 fixed bug #79 2012-02-02 10:20:57 +01:00
roberto@debian64 80be7385ed fixed locking 2012-02-02 09:59:48 +01:00
roberto@debian64 8913dda413 added uwsgi_tmpname() 2012-02-02 09:07:39 +01:00
roberto@debian64 b8ad90104b another series of fastrouter patches 2012-02-02 09:01:53 +01:00
roberto@debian64 2646109986 ported --fastrouter option 2012-02-02 08:56:47 +01:00
roberto@oneiric64 cf247c828a fixed emperor reload in lazy mode 2012-02-01 17:53:50 +01:00
roberto@debian64 28106e624e fixed http protocol bug 2012-02-01 16:41:50 +01:00
roberto@debian64 30e8420342 added --cheaper-overload 2012-02-01 16:07:29 +01:00
roberto@debian64 99e4d55e9b ported pthread mutex to the new api 2012-02-01 15:32:33 +01:00
roberto@goyle f9daec9e43 implementation of lock detector 2012-02-01 14:30:26 +01:00
roberto@goyle 68a2902ce3 fixed readlink in binary path 2012-01-31 11:46:30 +01:00
roberto@goyle 4b2db3de57 started revamp of the JVM plugin 2012-01-31 11:15:05 +01:00
roberto@goyle c4c526df17 fixed gateways in non-master mode 2012-01-31 11:03:19 +01:00
roberto@goyle 15ad5531b0 another series of updates 2012-01-31 10:54:29 +01:00
roberto@goyle c0af1c1094 ported rrdtool plugin 2012-01-31 10:44:28 +01:00
roberto@goyle 9b89333244 ported lua 2012-01-31 10:40:38 +01:00
roberto@goyle 1863030078 ported ping and nagios 2012-01-31 10:38:44 +01:00
roberto@goyle 15055ffa0d ported psgi to the new api 2012-01-31 10:31:46 +01:00
roberto@oneiric64 8391ce28f7 ported max vars to new options api 2012-01-30 11:09:59 +01:00
roberto@oneiric64 b38791a357 ported chmod-socket to new options api 2012-01-30 10:46:20 +01:00
roberto@oneiric64 53ba043168 ported logdate to new options api 2012-01-30 10:37:44 +01:00
roberto@oneiric64 d46a8dba7b ported snmp to new options api 2012-01-30 10:26:28 +01:00
roberto@oneiric64 1e62afc161 ported zerg to new options api 2012-01-30 09:33:59 +01:00
roberto@oneiric64 03cf6e868f ported mule subsystem to the new options api 2012-01-30 08:26:30 +01:00
roberto@oneiri64 e1da28ccc3 ported static file serving to the new options api 2012-01-30 08:21:04 +01:00
roberto@oneiric64 4173ca36cb ported map-socket to the new api 2012-01-30 08:05:52 +01:00
roberto@oneiric64 c393de492d ported ksm 2012-01-29 08:53:08 +01:00
roberto@oneiric64 f9a716d70f fixed dynamic options 2012-01-29 08:51:45 +01:00
roberto@oneiric64 2e8655c203 ported pidfile signal to the new api 2012-01-29 08:49:07 +01:00
roberto@oneiric64 42b7164f33 ported sqlite3 to the new api 2012-01-29 08:21:33 +01:00
roberto@oneiric64 602d49b045 ported cap/unshare to the new api 2012-01-29 08:04:05 +01:00
roberto@oneiric64 58a67df534 ported uid/gid to new api 2012-01-29 07:59:56 +01:00
roberto@oneiric64 de6cc04685 added exec:// facility 2012-01-29 07:52:39 +01:00
roberto@oneiric64 33763e074d ported spooler to the new options api 2012-01-28 17:40:24 +01:00
roberto@oneiric64 32b0f8efb6 ported queue and cache to new options api 2012-01-28 17:32:34 +01:00
roberto@oneiric64 644618963a another series of options porting 2012-01-28 17:14:49 +01:00
roberto@oneiric64 97ac31376e added --never-swap 2012-01-28 17:04:37 +01:00
roberto@oneiric64 e5ec0f0221 even simpler options hook 2012-01-28 16:37:20 +01:00
roberto@oneiric64 5875ddc355 refactored first part of clustering 2012-01-28 15:42:50 +01:00
roberto@oneiric64 f7d5f4692d another series of options ported to the new api 2012-01-28 15:14:41 +01:00
roberto@oneiric64 d85bc64aa9 ported uwsgi_help to the new api 2012-01-28 09:29:57 +01:00
roberto@oneiric64 a18ed0503c implemented flag subsystem for options 2012-01-28 08:57:17 +01:00
roberto@oneiric64 77a4e3771b ported plugin loading to the new api 2012-01-28 07:40:20 +01:00
roberto@oneiric64 7523eb1cb0 ported short options to new api 2012-01-27 19:37:37 +01:00
roberto@oneiric64 46f8ee9410 ported xml config to new option/help api 2012-01-27 18:24:55 +01:00
roberto@oneiric64 f0aa9f9fd2 another part of options refactoring 2012-01-27 17:54:31 +01:00
roberto@oneiric64 73d5cadd8c massive refactoring of options management (broken, do not use this rev) 2012-01-27 16:30:00 +01:00
roberto@oneiric64 1a0e2076d5 restore termios on exit (if required) 2012-01-25 07:19:25 +01:00
roberto@oneiric64 6db3dab5ea added --pyshell-oneshot 2012-01-25 06:32:02 +01:00
roberto@oneiric64 20856549c1 fixed a double free in spooler 2012-01-24 21:33:24 +01:00
roberto@oneiric64 d570845592 fixed sigquit/sigint in hijacked mode 2012-01-24 21:13:24 +01:00
roberto@oneiric64 eed27c0aac implemented rack.input.gets and expect-continue in http router 2012-01-24 21:11:17 +01:00
roberto@oneiric64 daef139496 added --http-manage-expect 2012-01-24 18:57:29 +01:00
roberto@oneiric64 3690d836b0 another refactoring of corerouter 2012-01-23 17:36:59 +01:00
roberto@oneiric64 93faeb4177 first round of common code base for routers 2012-01-23 16:04:10 +01:00
roberto@oneiric64 095b9154e0 fixed signal handling in gateways 2012-01-23 12:33:57 +01:00
roberto@oneiric64 f86aa55220 destructive commit for http and fastrouter plugins 2012-01-23 12:13:05 +01:00
roberto@oneiric64 40f7aecbba fixed a race condition in SIGINT/SIGQUIT 2012-01-22 17:55:09 +01:00
roberto@oneiric64 5d9d67caa4 preliminary refactoring for multithreaded fastrouter/removed fastfuncs support 2012-01-22 11:48:13 +01:00
roberto@oneiric64 0f00d6fb23 added --fastrouter-post-buffering-dir 2012-01-21 17:36:15 +01:00
roberto@oneiric64 61b0e68641 added UWSGI_POSTFILE 2012-01-21 04:26:02 +01:00
roberto@oneiric64 6ed38ced3c preliminary infrastructure for fastrouter buffering 2012-01-21 03:02:09 +01:00
roberto@app2 7a681a97b5 added --exec-in-jail 2012-01-20 16:55:54 +00:00
roberto@app2 41008fa594 fix a bunch of spooler issue 2012-01-20 15:16:47 +00:00
roberto@oneiric64 fb13084b87 applied patch #76 by prymitive 2012-01-20 10:59:39 +01:00
roberto@oneiric64 3f9023281e added --exec-pre-jail and --exec-post-jail 2012-01-20 09:18:18 +01:00
roberto@oneiric64 4e21fe6607 fix uwsgi.atexit when threading mode is enabled 2012-01-18 05:01:22 +01:00
roberto@oneiric64 7a95c726cd segmentation fault manager (linux only) 2012-01-15 04:33:19 +01:00
roberto@oneiric64 940401e0f8 second round of multispooler patches 2012-01-14 06:56:11 +01:00
roberto@oneiric64 86bfb20903 applied first part of multispooler patch 2012-01-14 06:00:33 +01:00
roberto@oneiric64 e21cf87285 fixed atexit 2012-01-13 04:26:20 +01:00
roberto@oneiric64 65f1445b64 bumped to 1.1 and added uwsgi.atexit 2012-01-12 19:25:54 +01:00
roberto@oneiric64 f87761d092 fix for invalid --http address 2012-01-11 11:14:31 +01:00
roberto@oneiric64 0c712ac28d added --no-harakiri-arh 2012-01-11 05:05:15 +01:00
roberto@oneiric64 db301531d0 added uwsgi.after_req_hook 2012-01-10 20:30:46 +01:00
roberto@oneiric64 4c82a72fd5 FreeBSD9 fix 2012-01-10 19:08:00 +01:00
roberto@oneiric64 7417e582c3 a fix for subscription system 2012-01-10 18:06:46 +01:00
roberto@oneiric64 e32564c7b2 added --fastrouter-harakiri 2012-01-10 15:58:49 +01:00
roberto@oneiric64 798bc482dc fixed a leak in cgi plugin 2012-01-10 14:00:36 +01:00
roberto@oneiric64 c7e7f756bc do not build netlink support by default 2012-01-10 13:43:13 +01:00
roberto@oneiric64 24358701f7 added Roy to contributors 2012-01-06 22:03:29 +01:00
roberto@netbsd64 f1e392c0a0 added support for post_buffering in cgi plugin 2012-01-06 22:57:58 +01:00
roberto@netbsd64 5e8d38d8bc support body_as_file in cgi plugin 2012-01-06 22:21:08 +01:00
roberto@oneiric64 4650d2edbb added support for indexed cgi vars 2012-01-06 19:36:42 +01:00
roberto@oneiric64 b153033514 fixed PATH_INFO and SCRIPT_NAME in cgi plugin 2012-01-06 18:23:07 +01:00
roberto@netbsd64 6dcbce5eb7 added binary detection for NetBSD 2012-01-05 22:47:50 +01:00
roberto@oneiric64 4ceeab439a fixed a typo 2012-01-05 21:14:45 +01:00
roberto@oneiric64 8b1a6be9da various realpath fixes 2012-01-05 21:10:02 +01:00
roberto@netbsd64 baeb864075 fixed #70 2012-01-05 21:28:47 +01:00
roberto@netbsd64 c88e1c3619 realpath on BSD is different from Linux/Solaris/OSX 2012-01-05 21:25:21 +01:00
roberto@oneiric64 1b04df7c5e Added tag 1.0.1 for changeset 8fe7bb792399 2012-01-03 17:12:16 +01:00
roberto@oneiric64 237f11dba3 fixed http protocol post optimization 2012-01-03 13:44:53 +01:00
roberto@oneiric64 313f1c2f29 make some gcc OSX version happy 2012-01-02 16:53:06 +01:00
roberto@oneiric64 f0862f3bc7 Added tag 1.0 for changeset 3c7092733585 2011-12-30 08:25:31 +01:00
roberto@oneiric64 1a8850ffe5 fixed cache monitor 2011-12-28 19:36:34 +01:00
roberto@genesi e640f812ba added cache monitor from Riccardo Magliocchetti in contrib/ 2011-12-28 04:32:21 +01:00
roberto@genesi 75ea170472 report hostname in welcome.py 2011-12-27 12:18:32 +01:00
roberto@debian32 1b14b1926e dded changelog for 1.0 2011-12-27 08:18:32 +01:00
roberto@oneiric64 edaed7ab01 fixed x-accel-redirect (temp workaround) 2011-12-26 08:26:14 +01:00
roberto@oneiric64 6cceece3d7 (really) fixed fibers plugin 2011-12-26 08:18:01 +01:00
roberto@oneiric64 2add03edb8 closed bug #67 2011-12-25 23:09:54 +01:00
roberto@oneiric64 7aab9bae51 report tiem delta in idle mode 2011-12-24 11:15:18 +01:00
roberto@oneiric64 46c2c1d885 moved version string to 1.0 2011-12-23 17:47:54 +01:00
roberto@oneiric64 544e97fac0 do not export original-proc-name in uwsgi.opt 2011-12-23 12:52:27 +01:00
roberto@oneiric64 265a700498 added --cheaper-step 2011-12-22 13:23:34 +01:00
roberto@oneiric64 a657b4b0aa Added tag 1.0-rc10 for changeset af490b8c30f8 2011-12-22 07:37:45 +01:00
roberto@oneiric64 ac97c8cf34 php plugin is now in beta 2011-12-21 15:46:23 +01:00
roberto@oneiric64 545f3ee608 gratily improved the php plugin 2011-12-21 15:00:14 +01:00
roberto@oneiric64 fcd1a36420 added --static-index 2011-12-21 11:02:36 +01:00
roberto@fiorenzo 47a8ab3da9 fixed fastrouter when nodes are on non-existent unix-socket 2011-12-21 11:00:45 +01:00
roberto@oneiric64 c4375a8e7a better ordering of options 2011-12-21 09:36:06 +01:00
roberto@oneiric64 a6c5bd3bb3 fixed optional-argument support 2011-12-21 07:56:19 +01:00
roberto@oneiric64 d53127e8cf fixed Makefile after php inclusion 2011-12-20 11:57:51 +01:00
roberto@oneiric64 851dd987ab added alpha-quality php plugin 2011-12-20 11:33:03 +01:00
roberto@goyle cf582af970 added --fastrouter-zerg 2011-12-19 09:37:46 +01:00
roberto@oneiric64 d0ec331b6b do not daemonize in emperor mode 2011-12-19 07:52:42 +01:00
roberto@oneiric64 cc75f5f7b3 fixed a stupid bug in emperor 2011-12-17 22:01:45 +01:00
roberto@oneiric64 3d08b7fdd0 added --cflags as build option 2011-12-17 14:02:52 +01:00
roberto@oneiric64 7a92449fc3 another binname improvement 2011-12-16 12:17:53 +01:00
roberto@oneiric64 4b3c34469d fixed bin-name implicit plugin loading 2011-12-16 11:51:07 +01:00
roberto@oneiric64 55bf34561e detect misusage of --rails 2011-12-16 06:49:04 +01:00
roberto@oneiric64 7e79dc0405 removed a debug line in uwsgidecorators 2011-12-15 09:21:17 +01:00
roberto@oneiric64 d3053523ab completed logging pluginization 2011-12-14 10:50:25 +01:00
roberto@oneiric64 e32185cc14 added --threaded-logger 2011-12-14 09:10:26 +01:00
roberto@oneiric64 8e3e3cf27b set level to 5 in graylog2 plugin 2011-12-13 20:42:39 +01:00
roberto@oneiric64 e2cea376e8 added rsyslog plugin 2011-12-13 20:33:17 +01:00
roberto@oneiric64 2a27b66d96 ported zeromq logging to the new api 2011-12-13 19:02:58 +01:00
roberto@oneiric64 522717ca99 initial structure for logging plugins (post-1.0) 2011-12-13 18:21:23 +01:00
roberto@oneiric64 5ee106170b added contrib/cgi_python.c 2011-12-13 06:40:10 +01:00
roberto@oneiric64 d62f04a5a6 cgi loadlib 2011-12-13 06:25:18 +01:00
roberto@oneiric64 eefe5048b2 fixed threading in multiple apps 2011-12-12 17:41:49 +01:00
roberto@oneiric64 8f792fde2d export daemons infos in stats server 2011-12-12 15:15:15 +01:00
roberto@oneiric64 d8ef2d8300 added CLONE_NEWPID for future unshare() improvements 2011-12-12 13:11:50 +01:00
roberto@oneiric64 e69dd5cb6a remove unshare call() on older kernels 2011-12-12 12:54:25 +01:00
roberto@oneiric64 8acd57d87e Added tag 1.0-rc9 for changeset 5da6fe43a8c2 2011-12-12 12:03:39 +01:00
roberto@oneiric64 a42aa1a273 raise exception on rack.input gets/each 2011-12-12 11:49:28 +01:00
roberto@sirius 4b2b7ccf82 fixed rack.input in older rails releases 2011-12-12 11:46:10 +01:00
roberto@Oneiric64 e0fa180a23 --cgi-allowed-ext --cgi-unset 2011-12-11 12:01:40 +01:00
roberto@oneiric64 06ea1fcd1b better SCRIPT_NAME handling in cgi plugin 2011-12-11 11:47:23 +01:00
roberto@oneiric64 567bcc582d improved PATH_INFO in cgi plugin 2011-12-11 11:09:20 +01:00
roberto@oneiric64 844f8c71fa more apache-compliant cgi plugin 2011-12-11 10:40:23 +01:00
roberto@oneiric64 bddbbb93cd first round of improvements for the cgi plugin 2011-12-10 13:37:11 +01:00
roberto@oneiric64 310cc83d36 --exec-as-user 2011-12-09 17:56:57 +01:00
roberto@oneiric64 23dcdc5863 added linux unshare() support 2011-12-09 17:26:33 +01:00
roberto@oneiric64 1286e1835c more tolerant cache checks 2011-12-09 07:42:49 +01:00
roberto@oneiric64 613f2ed939 fixed --rails wirh ruby 1.9.2 2011-12-08 18:36:40 +01:00
roberto@oneiric64 46108f8d0c include st.h in ruby1.8 2011-12-08 08:34:40 +01:00
roberto@oneiric64 28dcfa4131 added SpoolProc class in uwsgidsl.rb 2011-12-08 08:30:25 +01:00
roberto@oneiric64 b48597d3c3 completed spooler support in ruby 2011-12-08 08:09:38 +01:00
roberto@oneiric64 fe4c6ba13e you can now write spooler tasks in ruby 2011-12-08 06:40:29 +01:00
roberto@oneiric64 4049493ffd Added tag 1.0-rc8 for changeset 365e2514cc19 2011-12-07 10:23:54 +01:00
258 changed files with 33869 additions and 18367 deletions
+13
View File
@@ -39,3 +39,16 @@ fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
3c70927335856883283fe4db448e092cecc0ccdb 1.0
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
+1
View File
@@ -17,3 +17,4 @@ Charles Duffy
Lukas Lalinsky
Steven Fernandez
Łukasz Mierzwa
Roy Marples
+92
View File
@@ -1,3 +1,95 @@
*** current ***
* 1.3
- python tracebacker
- user-governed harakiri
- simplified external plugin development
- Linux namespace mountpoint improvements
- secured subscription system
- merged routers codebase (fastrouter, http, rawrouter)
- https support in the http router
- config report at the end of uWSGI build process
- support for keepalive in the http router
- improved subscription system (multicast and unix socket)
- custom options
- graceful reloads on shared sockets
- configurable log-master buffer size
- extreme-optimizations for the stats subsystem
*** april 2012 ***
* 1.2 [20120430]
- PyPy support
- Improved gevent support with threads
- Python auto-reload subsystem
- added --spooler-max-tasks
- pthread robust mutexes support in Linux and Solaris
- posix semaphores support in FreeBSD9
- thread-safe ctime() reporting
- interval support in cron subsystem
- improved syslog support
- better management of disconnected clients
- static files serving improvements
- another set of multithreading optimizations
- minor fixes in the Rack plugin
- Upstart socket-activation support
*** march 2012 ***
* 1.1 [20120317]
- new options parser subsystem
- improved php support
- multiple spooler with multiprocessing
- segmentation fault and floating point exceptions manager
- never-swap option
- zergpool plugin
- perl/psgi multiple interpreters support
- deadlock detector
- pluggable cheaper algos
- new internal routing susbsystem
- preliminary support for config logic
- log rotation infrastructure
- support for paste loggers
- threading improvements
- plugins can now mapped to specific modifiers
- <app> tag is deprecated (use mount option)
- report startup time for apps
- reintroduced expat support
- reintroduced remote spooler plugin
- various fastrouter optimizations
- added ruby rvm support
*** december 2011 ***
* 1.0 [20111230]
- adaptive process spawning (--cheaper option)
- new control options --stop, --reload, --suspend, --resume, --pause
- stats framework
- new subscription system
- support for mime types in static file serving
- posix capablities support
- uWSGI mules and farms
- support for multiple --touch-reload options
- new logging subsystem
- new custom locking subsystem
- process name handling
- better (and faster) HTTP parser
- perl and python threading improvements
- new plugins: rrdtool, carbon, cgi, php
- various improvements in the Rack/ruby plugin
- Linux KSM support
- refactored ping and nagios plugins
- support for signals in lazy mode
- optimized static-file serving
- support for linux unshare()
*** august 2011 ***
* 0.9.9 [20110829]
-2
View File
@@ -1,2 +0,0 @@
all:
python2.4 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python2.5 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python2.6 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python2.7 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python3.0 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python3.1 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python3.2 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python uwsgiconfig.py --build pylua
+29 -2
View File
@@ -160,20 +160,35 @@ static int uwsgi_map_location(request_rec *r)
return DECLINED;
}
static void log_err(const char *file, int line, request_rec *r,
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
static void log_err(const char *file, int line, int ami, request_rec *r,
apr_status_t status, const char *msg)
{
ap_log_rerror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, status, r, "uwsgi: %s", msg);
#else
static void log_err(const char *file, int line, request_rec *r,
apr_status_t status, const char *msg)
{
ap_log_rerror(file, line, APLOG_ERR, status, r, "uwsgi: %s", msg);
#endif
}
static void log_debug(const char *file, int line, request_rec *r, const
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
static void log_debug(const char *file, int line, int ami, request_rec *r, const
char *msg)
{
/*
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, msg);
ap_log_rerror(file, line, APLOG_WARNING, APR_SUCCESS, r, "uwsgi: %s", msg);
*/
ap_log_rerror(file, line, APLOG_MODULE_INDEX, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
#else
static void log_debug(const char *file, int line, request_rec *r, const
char *msg) {
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
#endif
}
/* buffered socket implementation (buckets are overkill) */
@@ -412,7 +427,11 @@ send_headers(request_rec *r, struct sockbuff *s)
apr_table_t *t;
apr_status_t rv = 0;
apr_port_t port = 0;
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
GET_PORT(port, r->useragent_addr);
#else
GET_PORT(port, r->connection->remote_addr);
#endif
uwsgi_cfg *cfg = our_dconfig(r);
log_debug(APLOG_MARK,r, "sending headers");
@@ -430,7 +449,11 @@ send_headers(request_rec *r, struct sockbuff *s)
add_header(t, "REQUEST_METHOD", (char *) r->method);
add_header(t, "QUERY_STRING", r->args ? r->args : "");
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
add_header(t, "SERVER_SOFTWARE", ap_get_server_description());
#else
add_header(t, "SERVER_SOFTWARE", ap_get_server_version());
#endif
add_header(t, "SERVER_ADMIN", r->server->server_admin);
add_header(t, "SERVER_NAME", (char *) ap_get_server_name(r));
add_header(t, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)));
@@ -438,7 +461,11 @@ send_headers(request_rec *r, struct sockbuff *s)
add_header(t, "SERVER_PROTOCOL", r->protocol);
add_header(t, "REQUEST_URI", original_uri(r));
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
add_header(t, "REMOTE_ADDR", r->useragent_ip);
#else
add_header(t, "REMOTE_ADDR", r->connection->remote_ip);
#endif
add_header(t, "REMOTE_PORT", apr_psprintf(r->pool, "%d", port));
add_header(t, "REMOTE_USER", r->user);
add_header(t, "DOCUMENT_ROOT", (char *) ap_document_root(r));
+397
View File
@@ -0,0 +1,397 @@
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_strings.h"
#include "apr_hooks.h"
#include "apr_optional_hooks.h"
#include "apr_buckets.h"
#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h"
#include "util_script.h"
#include "mod_proxy.h"
#define UWSGI_SCHEME "uwsgi"
#define UWSGI_DEFAULT_PORT 3031
module AP_MODULE_DECLARE_DATA proxy_uwsgi_module;
static int uwsgi_canon(request_rec *r, char *url)
{
char *host, sport[sizeof(":65535")];
const char *err, *path;
apr_port_t port = UWSGI_DEFAULT_PORT;
if (strncasecmp(url, UWSGI_SCHEME "://", sizeof(UWSGI_SCHEME) + 2)) {
return DECLINED;
}
url += sizeof(UWSGI_SCHEME); /* Keep slashes */
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
if (err) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"error parsing URL %s: %s", url, err);
return HTTP_BAD_REQUEST;
}
apr_snprintf(sport, sizeof(sport), ":%u", port);
if (ap_strchr(host, ':')) { /* if literal IPv6 address */
host = apr_pstrcat(r->pool, "[", host, "]", NULL);
}
path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
r->proxyreq);
if (!path) {
return HTTP_BAD_REQUEST;
}
r->filename = apr_pstrcat(r->pool, "proxy:" UWSGI_SCHEME "://", host, sport, "/",
path, NULL);
return OK;
}
static int uwsgi_send(proxy_conn_rec *conn, const char *buf, apr_size_t length,
request_rec *r)
{
apr_status_t rv;
apr_size_t written;
while (length > 0) {
written = length;
if ((rv = apr_socket_send(conn->sock, buf, &written)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"sending data to %s:%u failed",
conn->hostname, conn->port);
return HTTP_SERVICE_UNAVAILABLE;
}
/* count for stats */
conn->worker->s->transferred += written;
buf += written;
length -= written;
}
return OK;
}
/*
* Send uwsgi header block
*/
static int uwsgi_send_headers(request_rec *r, proxy_conn_rec *conn)
{
char *buf, *ptr;
const apr_array_header_t *env_table;
const apr_table_entry_t *env;
int j;
apr_size_t headerlen = 4;
uint16_t pktsize, keylen, vallen;
ap_add_common_vars(r);
ap_add_cgi_vars(r);
const char *script_name = apr_table_get(r->subprocess_env, "SCRIPT_NAME");
const char *path_info = apr_table_get(r->subprocess_env, "PATH_INFO");
if (script_name && path_info) {
apr_table_set(r->subprocess_env, "SCRIPT_NAME", apr_pstrndup(r->pool, script_name, strlen(script_name)-strlen(path_info)));
}
env_table = apr_table_elts(r->subprocess_env);
env = (apr_table_entry_t *)env_table->elts;
for (j = 0; j < env_table->nelts; ++j) {
headerlen += 2 + strlen(env[j].key) + 2 + strlen(env[j].val) ;
}
ptr = buf = apr_palloc(r->pool, headerlen);
ptr+=4;
for (j = 0; j < env_table->nelts; ++j) {
keylen = strlen(env[j].key);
*ptr++= (uint8_t) (keylen & 0xff);
*ptr++= (uint8_t) ((keylen >> 8) & 0xff);
memcpy(ptr, env[j].key, keylen) ; ptr+=keylen;
vallen = strlen(env[j].val);
*ptr++= (uint8_t) (vallen & 0xff);
*ptr++= (uint8_t) ((vallen >> 8) & 0xff);
memcpy(ptr, env[j].val, vallen) ; ptr+=vallen;
}
pktsize = headerlen-4;
buf[0] = 0;
buf[1] = (uint8_t) (pktsize & 0xff);
buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
buf[0] = 0;
return uwsgi_send(conn, buf, headerlen, r);
}
static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
{
if (ap_should_client_block(r)) {
char *buf = apr_palloc(r->pool, AP_IOBUFSIZE);
int status;
apr_size_t readlen;
readlen = ap_get_client_block(r, buf, AP_IOBUFSIZE);
while (readlen > 0) {
status = uwsgi_send(conn, buf, readlen, r);
if (status != OK) {
return HTTP_SERVICE_UNAVAILABLE;
}
readlen = ap_get_client_block(r, buf, AP_IOBUFSIZE);
}
if (readlen == -1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"receiving request body failed");
return HTTP_INTERNAL_SERVER_ERROR;
}
}
return OK;
}
static
apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n, request_rec *r,
int fold, int *writen)
{
char *tmp_s = s;
apr_status_t rv;
apr_size_t len;
rv = ap_rgetline(&tmp_s, n, &len, r, fold, bb);
apr_brigade_cleanup(bb);
if (rv == APR_SUCCESS) {
*writen = (int) len;
} else if (rv == APR_ENOSPC) {
*writen = n;
} else {
*writen = -1;
}
return rv;
}
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
{
char buffer[HUGE_STRING_LEN];
const char *buf;
char *value, *end;
int len;
apr_status_t rc;
conn_rec *c = r->connection;
apr_off_t readbytes;
apr_status_t rv;
apr_bucket *e;
apr_read_type_e mode = APR_NONBLOCK_READ;
request_rec *rp = ap_proxy_make_fake_req(backend->connection, r);
rp->proxyreq = PROXYREQ_RESPONSE;
apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
rc = ap_proxygetline(bb, buffer, sizeof(buffer), rp, 0, &len);
if (len == 0) {
rc = ap_proxygetline(bb, buffer, sizeof(buffer), rp, 0, &len);
}
if (len <= 0) {
// oops
return HTTP_INTERNAL_SERVER_ERROR;
}
backend->worker->s->read += len;
if (!apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
// oops
return HTTP_INTERNAL_SERVER_ERROR;
}
int major, minor;
major = buffer[5] - '0';
minor = buffer[7] - '0';
/* If not an HTTP/1 message or
* if the status line was > 8192 bytes
*/
if ((major != 1) || (len >= sizeof(buffer)-1)) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
apr_pstrcat(r->pool, "Corrupt status line returned by remote "
"server: ", buffer, NULL));
}
char keepchar = buffer[12];
buffer[12] = '\0';
r->status = atoi(&buffer[9]);
if (keepchar != '\0') {
buffer[12] = keepchar;
} else {
/* 2616 requires the space in Status-Line; the origin
* server may have sent one but ap_rgetline_core will
* have stripped it. */
buffer[12] = ' ';
buffer[13] = '\0';
}
r->status_line = apr_pstrdup(r->pool, &buffer[9]);
// start parsing headers;
while ((len = ap_getline(buffer, sizeof(buffer), rp, 1)) > 0) {
value = strchr(buffer, ':');
// invalid header skip
if (!value) continue;
*value = '\0';
++value;
while (apr_isspace(*value)) ++value;
for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end) *end = '\0';
apr_table_add(r->headers_out, buffer, value);
}
if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
ap_set_content_type(r, apr_pstrdup(r->pool, buf));
}
for(;;) {
rv = ap_get_brigade(rp->input_filters, bb,
AP_MODE_READBYTES, mode,
conf->io_buffer_size);
if (APR_STATUS_IS_EAGAIN(rv)
|| (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb))) {
e = apr_bucket_flush_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
if (ap_pass_brigade(r->output_filters, bb) || c->aborted) {
break;
}
apr_brigade_cleanup(bb);
mode = APR_BLOCK_READ;
continue;
}
else if (rv == APR_EOF) {
break;
}
else if (rv != APR_SUCCESS) {
ap_proxy_backend_broke(r, bb);
ap_pass_brigade(r->output_filters, bb);
}
mode = APR_NONBLOCK_READ;
apr_brigade_length(bb, 0, &readbytes);
backend->worker->s->read += readbytes;
ap_pass_brigade(r->output_filters, bb);
apr_brigade_cleanup(bb);
}
e = apr_bucket_eos_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
ap_pass_brigade(r->output_filters, bb);
apr_brigade_cleanup(bb);
return OK;
}
static int uwsgi_handler(request_rec *r, proxy_worker *worker,
proxy_server_conf *conf, char *url,
const char *proxyname, apr_port_t proxyport)
{
int status;
proxy_conn_rec *backend = NULL;
apr_pool_t *p = r->pool;
apr_uri_t *uri = apr_palloc(r->pool, sizeof(*uri));
char server_portstr[32];
if (strncasecmp(url, UWSGI_SCHEME "://", sizeof(UWSGI_SCHEME) + 2)) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"declining URL %s", url);
return DECLINED;
}
// ADD PATH_INFO
apr_table_add(r->subprocess_env, "PATH_INFO", url+strlen(worker->name));
/* Create space for state information */
status = ap_proxy_acquire_connection(UWSGI_SCHEME, &backend, worker,
r->server);
if (status != OK) {
goto cleanup;
}
backend->is_ssl = 0;
/* Step One: Determine Who To Connect To */
status = ap_proxy_determine_connection(p, r, conf, worker, backend,
uri, &url, proxyname, proxyport,
server_portstr, sizeof(server_portstr));
if (status != OK) {
goto cleanup;
}
/* Step Two: Make the Connection */
if (ap_proxy_connect_backend(UWSGI_SCHEME, backend, worker, r->server)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"failed to make connection to backend: %s:%u",
backend->hostname, backend->port);
status = HTTP_SERVICE_UNAVAILABLE;
goto cleanup;
}
/* Step Three: Create conn_rec */
if (!backend->connection) {
if ((status = ap_proxy_connection_create(UWSGI_SCHEME, backend,
r->connection, r->server)) != OK)
goto cleanup;
}
/* Step Four: Process the Request */
if ( ((status = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK)
|| ((status = uwsgi_send_headers(r, backend)) != OK)
|| ((status = uwsgi_send_body(r, backend)) != OK)
|| ((status = uwsgi_response(r, backend, conf)) != OK)) {
goto cleanup;
}
cleanup:
if (backend) {
backend->close = 1; /* always close the socket */
ap_proxy_release_connection(UWSGI_SCHEME, backend, r->server);
}
return status;
}
static void register_hooks(apr_pool_t *p)
{
proxy_hook_scheme_handler(uwsgi_handler, NULL, NULL, APR_HOOK_FIRST);
proxy_hook_canon_handler(uwsgi_canon, NULL, NULL, APR_HOOK_FIRST);
}
module AP_MODULE_DECLARE_DATA proxy_uwsgi_module = {
STANDARD20_MODULE_STUFF,
NULL, /* create per-directory config structure */
NULL, /* merge per-directory config structures */
NULL, /* create per-server config structure */
NULL, /* merge per-server config structures */
NULL, /* command table */
register_hooks /* register hooks */
};
+29 -3
View File
@@ -2,7 +2,7 @@
*** uWSGI/mod_uwsgi ***
Copyright 2009-2011 Unbit S.a.s. <info@unbit.it>
Copyright 2009-2012 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -37,11 +37,18 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
*/
#include <unistd.h>
#include <ctype.h>
#include "apr_strings.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "httpd.h"
#include "http_core.h"
#include "http_protocol.h"
#include "http_config.h"
#include "http_log.h"
#include "util_script.h"
#include <sys/socket.h>
#include <sys/un.h>
@@ -346,7 +353,11 @@ static int uwsgi_handler(request_rec *r) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->useragent_ip, &pkt_size) ;
#else
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
#endif
//
if (r->user) {
@@ -356,7 +367,7 @@ static int uwsgi_handler(request_rec *r) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", "", &pkt_size) ;
}
if (r->user) {
if (ap_auth_type(r) != NULL) {
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) ;
@@ -506,7 +517,22 @@ static int uwsgi_handler(request_rec *r) {
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
if (!c->cgi_mode) {
b = apr_bucket_transient_create(buf, cnt, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
b = apr_bucket_flush_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS) {
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
free(uwsgi_vars);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_brigade_cleanup(bb);
}
else {
apr_brigade_write(bb, NULL, NULL, buf, cnt);
}
}
else {
// EOF
+45
View File
@@ -0,0 +1,45 @@
[uwsgi]
xml = auto
ini = true
yaml = true
json = auto
sqlite3 = auto
zeromq = auto
snmp = true
spooler = true
embedded = true
ssl = auto
udp = true
multicast = true
threading = true
sendfile = true
minterpreters = true
async = true
ldap = auto
pcre = auto
routing = auto
ipv6 = false
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, router_rewrite, router_http
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = cgi
inherit = base
+2 -1
View File
@@ -1,3 +1,4 @@
[uwsgi]
inherit = default
main_plugin =
inherit = base
embedded_plugins = null
+2 -43
View File
@@ -1,44 +1,3 @@
[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
main_plugin = python
inherit = base
+2 -1
View File
@@ -1,3 +1,4 @@
[uwsgi]
inherit = default
main_plugin = python
inherit = base
embed_files = bootstrap3.py,django.zip,djapp.zip
+2 -1
View File
@@ -1,4 +1,5 @@
[uwsgi]
inherit = default
main_plugin = python
inherit = base
embed_files = embedme.py,uwsgidecorators.py
+2 -2
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,erlang
main_plugin = erlang
inherit = base
+2 -2
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, gevent
main_plugin = python,gevent
inherit = base
+1 -1
View File
@@ -1,5 +1,5 @@
[uwsgi]
inherit = default
inherit = base
bin_name = libuwsgi.so
embedded_plugins = null
as_shared_library = true
+2 -2
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = lua
main_plugin = lua
inherit = base
+2 -1
View File
@@ -1,3 +1,4 @@
[uwsgi]
inherit = default
main_plugin =
inherit = base
plugins = lua
+1 -1
View File
@@ -1,5 +1,5 @@
[uwsgi]
inherit = default
inherit = base
plugins = python, ping, rack, psgi, cache, http, fastrouter
plugin_dir = plugins
embedded_plugins = null
+2 -2
View File
@@ -1,4 +1,4 @@
[uwsgi]
inherit = default
inherit = base
plugin_dir = /usr/lib/uwsgi
embedded_plugins = null
embedded_plugins =
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = php
inherit = base
+2 -2
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = psgi
main_plugin = psgi
inherit = base
+2 -2
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,erlang,pyerl
main_plugin = python,erlang,pyerl
inherit = base
+2 -2
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,lua
main_plugin = python,lua
inherit = base
+2 -4
View File
@@ -1,5 +1,3 @@
[uwsgi]
inherit = default
bin_name = libuwsgi.so
embedded_plugins = symcall
as_shared_library = true
main_plugin = pypy
inherit = base
-1
View File
@@ -2,7 +2,6 @@
xml = true
ini = true
snmp = true
sctp = false
erlang = false
spooler = true
embedded = true
+2 -2
View File
@@ -1,5 +1,5 @@
[uwsgi]
inherit = default
main_plugin = pyuwsgi
inherit = base
bin_name = pyuwsgi.so
embedded_plugins = pyuwsgi,python,ping,cache,nagios,rpc,ugreen
as_shared_library = true
+2 -2
View File
@@ -1,3 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = rack, ping, cache, nagios, rpc, fastrouter, http, ugreen
main_plugin = rack
inherit = base
-1
View File
@@ -3,7 +3,6 @@ xml = true
ini = true
yaml = true
snmp = true
sctp = false
erlang = false
spooler = false
embedded = false
+4 -5
View File
@@ -2,11 +2,10 @@
xml = true
ini = true
yaml = true
json = true
json = false
sqlite3 = false
zeromq = false
snmp = false
sctp = false
spooler = true
embedded = true
udp = true
@@ -15,12 +14,12 @@ threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = true
pcre = false
pcre = true
routing = true
debug = false
unbit = true
xml_implementation = libxml2
xml_implementation = expat
yaml_implementation = auto
malloc_implementation = libc
plugins =
+44
View File
@@ -0,0 +1,44 @@
[uwsgi]
xml = false
ini = true
yaml = false
json = false
sqlite3 = false
zeromq = false
snmp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = false
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins =
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+12
View File
@@ -0,0 +1,12 @@
use POSIX;
use IO::Socket::INET;
use IO::Socket::INET6;
my $s = IO::Socket::INET->new(LocalAddr => '127.0.0.1', LocalPort => 1717, Proto => 'tcp', Reuse => 1);
my $s2 = IO::Socket::INET->new(LocalAddr => '127.0.0.1', LocalPort => 3022, Proto => 'tcp', Reuse => 1);
my $s3 = IO::Socket::INET6->new(LocalAddr => '::', LocalPort => 3017, Proto => 'tcp', Reuse => 1);
dup2($s->fileno, 17);
dup2($s2->fileno, 22);
dup2($s3->fileno, 30);
exec './uwsgi','-M', '--socket','fd://17', '--http-socket','fd://22', '--socket','fd://30';
+53
View File
@@ -0,0 +1,53 @@
#include <Python.h>
void uwsgi_cgi_load_python() {
Py_Initialize();
}
void uwsgi_cgi_run_python(char *filename) {
char **e, *p;
PyObject *k, *env_value;
FILE *fp = fopen(filename, "r");
PySys_SetArgv(1, &filename);
PyObject *os_module = PyImport_ImportModule("os");
if (os_module) {
PyObject *os_module_dict = PyModule_GetDict(os_module);
PyObject *py_environ = PyDict_GetItemString(os_module_dict, "environ");
if (py_environ) {
for (e = environ; *e != NULL; e++) {
p = strchr(*e, '=');
if (p == NULL) continue;
k = PyString_FromStringAndSize(*e, (int)(p-*e));
if (k == NULL) {
PyErr_Print();
continue;
}
env_value = PyString_FromString(p+1);
if (env_value == NULL) {
PyErr_Print();
Py_DECREF(k);
continue;
}
if (PyObject_SetItem(py_environ, k, env_value)) {
PyErr_Print();
}
Py_DECREF(k);
Py_DECREF(env_value);
}
}
}
PyRun_AnyFileEx(fp, filename, 1);
}
+114
View File
@@ -0,0 +1,114 @@
require 'sinatra'
require 'socket'
require 'json'
module EmperorStats
def self.uwsgi_get_stats(server)
parts = server.split(':')
if parts.length > 1
s = TCPSocket.open(parts[0], parts[1])
else
s = UNIXSocket.open(server)
end
return JSON.parse(s.read())
end
end
template = <<eof
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%=@title%></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="unbit">
<link href="http://unbit.github.com/bootstrap/css/bootstrap.css" rel="stylesheet">
<style>
body {
padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
}
</style>
<link href="http://unbit.github.com/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="#"><%=@title%></a>
</div>
</div>
</div>
<div class="container">
<hr/>
<h1>Emperor: <%=@stats['emperor']%></h1>
<hr/>
<div class="row">
<div class="span8">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>name</th><th>pid</th><th>first run</th>
<th>last respawn</th>
<th>last heartbeat</th>
<th>loyal</th>
<th>respawns</th>
<% if @stats['emperor_tyrant'] == 1 %>
<th>uid</th>
<th>gid</th>
<% end %>
</tr>
</thead>
<% for vassal in @stats['vassals'] %>
<tr>
<td><%=vassal['id']%></td>
<td><%=vassal['pid']%></td>
<td><%=Time.at(vassal['first_run']).strftime("%d %b %Y %H:%M:%S")%></td>
<td><%=Time.at(vassal['last_run']).strftime("%d %b %Y %H:%M:%S")%></td>
<td><% if vassal['last_heartbeat'] > 0 %><%=Time.at(vassal['last_heartbeat']).strftime("%d %b %Y %H:%M:%S")%><% end %></td>
<td><% if vassal['loyal'] > 0 %><%=Time.at(vassal['last_loyal']).strftime("%d %b %Y %H:%M:%S")%><% end %></td>
<td><%=vassal['respawns']%></td>
<% if @stats['emperor_tyrant'] == 1 %>
<td><%=vassal['uid']%></td>
<td><%=vassal['gid']%></td>
<% end %>
</tr>
<% end %>
</table>
</div>
<div class="span4">
<h3>blacklist</h3>
<table class="table table-striped table-bordered">
<thead>
<tr><th>name</th><th>throttle</th></tr>
<% for bli in @stats['blacklist'] %>
<tr>
<td><%=bli['id']%></td>
<td><%=bli['throttle_level']%></td>
</tr>
<% end %>
</thead>
</table>
</div>
</div>
<script src="http://unbit.github.com/jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="http://unbit.github.com/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
</body>
</html>
eof
get '/' do
@stats = EmperorStats::uwsgi_get_stats(ENV['EMPEROR'])
@title = 'uWSGI Emperor monitor'
erb template
end
run Sinatra::Application
+15
View File
@@ -0,0 +1,15 @@
use IO::Socket::INET;
my $s = IO::Socket::INET->new(PeerAddr => '127.0.0.1', PeerPort => $ARGV[0]);
my $mountpoint = $ARGV[1];
my $app = $ARGV[2];
my $uwsgi_appid = pack('v', length('UWSGI_APPID')).'UWSGI_APPID'.pack('v', length($mountpoint)).$mountpoint;
my $uwsgi_script = pack('v', length('UWSGI_SCRIPT')).'UWSGI_SCRIPT'.pack('v', length($app)).$app;
$s->send(pack('CvC', 5, length($uwsgi_appid.$uwsgi_script),0).$uwsgi_appid.$uwsgi_script);
while((my $cnt = $s->recv(my $buf, 4096))> 0) {
print $buf;
}
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/perl
use Crypt::OpenSSL::RSA;
use IO::Socket::INET;
open PK,$ARGV[3];
my @lines = <PK>;
close PK;
$rsa_priv = Crypt::OpenSSL::RSA->new_private_key(join('',@lines));
my %items = {};
$items{'key'} = $ARGV[1];
$items{'address'} = $ARGV[2];
my $uwsgi_pkt = '';
foreach(keys %items) {
$uwsgi_pkt .= pack('v', length($_)).$_.pack('v', length($items{$_})).$items{$_};
}
my $unix_check = time();
$uwsgi_pkt .= pack('v', 4).'unix'.pack('v', length($unix_check)).$unix_check;
my $signature = $rsa_priv->sign($uwsgi_pkt);
$uwsgi_pkt .= pack('v', 4).'sign'.pack('v', length($signature)).$signature;
my $udp = new IO::Socket::INET(PeerAddr => $ARGV[0], Proto => 'udp');
$udp->send(pack('CvC', 224, length($uwsgi_pkt), 0).$uwsgi_pkt);
print ''.(length($uwsgi_pkt)+4).' bytes sent to '.$ARGV[0]."\n";
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/perl
use IO::Socket::INET;
my %items = {};
$items{'key'} = $ARGV[1];
$items{'address'} = $ARGV[2];
my $uwsgi_pkt = '';
foreach(keys %items) {
$uwsgi_pkt .= pack('v', length($_)).$_.pack('v', length($items{$_})).$items{$_};
}
my $udp = new IO::Socket::INET(PeerAddr => $ARGV[0], Proto => 'udp');
$udp->send(pack('CvC', 224, length($uwsgi_pkt), 0).$uwsgi_pkt);
print ''.(length($uwsgi_pkt)+4).' bytes sent to '.$ARGV[0]."\n";
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
COMMAND=./uwsgi
CONFIG_FILE=
FIRST=0
for ARG in $@;do
if [ $FIRST -eq 0 ];then
FIRST=1
else
ARGS="$ARGS $ARG"
fi
done
export UWSGI_INHERIT=CONFIG_FILE
export UWSGI_PYRUN=$1
export UWSGI_PYARGV=$ARGS
exec $COMMAND
+123
View File
@@ -0,0 +1,123 @@
import mmap
import os
import struct
import array
import time
import sys
from optparse import OptionParser
class Cache:
def __init__(self, filename, cache_slots, block_size=65536, sample_sleep=1):
self.block_size = block_size
self.cache_slots = cache_slots
self.key_size = 2048
self.item_size = 2 + 2 + 4 + 8 + 8 + 8 + 8 + 8 + self.key_size
self.block_size_start = self.item_size * self.cache_slots
fd = os.open(filename, os.O_RDONLY)
self.cache_store = mmap.mmap(fd, 0, mmap.MAP_SHARED, mmap.PROT_READ)
self.sample_sleep = sample_sleep
self.samples = 0
self.history = []
self.cache_full = 0
self.cache_empty = 0
self.cache_items = 0
self.block_sizes = 0
def store_read_item_block(self, position):
pos = self.cache_store.tell()
# uwsgi cache stores cache entries first and then the blocks
self.cache_store.seek(self.block_size_start + (position * self.block_size))
buf = self.cache_store.read(self.block_size)
self.cache_store.seek(pos)
return buf
def store_read_item(self, position):
buf = self.cache_store.read(self.item_size)
fields = struct.unpack_from('@HHIQQQQQ2048c', buf)
key = array.array('c', fields[8:self.key_size+8]).tostring().rstrip('\x00')
if [x for x in key if x!= '\x00']:
buf = self.store_read_item_block(position)
value = array.array('c', buf).tostring().rstrip('\x00')
else:
value = ''
return (position, key, value, len(value))
def read(self):
data = [self.store_read_item(i) for i in range(self.cache_slots)]
self.cache_store.seek(0)
self.update_stats(data)
if self.sample_sleep:
time.sleep(self.sample_sleep)
return data
def update_stats(self, data):
# data is a list of (position, key, value, len(value)) tuples
items = len([1 for x in data if x[3] > 0])
self.cache_items += items
full, empty = items == self.cache_slots, items == 0
if full:
self.cache_full += 1
if empty:
self.cache_empty += 1
self.samples += 1
block_sizes = sum([x[3] for x in data])
self.block_sizes += block_sizes
self.history.append({'full': full, 'empty': empty, 'data': data, \
'items': items, 'block_sizes': block_sizes})
def dump(self):
return {
'samples': self.samples,
'history': self.history,
'cache_slots': self.cache_slots,
'sample_sleep': self.sample_sleep,
'cache_empty': self.cache_empty,
'cache_full': self.cache_full,
'cache_items': self.cache_items,
'block_sizes': self.block_sizes,
}
def show_dump(self):
d = self.dump()
print
print "Recorded %d samples (%d second(s) sleep between samples)" % \
(d['samples'], d['sample_sleep'])
print "Cache empty %d times, full %d times, %.2f items on average" % \
(d['cache_empty'], d['cache_full'], d['cache_items'] / d['samples'])
print "Block size average size: %d bytes" % \
(d['block_sizes'] / d['cache_items'] * 8)
print "Data in cache average: %d bytes" % \
(d['block_sizes'] / d['samples'] * 8)
def main(options):
cache = Cache(options.cache_store, options.cache_slots, options.block_size,
options.sleep_time)
print "Recording..."
while True:
try:
data = cache.read()
except KeyboardInterrupt:
cache.show_dump()
sys.exit(0)
if __name__ == '__main__':
parser = OptionParser()
parser.add_option("-s", "--cache-slots", dest="cache_slots", type="int",
help="Slots available in the cache, uwsgi cache option")
parser.add_option("-c", "--cache-store", dest="cache_store", default="uwsgi.cache",
help="The filename of the cache store, uwsgi cache-store option. Default: uwsgi.cache")
parser.add_option("-b", "--block-size", dest="block_size", default=65536, type="int",
help="The size of the cache block, uwsgi cache-blocksize option. Default: 65536")
parser.add_option("-t", "--sleep-time", dest="sleep_time", default=1, type="int",
help="The time to sleep between each sample. Default: 1")
(options, args) = parser.parse_args()
if not options.cache_slots:
parser.error('Option -s / --cache-slots is mandatory')
main(options)
+96
View File
@@ -0,0 +1,96 @@
require 'sinatra'
require 'socket'
require 'json'
module USubscribers
def self.uwsgi_get_stats(server)
parts = server.split(':')
if parts.length > 1
s = TCPSocket.open(parts[0], parts[1])
else
s = UNIXSocket.open(server)
end
return JSON.parse(s.read())
end
end
template = <<eof
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%=@title%></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="unbit">
<link href="http://unbit.github.com/bootstrap/css/bootstrap.css" rel="stylesheet">
<style>
body {
padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
}
</style>
<link href="http://unbit.github.com/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="#"><%=@title%></a>
</div>
</div>
</div>
<% for server in @servers.keys %>
<div class="container">
<hr/>
<h1>SubscriptionServer: <%=server%></h1>
<hr/>
<div class="row">
<% for pool in @servers[server] %>
<div class="span6">
<h3><%=pool['key']%> (<%=pool['hits']%> hits)</h3>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>node</th><th>load</th><th>requests</th>
<th>last check</th>
<th>fail count</th>
</tr>
</thead>
<% for node in pool['nodes'] %>
<tr>
<td><%=node['name']%></td><td><%=node['load']%></td><td><%=node['requests']%></td>
<td><%=Time.at(node['last_check']).strftime("%d-%m-%Y %H:%M:%S")%></td>
<td><%=node['failcnt']%></td>
</tr>
<% end %>
</table>
</div>
<% end %>
</div>
</div>
<% end %>
<script src="http://unbit.github.com/jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="http://unbit.github.com/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
</body>
</html>
eof
get '/' do
@servers = {}
for server in ENV['U_SERVERS'].split(',')
stats = USubscribers::uwsgi_get_stats(server)
if stats
@servers[server] = stats['subscriptions']
end
end
@title = 'uWSGI subscriptions viewer'
erb template
end
run Sinatra::Application
+47 -16
View File
@@ -2,6 +2,29 @@
extern struct uwsgi_server uwsgi;
void uwsgi_async_init() {
int i;
uwsgi.async_queue = event_queue_init();
if (uwsgi.async_queue < 0) {
exit(1);
}
uwsgi_add_sockets_to_queue(uwsgi.async_queue, -1);
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
for (i = 0; i < uwsgi.async; i++) {
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
}
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
}
struct wsgi_request *find_wsgi_req_proto_by_fd(int fd) {
return uwsgi.async_proto_fd_table[fd];
}
@@ -76,7 +99,7 @@ struct wsgi_request *find_first_available_wsgi_req() {
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
time_t current_time = time(NULL);
time_t current_time = uwsgi_now();
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
@@ -150,7 +173,7 @@ void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
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);
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now()+timeout, wsgi_req);
}
}
@@ -214,6 +237,7 @@ void *async_loop(void *arg1) {
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.my_signal_socket);
}
// set a default request manager
@@ -230,7 +254,7 @@ void *async_loop(void *arg1) {
timeout = 0;
}
if (min_timeout) {
timeout = min_timeout->key - time(NULL);
timeout = min_timeout->key - uwsgi_now();
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
@@ -253,6 +277,12 @@ void *async_loop(void *arg1) {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
continue;
}
is_a_new_connection = 0;
// new request coming in ?
@@ -266,12 +296,12 @@ void *async_loop(void *arg1) {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
now = time(NULL);
now = uwsgi_now();
if (now > last_now) {
uwsgi_log("async queue is full !!!\n");
last_now = now;
}
break;;
break;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock );
@@ -289,15 +319,15 @@ void *async_loop(void *arg1) {
// 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;
}
}
/* re-set blocking socket */
int arg = uwsgi_sock->arg;
arg &= (~O_NONBLOCK);
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, 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)) {
@@ -336,8 +366,9 @@ void *async_loop(void *arg1) {
runqueue_push(uwsgi.wsgi_req);
continue;
}
else if (proto_parser_status == -1) {
uwsgi_log("error parsing request\n");
else if (proto_parser_status < 0) {
if (proto_parser_status == -1)
uwsgi_log("error parsing request\n");
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
close(interesting_fd);
continue;
+68
View File
@@ -0,0 +1,68 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_buffer *uwsgi_buffer_new(size_t len) {
struct uwsgi_buffer *ub = uwsgi_calloc(sizeof(struct uwsgi_buffer));
if (len) {
ub->buf = uwsgi_malloc(len);
ub->len = len;
}
return ub;
}
int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
size_t remains = ub->len - ub->pos;
if (len > remains) {
char *new_buf = realloc(ub->buf, ub->len + UMAX(len, (size_t) uwsgi.page_size));
if (!new_buf) {
uwsgi_error("realloc()");
return -1;
}
}
memcpy(ub->buf + ub->pos, buf, len);
ub->pos += len;
return 0;
}
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
if (ub->buf) free(ub->buf);
free(ub);
}
int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
size_t remains = ub->pos;
char *ptr = ub->buf;
while(remains > 0) {
int ret = uwsgi_waitfd_write(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret > 0) {
ssize_t len = write(fd, ptr, remains);
if (len > 0) {
ptr += len;
remains -= len;
}
else if (len == 0) {
return -1;
}
else {
uwsgi_error("write()");
return -1;
}
}
else if (ret == 0) {
uwsgi_log("timeout while sending buffer !!!\n");
return -1;
}
else {
return -1;
}
}
return 0;
}
+36 -16
View File
@@ -6,12 +6,7 @@ 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_blocksize = UMAX16;
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) {
@@ -88,10 +83,10 @@ void uwsgi_init_cache() {
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
uwsgi.cache_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.cache_lock);
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
uwsgi_log("*** Cache subsystem initialized: %dMB 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));
uwsgi_log("*** Cache subsystem initialized: %dMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n", ((uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024),
(unsigned long long) sizeof(struct uwsgi_cache_item), (unsigned long long) sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, (unsigned long long) uwsgi.cache_blocksize * uwsgi.cache_max_items);
}
uint32_t djb33x_hash(char *key, int keylen) {
@@ -116,13 +111,14 @@ inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint64_t slot = uwsgi.cache_hashtable[hash_key];
struct uwsgi_cache_item *uci;
uint64_t rounds = 0;
//uwsgi_log("found slot %d for key %d\n", slot, hash_key);
uci = &uwsgi.cache_items[slot];
// first round
if (uci->djbhash != hash) goto cycle;
if (uci->djbhash != hash) return 0;
if (uci->keysize != keylen) goto cycle;
if (memcmp(uci->key, key, keylen)) goto cycle;
@@ -132,7 +128,20 @@ cycle:
while(uci->next) {
slot = uci->next;
uci = &uwsgi.cache_items[slot];
if (uci->djbhash != hash) continue;
rounds++;
if (rounds > uwsgi.cache_max_items) {
uwsgi_log("ALARM !!! cache-loop (and potential deadlock) detected slot = %llu prev = %llu next = %llu\n", uci->next, slot, uci->prev, uci->next);
// terrible case: the whole uWSGI stack can deadlock, leaving only the master alive
// if the master is avalable, trigger a brutal reload
if (uwsgi.master_process) {
kill(uwsgi.workers[0].pid, SIGTERM);
}
// otherwise kill the current worker (could be pretty useless...)
else {
exit(1);
}
}
if (uci->djbhash != hash) return 0;
if (uci->keysize != keylen) continue;
if (!memcmp(uci->key, key, keylen)) return slot;
}
@@ -159,13 +168,14 @@ char *uwsgi_cache_get(char *key, uint16_t keylen, uint64_t *valsize) {
return NULL;
}
int uwsgi_cache_del(char *key, uint16_t keylen) {
int uwsgi_cache_del(char *key, uint16_t keylen, uint64_t index) {
uint64_t index = 0;
struct uwsgi_cache_item *uci;
int ret = -1;
index = uwsgi_cache_get_index(key, keylen);
if (!index)
index = uwsgi_cache_get_index(key, keylen);
if (index) {
uci = &uwsgi.cache_items[index] ;
uci->keysize = 0;
@@ -182,9 +192,15 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
if (uci->prev) {
uwsgi.cache_items[uci->prev].next = uci->next;
}
else {
// set next as the new entry point (could be 0)
uwsgi.cache_hashtable[uci->djbhash % 0xffff] = uci->next;
}
if (uci->next) {
uwsgi.cache_items[uci->next].prev = uci->prev;
}
if (!uci->prev && !uci->next) {
// reset hashtable entry
//uwsgi_log("!!! resetted hashtable entry !!!\n");
@@ -193,6 +209,7 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
uci->djbhash = 0;
uci->prev = 0;
uci->next = 0;
uci->expires = 0;
}
return ret;
@@ -252,7 +269,7 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
}
}
uci = &uwsgi.cache_items[index] ;
if (expires) expires += time(NULL);
if (expires) expires += uwsgi_now();
uci->expires = expires;
uci->djbhash = djb33x_hash(key, keylen);
uci->hits = 0;
@@ -267,6 +284,9 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
ret = 0;
// now put the value in the 16bit hashtable
slot = uci->djbhash % 0xffff;
// reset values
uci->prev = 0;
uci->next = 0;
if (uwsgi.cache_hashtable[slot] == 0) {
uwsgi.cache_hashtable[slot] = index;
@@ -287,7 +307,7 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = &uwsgi.cache_items[index] ;
if (expires) {
expires += time(NULL);
expires += uwsgi_now();
uci->expires = expires;
}
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
+46
View File
@@ -0,0 +1,46 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
// in the future we will need to use the best clock source for each os/system
time_t uwsgi_now() {
return uwsgi.clock->seconds();
}
uint64_t uwsgi_micros() {
return uwsgi.clock->microseconds();
}
void uwsgi_register_clock(struct uwsgi_clock *clock) {
struct uwsgi_clock *clocks = uwsgi.clocks;
clock->next = NULL;
if (!clocks) {
uwsgi.clocks = clock;
return;
}
while(clocks) {
if (!clocks->next) {
clocks->next = clock;
return;
}
clocks = clocks->next;
}
}
void uwsgi_set_clock(char *name) {
struct uwsgi_clock *clocks = uwsgi.clocks;
while(clocks) {
if (!strcmp(name, clocks->name)) {
uwsgi.clock = clocks;
return;
}
clocks = clocks->next;
}
uwsgi_log("unable to set \"%s\" clock\n", name);
exit(1);
}
+113 -4
View File
@@ -2,7 +2,15 @@
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_UDP
static void cluster_manage_opt(char *key, uint16_t keylen, char *value, uint16_t vallen, void *foobar) {
add_exported_option( uwsgi_concat2n(key, keylen, "", 0), uwsgi_concat2n(value, vallen, "", 0), 0);
}
void cluster_setup() {
int rlen;
@@ -31,7 +39,7 @@ void cluster_setup() {
else if (rlen > 0) {
// receive the packet
char clusterbuf[4096];
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, manage_string_opt, NULL)) {
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
uwsgi_configure();
goto options_parsed;
}
@@ -79,7 +87,7 @@ void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
if (ucn->name[0] != 0) {
if (!strcmp(ucn->name, nucn->name)) {
ucn->status = UWSGI_NODE_OK;
ucn->last_seen = time(NULL);
ucn->last_seen = uwsgi_now();
// update requests
ucn->requests = nucn->requests;
return;
@@ -114,7 +122,7 @@ void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
tcp_port[0] = ':';
}
ucn->last_seen = time(NULL);
ucn->last_seen = uwsgi_now();
ucn->requests = nucn->requests;
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
return;
@@ -316,7 +324,7 @@ char *uwsgi_cluster_best_node() {
return NULL;
}
uwsgi.shared->nodes[best_node].last_choosen = time(NULL);
uwsgi.shared->nodes[best_node].last_choosen = uwsgi_now();
return uwsgi.shared->nodes[best_node].name;
}
@@ -351,5 +359,106 @@ void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t val
}
}
void manage_cluster_message(char *cluster_opt_buf, int cluster_opt_size) {
struct uwsgi_cluster_node nucn;
switch (uwsgi.workers[0].cores[0].req.uh.modifier1) {
case 95:
memset(&nucn, 0, sizeof(struct uwsgi_cluster_node));
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.wsgi_requests[0]->uh.pktsize);
#endif
uwsgi_hooked_parse(uwsgi.workers[0].cores[0].req.buffer, uwsgi.workers[0].cores[0].req.uh.pktsize, manage_cluster_announce, &nucn);
if (nucn.name[0] != 0) {
uwsgi_cluster_add_node(&nucn, CLUSTER_NODE_DYNAMIC);
}
break;
case 96:
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.wsgi_requests[0]->uh.pktsize);
#endif
uwsgi_log_verbose("%.*s\n", uwsgi.workers[0].cores[0].req.uh.pktsize, uwsgi.workers[0].cores[0].req.buffer);
break;
case 98:
if (kill(getpid(), SIGHUP)) {
uwsgi_error("kill()");
}
break;
case 99:
if (uwsgi.cluster_nodes)
break;
if (uwsgi.workers[0].cores[0].req.uh.modifier2 == 0) {
uwsgi_log("requested configuration data, sending %d bytes\n", cluster_opt_size);
sendto(uwsgi.cluster_fd, cluster_opt_buf, cluster_opt_size, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr));
}
break;
case 73:
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.workers[0].cores[0].req.uh.pktsize);
#endif
uwsgi_log_verbose("[uWSGI cluster %s] new node available: %.*s\n", uwsgi.cluster, uwsgi.workers[0].cores[0].req.uh.pktsize, uwsgi.workers[0].cores[0].req.buffer);
break;
}
}
#endif
char *uwsgi_setup_clusterbuf(size_t *size) {
size_t cluster_opt_size = 4;
int i;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
//uwsgi_log("%s\n", uwsgi.exported_opts[i]->key);
cluster_opt_size += 2 + strlen(uwsgi.exported_opts[i]->key);
if (uwsgi.exported_opts[i]->value) {
cluster_opt_size += 2 + strlen(uwsgi.exported_opts[i]->value);
}
else {
cluster_opt_size += 2 + 1;
}
}
//uwsgi_log("cluster opts size: %d\n", cluster_opt_size);
char *cluster_opt_buf = uwsgi_malloc(cluster_opt_size);
struct uwsgi_header *uh = (struct uwsgi_header *) cluster_opt_buf;
uh->modifier1 = 99;
uh->pktsize = cluster_opt_size - 4;
uh->modifier2 = 1;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(uh->pktsize);
#endif
char *cptrbuf = cluster_opt_buf + 4;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
//uwsgi_log("%s\n", uwsgi.exported_opts[i]->key);
uint16_t ustrlen = strlen(uwsgi.exported_opts[i]->key);
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(cptrbuf, uwsgi.exported_opts[i]->key, ustrlen);
cptrbuf += ustrlen;
if (uwsgi.exported_opts[i]->value) {
ustrlen = strlen(uwsgi.exported_opts[i]->value);
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(cptrbuf, uwsgi.exported_opts[i]->value, ustrlen);
}
else {
ustrlen = 1;
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
*cptrbuf = '1';
}
cptrbuf += ustrlen;
}
return cluster_opt_buf;
}
+1340
View File
File diff suppressed because it is too large Load Diff
+58 -3
View File
@@ -42,6 +42,18 @@ int event_queue_fd_write_to_read(int eq, int fd) {
}
int event_queue_fd_read_to_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, 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;
@@ -172,6 +184,7 @@ int event_queue_init() {
int epfd;
epfd = epoll_create(256);
if (epfd < 0) {
@@ -215,6 +228,23 @@ int event_queue_fd_write_to_read(int eq, int fd) {
return fd;
}
int event_queue_fd_read_to_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_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;
@@ -344,6 +374,28 @@ int event_queue_fd_write_to_read(int eq, int fd) {
return fd;
}
int event_queue_fd_read_to_write(int eq, int fd) {
struct kevent kev;
#ifndef __FreeBSD__
EV_SET(&kev, fd, EVFILT_READ, 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_WRITE, 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;
@@ -403,7 +455,8 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
}
if (ret < 0) {
uwsgi_error("kevent()");
if (errno != EINTR)
uwsgi_error("kevent()");
}
return ret;
@@ -419,7 +472,8 @@ int event_queue_interesting_fd(void *events, int id) {
int event_queue_interesting_fd_has_error(void *events, int id) {
struct kevent *ev = (struct kevent *) events;
if ( ( (ev[id].flags == EV_ERROR) || (ev[id].flags == EV_EOF) || (ev[id].flags == (EV_EOF|EV_ERROR))) ) {
// DO NOT CHECK FOR EOF !!!
if ( ev[id].flags & EV_ERROR ) {
return 1;
}
return 0;
@@ -443,7 +497,8 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
}
if (ret < 0) {
uwsgi_error("kevent()");
if (errno != EINTR)
uwsgi_error("kevent()");
}
if (ret > 0) {
+159
View File
@@ -0,0 +1,159 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(int, void *), void *data) {
struct uwsgi_gateway *ug;
int num=1,i;
if (ushared->gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<ushared->gateways_cnt;i++) {
if (!strcmp(name, ushared->gateways[i].name)) {
num++;
}
}
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
ug = &ushared->gateways[ushared->gateways_cnt];
ug->pid = 0;
ug->name = name;
ug->loop = loop;
ug->num = num;
ug->fullname = fullname;
ug->data = data;
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
uwsgi_error("socketpair()");
}
if (!uwsgi.master_process)
gateway_respawn(ushared->gateways_cnt);
ushared->gateways_cnt++;
return ug;
}
void gateway_respawn(int id) {
pid_t gw_pid;
struct uwsgi_gateway *ug = &ushared->gateways[id];
if (uwsgi.master_process)
uwsgi.shared->gateways_harakiri[id] = 0;
gw_pid = uwsgi_fork(ug->fullname);
if (gw_pid < 0) {
uwsgi_error("fork()");
return;
}
if (gw_pid == 0) {
uwsgi_fixup_fds(0, 0, ug);
if (uwsgi.master_as_root) uwsgi_as_root();
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
uwsgi.mypid = getpid();
signal(SIGALRM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
signal(SIGTERM, end_me);
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
ug->loop(id, ug->data);
// 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);
}
}
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *name, char *owner) {
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
uwsgi_sock = uwsgi.gateway_sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
uwsgi_sock->fd = -1;
uwsgi_sock->shared = 0;
uwsgi_sock->name = name;
uwsgi_sock->name_len = strlen(name);
uwsgi_sock->owner = owner;
return uwsgi_sock;
}
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int fd, char *owner) {
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
uwsgi_sock = uwsgi.gateway_sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
uwsgi_sock->fd = fd;
uwsgi_sock->name = uwsgi_getsockname(fd);
uwsgi_sock->name_len = strlen(uwsgi_sock->name);
uwsgi_sock->owner = owner;
return uwsgi_sock;
}
void uwsgi_gateway_go_cheap(char *gw_id, int queue, int *i_am_cheap) {
uwsgi_log("[%s pid %d] no more nodes available. Going cheap...\n", gw_id, (int) uwsgi.mypid);
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
event_queue_del_fd(queue, ugs->fd, event_queue_read());
}
ugs = ugs->next;
}
*i_am_cheap = 1;
}
+2 -2
View File
@@ -14,7 +14,7 @@ void ini_rstrip(char *line) {
off_t i;
for(i = strlen(line)-1;i>=0; i--) {
if (line[i] == ' ' || line[i] == '\t') {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
line[i] = 0;
continue;
}
@@ -28,7 +28,7 @@ char *ini_lstrip(char *line) {
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
if (line[i] == ' ' || line[i] == '\t') {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
}
+235
View File
@@ -0,0 +1,235 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_init_default() {
uwsgi.cpus = 1;
uwsgi.backtrace_depth = 64;
uwsgi.max_apps = 64;
uwsgi.master_queue = -1;
uwsgi.signal_socket = -1;
uwsgi.my_signal_socket = -1;
uwsgi.cache_server_fd = -1;
uwsgi.stats_fd = -1;
uwsgi.original_log_fd = -1;
uwsgi.emperor_fd_config = -1;
// default emperor scan frequency
uwsgi.emperor_freq = 3;
uwsgi.emperor_throttle = 1000;
uwsgi.emperor_heartbeat = 30;
// max 3 minutes throttling
uwsgi.emperor_max_throttle = 1000 * 180;
uwsgi.emperor_pid = -1;
uwsgi.subscribe_freq = 10;
uwsgi.subscription_tolerance = 17;
uwsgi.cluster_fd = -1;
uwsgi.cores = 1;
uwsgi.threads = 1;
uwsgi.default_app = -1;
uwsgi.buffer_size = 4096;
uwsgi.numproc = 1;
uwsgi.forkbomb_delay = 2;
uwsgi.async = 1;
uwsgi.listen_queue = 100;
uwsgi.cheaper_overload = 3;
uwsgi.log_master_bufsize = 8192;
uwsgi.max_vars = MAX_VARS;
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
#ifdef UWSGI_SPOOLER
uwsgi.shared->spooler_frequency = 30;
uwsgi.shared->spooler_signal_pipe[0] = -1;
uwsgi.shared->spooler_signal_pipe[1] = -1;
#endif
uwsgi.shared->mule_signal_pipe[0] = -1;
uwsgi.shared->mule_signal_pipe[1] = -1;
uwsgi.shared->mule_queue_pipe[0] = -1;
uwsgi.shared->mule_queue_pipe[1] = -1;
uwsgi.shared->worker_log_pipe[0] = -1;
uwsgi.shared->worker_log_pipe[1] = -1;
#ifdef UWSGI_SSL
// 1 day of tolerance
uwsgi.subscriptions_sign_check_tolerance = 3600 * 24;
#endif
}
void uwsgi_setup_reload() {
char env_reload_buf[11];
char *env_reloads = getenv("UWSGI_RELOADS");
if (env_reloads) {
//convert env value to int
uwsgi.reloads = atoi(env_reloads);
uwsgi.reloads++;
//convert reloads to string
int rlen = snprintf(env_reload_buf, 10, "%u", uwsgi.reloads);
if (rlen > 0) {
env_reload_buf[rlen] = 0;
if (setenv("UWSGI_RELOADS", env_reload_buf, 1)) {
uwsgi_error("setenv()");
}
}
uwsgi.is_a_reload = 1;
}
else {
if (setenv("UWSGI_RELOADS", "0", 1)) {
uwsgi_error("setenv()");
}
}
}
void uwsgi_autoload_plugins_by_name(char *argv_zero) {
char *plugins_requested = NULL;
char *original_proc_name = getenv("UWSGI_ORIGINAL_PROC_NAME");
if (!original_proc_name) {
// here we use argv[0];
original_proc_name = argv_zero;
setenv("UWSGI_ORIGINAL_PROC_NAME", original_proc_name, 1);
}
char *p = strrchr(original_proc_name, '/');
if (p == NULL)
p = original_proc_name;
p = strstr(p, "uwsgi_");
if (p != NULL) {
plugins_requested = strtok(uwsgi_str(p + 6), "_");
while (plugins_requested) {
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
uwsgi_load_plugin(-1, plugins_requested, NULL);
plugins_requested = strtok(NULL, "_");
}
}
plugins_requested = getenv("UWSGI_PLUGINS");
if (plugins_requested) {
plugins_requested = uwsgi_concat2(plugins_requested, "");
char *p = strtok(plugins_requested, ",");
while (p != NULL) {
uwsgi_load_plugin(-1, p, NULL);
p = strtok(NULL, ",");
}
}
}
void uwsgi_commandline_config() {
int i;
uwsgi.option_index = -1;
char *optname;
while ((i = getopt_long(uwsgi.argc, uwsgi.argv, uwsgi.short_options, uwsgi.long_options, &uwsgi.option_index)) != -1) {
if (i == '?') {
uwsgi_log("getopt_long() error\n");
exit(1);
}
if (uwsgi.option_index > -1) {
optname = (char *) uwsgi.long_options[uwsgi.option_index].name;
}
else {
optname = uwsgi_get_optname_by_index(i);
}
if (!optname) {
uwsgi_log("unable to parse command line options\n");
exit(1);
}
uwsgi.option_index = -1;
add_exported_option(optname, optarg, 0);
}
#ifdef UWSGI_DEBUG
uwsgi_log("optind:%d argc:%d\n", optind, uwsgi.argc);
#endif
if (optind < uwsgi.argc) {
for (i = optind; i < uwsgi.argc; i++) {
char *lazy = uwsgi.argv[i];
if (lazy[0] != '[') {
uwsgi_opt_load(NULL, lazy, NULL);
// manage magic mountpoint
int magic = 0;
int j;
for (j = 0; j < uwsgi.gp_cnt; j++) {
if (uwsgi.gp[j]->magic) {
if (uwsgi.gp[j]->magic(NULL, lazy)) {
magic = 1;
break;
}
}
}
if (!magic) {
for (j = 0; j < 256; j++) {
if (uwsgi.p[j]->magic) {
if (uwsgi.p[j]->magic(NULL, lazy)) {
magic = 1;
break;
}
}
}
}
}
}
}
}
void uwsgi_setup_workers() {
int i,j;
// allocate shared memory for workers + master
uwsgi.workers = (struct uwsgi_worker *) uwsgi_calloc_shared(sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1 + uwsgi.grunt));
for (i = 0; i <= uwsgi.numproc; i++) {
// allocate memory for apps
uwsgi.workers[i].apps = (struct uwsgi_app *) uwsgi_calloc_shared(sizeof(struct uwsgi_app) * uwsgi.max_apps);
// allocate memory for cores
uwsgi.workers[i].cores = (struct uwsgi_core *) uwsgi_calloc_shared(sizeof(struct uwsgi_core) * uwsgi.cores);
for (j = 0; j < uwsgi.cores; j++) {
// allocate shared memory for thread states (required for some language, like python)
uwsgi.workers[i].cores[j].ts = uwsgi_calloc_shared(sizeof(void *) * uwsgi.max_apps);
// raw per-request buffer
uwsgi.workers[i].cores[j].buffer = uwsgi_malloc_shared(uwsgi.buffer_size);
// iovec for uwsgi vars
uwsgi.workers[i].cores[j].hvec = uwsgi_malloc_shared(sizeof(struct iovec) * uwsgi.vec_size);
if (uwsgi.post_buffering > 0)
uwsgi.workers[i].cores[j].post_buf = uwsgi_malloc_shared(uwsgi.post_buffering_bufsize);
}
// master does not need to following steps...
if (i == 0) continue;
uwsgi.workers[i].signal_pipe[0] = -1;
uwsgi.workers[i].signal_pipe[1] = -1;
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
}
}
View File
+13 -37
View File
@@ -108,56 +108,37 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct option *aopt, *lopt;
struct uwsgi_option *op = uwsgi.options;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
static int counter = 30000000;
*count = 0;
lopt = uwsgi.long_options;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*uwsgi_count_options(op));
while( (aopt = lopt) ) {
if (!aopt->name)
break;
while( op && op->name ) {
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
uwsgi_name_to_ldap((char *)op->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry) goto next;
if (aopt->flag) {
entry = &ule[*count] ;
entry->num = counter;
strcpy(entry->names, ldap_name);
counter++;
*count = *count+1;
}
else {
entry = get_ldap_by_num(ule, aopt->val, *count);
if (entry) {
strcat(entry->names, ldap_name);
}
else {
entry = &ule[*count] ;
entry->num = aopt->val;
strcpy(entry->names, ldap_name);
*count = *count+1;
}
}
entry = &ule[*count] ;
entry->num = *count;
strcpy(entry->names, ldap_name);
*count = *count+1;
entry->has_arg = aopt->has_arg;
entry->has_arg = op->type;
next:
lopt++;
op++;
}
return ule;
}
void uwsgi_ldap_schema_dump_ldif() {
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
int i;
int items;
@@ -210,7 +191,7 @@ void uwsgi_ldap_schema_dump_ldif() {
exit(0);
}
void uwsgi_ldap_schema_dump() {
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
int i;
int items;
@@ -258,7 +239,7 @@ void uwsgi_ldap_schema_dump() {
exit(0);
}
void uwsgi_ldap_config() {
void uwsgi_ldap_config(char *url) {
LDAP *ldp;
LDAPMessage *results, *entry;
@@ -267,7 +248,6 @@ void uwsgi_ldap_config() {
char *attr;
char *uwsgi_attr;
char *url = "ldap:///";
char *url_slash;
int desired_version = LDAP_VERSION3;
@@ -275,10 +255,6 @@ void uwsgi_ldap_config() {
LDAPURLDesc *ldap_url;
if (uwsgi.ldap) {
url = uwsgi.ldap;
}
if (!ldap_is_ldap_url(url)) {
uwsgi_log("invalid LDAP url.\n");
exit(1);
+631
View File
@@ -0,0 +1,631 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uli) {
uwsgi.registered_locks = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
uwsgi.registered_locks->id = id;
uwsgi.registered_locks->pid = 0;
if (rw) {
uwsgi.registered_locks->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
}
else {
uwsgi.registered_locks->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
}
uwsgi.registered_locks->rw = rw;
uwsgi.registered_locks->next = NULL;
return uwsgi.registered_locks;
}
while(uli) {
if (!uli->next) {
uli->next = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
if (rw) {
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
}
else {
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
}
uli->next->id = id;
uli->next->pid = 0;
uli->next->rw = rw;
uli->next->next = NULL;
return uli->next;
}
uli = uli->next;
}
uwsgi_log("*** DANGER: unable to allocate lock %s ***\n", id);
exit(1);
}
#ifdef UWSGI_LOCK_USE_MUTEX
#ifdef EOWNERDEAD
#define UWSGI_LOCK_ENGINE_NAME "pthread robust mutexes"
int uwsgi_pthread_robust_mutexes_enabled = 1;
#else
#define UWSGI_LOCK_ENGINE_NAME "pthread mutexes"
#endif
#define UWSGI_LOCK_SIZE sizeof(pthread_mutex_t)
#ifdef OBSOLETE_LINUX_KERNEL
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutex_t)
#else
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlock_t)
#endif
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
pthread_mutexattr_t attr;
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
#ifdef EOWNERDEAD
retry:
#endif
if (pthread_mutexattr_init(&attr)) {
uwsgi_log("unable to allocate mutexattr structure\n");
exit(1);
}
if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share mutex\n");
exit(1);
}
#ifdef EOWNERDEAD
if (uwsgi_pthread_robust_mutexes_enabled) {
if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP)) {
uwsgi_log("unable to make the mutex 'robust'\n");
exit(1);
}
}
#endif
if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
#ifdef EOWNERDEAD
if (uwsgi_pthread_robust_mutexes_enabled) {
uwsgi_log("!!! it looks like your kernel does not support pthread robust mutexes !!!\n");
uwsgi_log("!!! falling back to standard pthread mutexes !!!\n");
uwsgi_pthread_robust_mutexes_enabled = 0;
pthread_mutexattr_destroy(&attr);
goto retry;
}
#endif
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
pthread_mutexattr_destroy(&attr);
#ifdef EOWNERDEAD
if (!uwsgi_pthread_robust_mutexes_enabled) {
uli->can_deadlock = 1;
}
#else
uli->can_deadlock = 1;
#endif
return uli;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (pthread_mutex_trylock((pthread_mutex_t *) uli->lock_ptr) == 0 ) {
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
return uwsgi_lock_fast_check(uli);
#else
if (pthread_rwlock_trywrlock((pthread_rwlock_t *) uli->lock_ptr) == 0 ) {
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
return 0;
}
return uli->pid;
#endif
}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
#ifdef EOWNERDEAD
if (pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr) == EOWNERDEAD) {
uwsgi_log("[deadlock-detector] a process holding a robust mutex died. recovering...\n");
pthread_mutex_consistent_np((pthread_mutex_t *) uli->lock_ptr);
}
#else
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
#endif
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
uli->pid = 0;
}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock_fast(uli);
#else
pthread_rwlock_rdlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
#endif
}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock_fast(uli);
#else
pthread_rwlock_wrlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
#endif
}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_unlock_fast(uli);
#else
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = 0;
#endif
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
#ifdef OBSOLETE_LINUX_KERNEL
return uwsgi_lock_fast_init(id);
#else
pthread_rwlockattr_t attr;
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
if (pthread_rwlockattr_init(&attr)) {
uwsgi_log("unable to allocate rwlock structure\n");
exit(1);
}
if (pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share rwlock\n");
exit(1);
}
if (pthread_rwlock_init((pthread_rwlock_t *) uli->lock_ptr, &attr)) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
pthread_rwlockattr_destroy(&attr);
uli->can_deadlock = 1;
return uli;
#endif
}
#elif defined(UWSGI_LOCK_USE_UMTX)
/* Warning: FreeBSD is still not ready for process-shared UMTX */
#include <machine/atomic.h>
#include <sys/umtx.h>
#define UWSGI_LOCK_SIZE sizeof(struct umtx)
#define UWSGI_RWLOCK_SIZE sizeof(struct umtx)
#define UWSGI_LOCK_ENGINE_NAME "FreeBSD umtx"
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
umtx_init((struct umtx*) uli->lock_ptr);
return uli;
}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
umtx_lock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
uli->pid = 0;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (umtx_trylock((struct umtx*) uli->lock_ptr, (u_long) getpid() )) {
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
#elif defined(UWSGI_LOCK_USE_POSIX_SEM)
#define UWSGI_LOCK_SIZE sizeof(sem_t)
#define UWSGI_RWLOCK_SIZE sizeof(sem_t)
#define UWSGI_LOCK_ENGINE_NAME "POSIX semaphores"
#include <semaphore.h>
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
sem_init((sem_t*) uli->lock_ptr, 1, 1);
uli->can_deadlock = 1;
return uli;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
sem_wait((sem_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
sem_post((sem_t*) uli->lock_ptr);
uli->pid = 0;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (sem_trywait((sem_t *) uli->lock_ptr) == 0) {
sem_post((sem_t*) uli->lock_ptr);
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
#elif defined(UWSGI_LOCK_USE_OSX_SPINLOCK)
#define UWSGI_LOCK_ENGINE_NAME "OSX spinlocks"
#define UWSGI_LOCK_SIZE sizeof(OSSpinLock)
#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock)
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
uli->can_deadlock = 1;
return uli;
}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
OSSpinLockLock((OSSpinLock *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
OSSpinLockUnlock((OSSpinLock *) uli->lock_ptr);
uli->pid = 0;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (OSSpinLockTry((OSSpinLock *) uli->lock_ptr)) {
OSSpinLockUnlock((OSSpinLock *) uli->lock_ptr);
return 0;
}
return uli->pid;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
uli->can_deadlock = 1;
return uli;
}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
#else
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
#define uwsgi_lock_fast_check uwsgi_lock_ipcsem_check
#define uwsgi_lock_fast uwsgi_lock_ipcsem
#define uwsgi_unlock_fast uwsgi_unlock_ipcsem
#define uwsgi_rwlock_fast_init uwsgi_rwlock_ipcsem_init
#define uwsgi_rwlock_fast_check uwsgi_rwlock_ipcsem_check
#define uwsgi_rlock_fast uwsgi_rlock_ipcsem
#define uwsgi_wlock_fast uwsgi_wlock_ipcsem
#define uwsgi_rwunlock_fast uwsgi_rwunlock_ipcsem
#define UWSGI_LOCK_SIZE sizeof(int)
#define UWSGI_RWLOCK_SIZE sizeof(int)
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
#define UWSGI_IPCSEM_ATEXIT 1
#endif
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
// used by ftok
static int counter = 1;
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} semu ;
int semid;
key_t myKey;
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
if (uwsgi.ftok) {
myKey = ftok(uwsgi.ftok, counter);
if (myKey < 0) {
uwsgi_error("ftok()");
exit(1);
}
counter++;
semid = semget(myKey, 1, IPC_CREAT|0666);
}
else {
semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL| 0666);
}
if (semid < 0) {
uwsgi_error("semget()");
exit(1);
}
// do this now, to allows triggering of atexit hook in case of problems
memcpy(uli->lock_ptr, &semid, sizeof(int));
semu.val = 1;
if (semctl(semid, 0, SETVAL, semu)) {
uwsgi_error("semctl()");
exit(1);
}
return uli;
}
void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
int semid;
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = SEM_UNDO;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semop(semid, &sb, 1)) {
uwsgi_error("semop()");
}
}
void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
int semid;
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = 1;
sb.sem_flg = SEM_UNDO;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semop(semid, &sb, 1)) {
uwsgi_error("semop()");
}
}
struct uwsgi_lock_item *uwsgi_rwlock_ipcsem_init(char *id) { return uwsgi_lock_ipcsem_init(id);}
void uwsgi_rlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
void uwsgi_wlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
void uwsgi_rwunlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_unlock_ipcsem(uli); }
// ipc cannot deadlock
pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
return 0;
}
void uwsgi_ipcsem_clear(void) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uwsgi.workers) goto clear;
if (uwsgi.mywid == 0) goto clear;
if (uwsgi.master_process && getpid() == uwsgi.workers[0].pid) goto clear;
if (!uwsgi.master_process && uwsgi.mywid == 1) goto clear;
return;
clear:
#ifdef UWSGI_DEBUG
uwsgi_log("removing sysvipc semaphores...\n");
#endif
while(uli) {
int semid = 0;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semctl(semid, 0, IPC_RMID)) {
uwsgi_error("semctl()");
}
uli = uli->next;
}
}
pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_ipcsem_check(uli); }
void uwsgi_setup_locking() {
// use the fastest available locking
if (uwsgi.lock_engine) {
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
uwsgi_log_initial("lock engine: ipcsem\n");
atexit(uwsgi_ipcsem_clear);
uwsgi.lock_ops.lock_init = uwsgi_lock_ipcsem_init;
uwsgi.lock_ops.lock_check = uwsgi_lock_ipcsem_check;
uwsgi.lock_ops.lock = uwsgi_lock_ipcsem;
uwsgi.lock_ops.unlock = uwsgi_unlock_ipcsem;
uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_ipcsem_init;
uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_ipcsem_check;
uwsgi.lock_ops.rlock = uwsgi_rlock_ipcsem;
uwsgi.lock_ops.wlock = uwsgi_wlock_ipcsem;
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_ipcsem;
uwsgi.lock_size = 8;
uwsgi.rwlock_size = 8;
return;
}
}
uwsgi_log_initial("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
#ifdef UWSGI_IPCSEM_ATEXIT
atexit(uwsgi_ipcsem_clear);
#endif
uwsgi.lock_ops.lock_init = uwsgi_lock_fast_init;
uwsgi.lock_ops.lock_check = uwsgi_lock_fast_check;
uwsgi.lock_ops.lock = uwsgi_lock_fast;
uwsgi.lock_ops.unlock = uwsgi_unlock_fast;
uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_fast_init;
uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_fast_check;
uwsgi.lock_ops.rlock = uwsgi_rlock_fast;
uwsgi.lock_ops.wlock = uwsgi_wlock_fast;
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_fast;
uwsgi.lock_size = UWSGI_LOCK_SIZE;
uwsgi.rwlock_size = UWSGI_RWLOCK_SIZE;
// application generic lock
int i;
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
for (i = 0; i < uwsgi.locks + 1; i++) {
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
}
// event queue lock (mitigate same event on multiple queues)
if (uwsgi.threads > 1) {
pthread_mutex_init(&uwsgi.thunder_mutex, NULL);
}
if (uwsgi.master_process) {
// signal table lock
uwsgi.signal_table_lock = uwsgi_lock_init("signal");
// fmon table lock
uwsgi.fmon_table_lock = uwsgi_lock_init("filemon");
// timer table lock
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
// probe table lock
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
// rb_timer table lock
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
// cron table lock
uwsgi.cron_table_lock = uwsgi_lock_init("cron");
}
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
}
int uwsgi_fcntl_lock(int fd) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = 0;
int ret = fcntl(fd, F_SETLKW, &fl);
if (ret < 0)
uwsgi_error("fcntl()");
return ret;
}
int uwsgi_fcntl_is_locked(int fd) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = 0;
if (fcntl(fd, F_SETLK, &fl)) {
return 1;
}
return 0;
}
void uwsgi_deadlock_check(pid_t diedpid) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
while (uli) {
if (!uli->can_deadlock)
goto nextlock;
pid_t locked_pid = 0;
if (uli->rw) {
locked_pid = uwsgi_rwlock_check(uli);
}
else {
locked_pid = uwsgi_lock_check(uli);
}
if (locked_pid == diedpid) {
uwsgi_log("[deadlock-detector] pid %d was holding lock %s (%p)\n", (int) diedpid, uli->id, uli->lock_ptr);
if (uli->rw) {
uwsgi_rwunlock(uli);
}
else {
uwsgi_unlock(uli);
}
}
nextlock:
uli = uli->next;
}
}
+1009
View File
File diff suppressed because it is too large Load Diff
+122
View File
@@ -0,0 +1,122 @@
#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.workers[uwsgi.mywid].cores[core_id].req;
#ifdef UWSGI_THREADING
int i;
sigset_t smask;
if (uwsgi.threads > 1) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
#ifdef UWSGI_DEBUG
sigdelset(&smask, SIGSEGV);
#endif
pthread_sigmask(SIG_BLOCK, &smask, NULL);
// run per-thread socket hook
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (uwsgi_sock->proto_thread_fixup) {
uwsgi_sock->proto_thread_fixup(uwsgi_sock, core_id);
}
uwsgi_sock = uwsgi_sock->next;
}
for (i = 0; i < 256; 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, core_id);
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);
}
// ok we are ready, let's start managing requests and signals
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;
}
+1572
View File
File diff suppressed because it is too large Load Diff
+1078
View File
File diff suppressed because it is too large Load Diff
+95 -5
View File
@@ -36,25 +36,30 @@ void uwsgi_mule(int id) {
pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
if (pid == 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
uwsgi.muleid = id;
// avoid race conditions
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = getpid();
uwsgi_fixup_fds(0, id);
uwsgi_fixup_fds(0, id, NULL);
uwsgi.my_signal_socket = uwsgi.mules[id-1].signal_pipe[1];
uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];
uwsgi_close_all_sockets();
for (i = 0; i < 0xFF; i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
for (i = 0; i < 0xFF; i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
@@ -62,7 +67,7 @@ void uwsgi_mule(int id) {
if (uwsgi.mules[id-1].patch) {
for (i = 0; i < 0xFF; i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
// never here
@@ -184,7 +189,7 @@ void uwsgi_mule_handler() {
}
else {
int i,found = 0;
for(i=0;i<0xff;i++) {
for(i=0;i<256;i++) {
if (uwsgi.p[i]->mule_msg) {
if (uwsgi.p[i]->mule_msg(message, len)) {
found = 1;
@@ -356,3 +361,88 @@ clear:
return len;
}
void uwsgi_opt_add_mule(char *opt, char *value, void *foobar) {
uwsgi.mules_cnt++;
uwsgi_string_new_list(&uwsgi.mules_patches, value);
}
void uwsgi_opt_add_mules(char *opt, char *value, void *foobar) {
int i;
for(i=0;i<atoi(value);i++) {
uwsgi.mules_cnt++;
uwsgi_string_new_list(&uwsgi.mules_patches, NULL);
}
}
void uwsgi_opt_add_farm(char *opt, char *value, void *foobar) {
uwsgi.farms_cnt++;
uwsgi_string_new_list(&uwsgi.farms_list, value);
}
void uwsgi_setup_mules_and_farms() {
int i;
if (uwsgi.mules_cnt > 0) {
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
for (i = 0; i < uwsgi.mules_cnt; i++) {
// create the socket pipe
create_signal_pipe(uwsgi.mules[i].signal_pipe);
create_signal_pipe(uwsgi.mules[i].queue_pipe);
uwsgi.mules[i].id = i + 1;
snprintf(uwsgi.mules[i].name, 0xff, "uWSGI mule %d", i + 1);
}
}
if (uwsgi.farms_cnt > 0) {
uwsgi.farms = (struct uwsgi_farm *) uwsgi_calloc_shared(sizeof(struct uwsgi_farm) * uwsgi.farms_cnt);
struct uwsgi_string_list *farm_name = uwsgi.farms_list;
for (i = 0; i < uwsgi.farms_cnt; i++) {
char *farm_value = uwsgi_str(farm_name->value);
char *mules_list = strchr(farm_value, ':');
if (!mules_list) {
uwsgi_log("invalid farm value (%s) must be in the form name:mule[,muleN].\n", farm_value);
exit(1);
}
mules_list[0] = 0;
mules_list++;
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
// create the socket pipe
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_signal_pipe(uwsgi.farms[i].queue_pipe);
char *p = strtok(mules_list, ",");
while (p != NULL) {
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
if (!um) {
uwsgi_log("invalid mule id: %s\n", p);
exit(1);
}
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
p = strtok(NULL, ",");
}
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
farm_name = farm_name->next;
}
}
}
View File
+277
View File
@@ -0,0 +1,277 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static int plugin_already_loaded(const char *plugin) {
int i;
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->name) {
if (!strcmp(plugin, uwsgi.p[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
if (uwsgi.p[i]->alias) {
if (!strcmp(plugin, uwsgi.p[i]->alias)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
}
for(i=0;i<uwsgi.gp_cnt;i++) {
if (uwsgi.gp[i]->name) {
if (!strcmp(plugin, uwsgi.gp[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
if (uwsgi.gp[i]->alias) {
if (!strcmp(plugin, uwsgi.gp[i]->alias)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
}
return 0;
}
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
void *plugin_handle = NULL;
char *plugin_abs_path = NULL;
char *plugin_filename = NULL;
int need_free = 0;
char *plugin_name = plugin;
char *plugin_symbol_name_start = plugin;
struct uwsgi_plugin *up;
char linkpath_buf[1024], linkpath[1024];
int linkpath_size;
char *colon = strchr(plugin_name, ':');
if (colon) {
colon[0] = 0;
modifier = atoi(plugin_name);
plugin_name = colon+1;
colon[0] = ':';
}
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
need_free = 1;
}
plugin_symbol_name_start = plugin_name;
// step 1: check for absolute plugin (stop if it fails)
if (strchr(plugin_name, '/')) {
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
if (!plugin_handle) {
if (!has_option)
uwsgi_log( "%s\n", dlerror());
goto end;
}
plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/');
plugin_symbol_name_start++;
plugin_abs_path = plugin_name;
goto success;
}
// step dir, check for user-supplied plugins directory
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
while(pdir) {
plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name);
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
if (plugin_handle) {
plugin_abs_path = plugin_filename;
//free(plugin_filename);
goto success;
}
free(plugin_filename);
plugin_filename = NULL;
pdir = pdir->next;
}
// last step: search in compile-time plugin_dir
if (!plugin_handle) {
plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name);
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
plugin_abs_path = plugin_filename;
//free(plugin_filename);
}
success:
if (!plugin_handle) {
if (!has_option)
uwsgi_log( "%s\n", dlerror());
}
else {
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start)-3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
if (!up) {
// is it a link ?
memset(linkpath_buf, 0, 1024);
memset(linkpath, 0, 1024);
if ((linkpath_size = readlink(plugin_abs_path, linkpath_buf, 1023)) > 0) {
do {
linkpath_buf[linkpath_size] = '\0';
strncpy(linkpath, linkpath_buf, linkpath_size+1);
} while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0);
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", linkpath);
#endif
free(plugin_entry_symbol);
up = dlsym(plugin_handle, plugin_entry_symbol);
char *slash = uwsgi_get_last_char(linkpath, '/');
if (!slash) {
slash = linkpath;
}
else {
slash++;
}
plugin_entry_symbol = uwsgi_concat2n(slash, strlen(slash)-3, "",0);
up = dlsym(plugin_handle, plugin_entry_symbol);
}
}
if (up) {
if (!up->name) {
uwsgi_log("the loaded plugin (%s) has no .name attribute\n", plugin_name);
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
free(plugin_entry_symbol);
return NULL;
}
if (plugin_already_loaded(up->name)) {
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
free(plugin_entry_symbol);
return NULL;
}
if (has_option) {
struct uwsgi_option *op = up->options;
int found = 0;
while (op && op->name) {
if (!strcmp(has_option, op->name)) {
found = 1;
break;
}
op++;
}
if (!found) {
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
free(plugin_entry_symbol);
return NULL;
}
}
if (modifier != -1) {
fill_plugin_table(modifier, up);
up->modifier1 = modifier;
}
else {
fill_plugin_table(up->modifier1, up);
}
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
free(plugin_entry_symbol);
if (up->on_load)
up->on_load();
return plugin_handle;
}
if (!has_option)
uwsgi_log( "%s\n", dlerror());
}
end:
if (need_free)
free(plugin_name);
if (plugin_filename)
free(plugin_filename);
return NULL;
}
int uwsgi_try_autoload(char *option) {
DIR *d;
struct dirent *dp;
// step dir, check for user-supplied plugins directory
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
while(pdir) {
d = opendir(pdir->value);
if (d) {
while ((dp = readdir(d)) != NULL) {
if (uwsgi_endswith(dp->d_name, "_plugin.so")) {
char *filename = uwsgi_concat3(pdir->value, "/", dp->d_name);
if (uwsgi_load_plugin(-1, filename, option)) {
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
free(filename);
closedir(d);
// add new options
build_options();
return 1;
}
free(filename);
}
}
closedir(d);
}
pdir = pdir->next;
}
// last step: search in compile-time plugin_dir
d = opendir(UWSGI_PLUGIN_DIR);
if (!d) return 0;
while((dp = readdir(d)) != NULL) {
if (uwsgi_endswith(dp->d_name, "_plugin.so")) {
char *filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", dp->d_name);
if (uwsgi_load_plugin(-1, filename, option)) {
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
free(filename);
closedir(d);
// add new options
build_options();
return 1;
}
free(filename);
}
}
closedir(d);
return 0;
}
+582 -169
View File
@@ -16,7 +16,8 @@ static size_t get_content_length(char *buf, uint16_t size) {
return val;
}
void set_http_date(time_t t, char *dst) {
int set_http_date(time_t t, char *header, int header_len, char *dst, int last) {
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *months[] = {
@@ -26,12 +27,168 @@ void set_http_date(time_t t, char *dst) {
};
struct tm *hdtm = gmtime(&t);
snprintf(dst, 49, "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n\r\n",
if (last) {
return snprintf(dst, 36+header_len, "%.*s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n\r\n",
header_len, header,
week[hdtm->tm_wday], hdtm->tm_mday,
months[hdtm->tm_mon], hdtm->tm_year+1900,
hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
}
return snprintf(dst, 34+header_len, "%.*s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
header_len, header,
week[hdtm->tm_wday], hdtm->tm_mday,
months[hdtm->tm_mon], hdtm->tm_year+1900,
hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
}
void uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int mime_type_len, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_type;
time_t now = wsgi_req->start_of_request/1000000;
// Expires+34+1
char expires[42];
while(udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now+delta, "Expires", 7, expires, 0);
if (size > 0) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
wsgi_req->header_cnt++;
}
return;
}
udd = udd->next;
}
udd = uwsgi.static_expires_type_mtime;
while(udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime+delta, "Expires", 7, expires, 0);
if (size > 0) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
wsgi_req->header_cnt++;
}
return;
}
udd = udd->next;
}
}
#ifdef UWSGI_PCRE
void uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filename_len, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires;
time_t now = wsgi_req->start_of_request/1000000;
// Expires+34+1
char expires[42];
while(udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now+delta, "Expires", 7, expires, 0);
if (size > 0) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
wsgi_req->header_cnt++;
}
return;
}
udd = udd->next;
}
udd = uwsgi.static_expires_mtime;
while(udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime+delta, "Expires", 7, expires, 0);
if (size > 0) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
wsgi_req->header_cnt++;
}
return;
}
udd = udd->next;
}
}
void uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_path_info;
time_t now = wsgi_req->start_of_request/1000000;
// Expires+34+1
char expires[42];
while(udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now+delta, "Expires", 7, expires, 0);
if (size > 0) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
wsgi_req->header_cnt++;
}
return;
}
udd = udd->next;
}
udd = uwsgi.static_expires_path_info_mtime;
while(udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime+delta, "Expires", 7, expires, 0);
if (size > 0) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
wsgi_req->header_cnt++;
}
return;
}
udd = udd->next;
}
}
void uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_uri;
time_t now = wsgi_req->start_of_request/1000000;
// Expires+34+1
char expires[42];
while(udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now+delta, "Expires", 7, expires, 0);
if (size > 0) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
wsgi_req->header_cnt++;
}
return;
}
udd = udd->next;
}
udd = uwsgi.static_expires_uri_mtime;
while(udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime+delta, "Expires", 7, expires, 0);
if (size > 0) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
wsgi_req->header_cnt++;
}
return;
}
udd = udd->next;
}
}
#endif
// only RFC 1123 is supported
time_t parse_http_date(char *date, uint16_t len) {
@@ -122,11 +279,11 @@ time_t parse_http_date(char *date, uint16_t len) {
}
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char *message, uint16_t message_size) {
int fd;
struct sockaddr_in udp_addr;
struct sockaddr_un un_addr;
char *udp_port;
ssize_t ret;
@@ -140,23 +297,34 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
}
udp_port = strchr(host, ':');
if (udp_port == NULL) {
return -1;
if (udp_port) {
udp_port[0] = 0;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
udp_addr.sin_family = AF_INET;
udp_addr.sin_port = htons(atoi(udp_port+1));
udp_addr.sin_addr.s_addr = inet_addr(host);
}
else {
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("socket()");
return -1;
}
udp_port[0] = 0;
memset(&un_addr, 0, sizeof(struct sockaddr_un));
un_addr.sun_family = AF_UNIX;
// use 102 as the magic number
strncat(un_addr.sun_path, host, 102);
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
udp_addr.sin_family = AF_INET;
udp_addr.sin_port = htons(atoi(udp_port+1));
udp_addr.sin_addr.s_addr = inet_addr(host);
uh->modifier1 = modifier1;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(message_size);
@@ -165,14 +333,18 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
#endif
uh->modifier2 = modifier2;
ret = sendto(fd, (char *) uh, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
if (udp_port) {
ret = sendto(fd, (char *) uh, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
udp_port[0] = ':';
}
else {
ret = sendto(fd, (char *) uh, message_size+4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
}
if (ret < 0) {
uwsgi_error("sendto()");
}
close(fd);
udp_port[0] = ':';
if ((char *)uh != message) {
free(uh);
}
@@ -180,7 +352,6 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
return ret;
}
#endif
int uwsgi_enqueue_message(char *host, int port, uint8_t modifier1, uint8_t modifier2, char *message, int size, int timeout) {
@@ -241,12 +412,9 @@ int uwsgi_enqueue_message(char *host, int port, uint8_t modifier1, uint8_t modif
ssize_t uwsgi_send_message(int fd, uint8_t modifier1, uint8_t modifier2, char *message, uint16_t size, int pfd, ssize_t plen, int timeout) {
struct pollfd uwsgi_mpoll;
ssize_t cnt;
struct uwsgi_header uh;
char buffer[4096];
ssize_t ret = 0;
int pret;
struct msghdr msg;
struct iovec iov [1];
union {
@@ -307,37 +475,8 @@ ssize_t uwsgi_send_message(int fd, uint8_t modifier1, uint8_t modifier2, char *m
// transfer data from one socket to another
if (pfd >= 0 && plen > 0) {
uwsgi_mpoll.fd = pfd;
uwsgi_mpoll.events = POLLIN;
while(plen > 0) {
pret = poll(&uwsgi_mpoll, 1, timeout*1000);
if (pret < 0) {
uwsgi_error("poll()");
return -1;
}
else if (pret == 0) {
uwsgi_log("timeout waiting for socket data\n");
return -1;
}
else {
cnt = read(pfd, buffer, UMIN(4096, plen));
if (cnt < 0) {
uwsgi_error("read()");
return -1;
}
else if (cnt == 0) {
return ret;
}
// send to peer
if (write(fd, buffer, cnt) != cnt) {
uwsgi_error("write()");
return -1;
}
ret += cnt;
plen -= cnt;
}
}
ret = uwsgi_pipe_sized(pfd, fd, timeout, plen);
if (ret < 0) return -1;
}
@@ -564,14 +703,19 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
/* set an HTTP 500 status as default */
wsgi_req->status = 500;
// skip if already parsed
if (wsgi_req->parsed) return 0;
// has the protocol already parsed the request ?
if (wsgi_req->uri_len > 0) {
wsgi_req->parsed = 1;
i = uwsgi_simple_parse_vars(wsgi_req, ptrbuf, bufferend);
if (i == 0) goto next;
return i;
}
wsgi_req->parsed = 1;
wsgi_req->path_info_pos = -1;
while (ptrbuf < bufferend) {
@@ -677,6 +821,15 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->file_len = strsize;
wsgi_req->dynamic = 1;
}
else if (!uwsgi_strncmp("UWSGI_POSTFILE", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
char *postfile = uwsgi_concat2n(ptrbuf, strsize, "", 0);
wsgi_req->async_post = fopen(postfile, "r");
if (!wsgi_req->async_post) {
uwsgi_error_open(postfile);
}
free(postfile);
wsgi_req->body_as_file = 1;
}
else if (!uwsgi_strncmp("UWSGI_TOUCH_RELOAD", 18, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->touch_reload = ptrbuf;
wsgi_req->touch_reload_len = strsize;
@@ -696,14 +849,14 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
free(env_value);
}
}
else if (!uwsgi_strncmp("SERVER_NAME", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len) && !uwsgi.vhost_host) {
else if (!uwsgi_strncmp("SERVER_NAME", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len) && !wsgi_req->host_len) {
wsgi_req->host = ptrbuf;
wsgi_req->host_len = strsize;
#ifdef UWSGI_DEBUG
uwsgi_debug("SERVER_NAME=%.*s\n", wsgi_req->host_len, wsgi_req->host);
#endif
}
else if (!uwsgi_strncmp("HTTP_HOST", 9, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len) && uwsgi.vhost_host) {
else if (!uwsgi_strncmp("HTTP_HOST", 9, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->host = ptrbuf;
wsgi_req->host_len = strsize;
#ifdef UWSGI_DEBUG
@@ -718,6 +871,14 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->if_modified_since = ptrbuf;
wsgi_req->if_modified_since_len = strsize;
}
else if (!uwsgi_strncmp("HTTP_AUTHORIZATION", 18, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->authorization = ptrbuf;
wsgi_req->authorization_len = strsize;
}
else if (!uwsgi_strncmp("DOCUMENT_ROOT", 13, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->document_root = ptrbuf;
wsgi_req->document_root_len = strsize;
}
else if (uwsgi.log_x_forwarded_for && !uwsgi_strncmp("HTTP_X_FORWARDED_FOR", 20, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_addr = ptrbuf;
wsgi_req->remote_addr_len = strsize;
@@ -863,24 +1024,44 @@ next:
}
}
// check if a file named uwsgi.check_static+env['PATH_INFO'] exists
if (wsgi_req->path_info_len > 1) {
udd = uwsgi.check_static;
while(udd) {
// need to build the path ?
if (udd->value == NULL) {
udd->value = realpath(udd->key, NULL);
if (!udd->value) goto nextcs;
udd->vallen = strlen(udd->value);
}
// check for static files
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len)) {
return -1;
}
nextcs:
udd = udd->next;
// skip extensions
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
while(sse) {
if (wsgi_req->path_info_len >= sse->len) {
if (!uwsgi_strncmp(wsgi_req->path_info+(wsgi_req->path_info_len - sse->len), sse->len, sse->value, sse->len)) {
return 0;
}
}
sse = sse->next;
}
// check if a file named uwsgi.check_static+env['PATH_INFO'] exists
udd = uwsgi.check_static;
while(udd) {
// need to build the path ?
if (udd->value == NULL) {
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
#endif
udd->value = uwsgi_malloc(PATH_MAX+1);
if (!realpath(udd->key, udd->value)) {
free(udd->value);
udd->value = NULL;
}
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
#endif
if (!udd->value) goto nextcs;
udd->vallen = strlen(udd->value);
}
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len, 0)) {
return -1;
}
nextcs:
udd = udd->next;
}
// check static-map
@@ -890,15 +1071,25 @@ nextcs:
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, udd->keylen, udd->key);
#endif
if (udd->status == 0) {
char *real_docroot = realpath(udd->value, NULL);
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
#endif
char *real_docroot = uwsgi_malloc(PATH_MAX+1);
if (!realpath(udd->value, real_docroot)) {
free(real_docroot);
udd->value = NULL;
}
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
#endif
if (!real_docroot) goto nextsm;
udd->value = real_docroot;
udd->vallen = strlen(udd->value);
udd->status = 1;
udd->status = 1 + uwsgi_is_file(real_docroot);
}
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info+udd->keylen, wsgi_req->path_info_len-udd->keylen)) {
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info+udd->keylen, wsgi_req->path_info_len-udd->keylen, udd->status-1)) {
return -1;
}
}
@@ -906,6 +1097,53 @@ nextsm:
udd = udd->next;
}
// check for static_maps in append mode
udd = uwsgi.static_maps2;
while(udd) {
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, udd->keylen, udd->key);
#endif
if (udd->status == 0) {
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
#endif
char *real_docroot = uwsgi_malloc(PATH_MAX+1);
if (!realpath(udd->value, real_docroot)) {
free(real_docroot);
udd->value = NULL;
}
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
#endif
if (!real_docroot) goto nextsm2;
udd->value = real_docroot;
udd->vallen = strlen(udd->value);
udd->status = 1 + uwsgi_is_file(real_docroot);
}
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len, udd->status-1)) {
return -1;
}
}
nextsm2:
udd = udd->next;
}
// finally check for docroot
if (uwsgi.check_static_docroot && wsgi_req->document_root_len > 0) {
char *real_docroot = uwsgi_expand_path(wsgi_req->document_root, wsgi_req->document_root_len, NULL);
if (!real_docroot) {
return -1;
}
if (!uwsgi_file_serve(wsgi_req, real_docroot, strlen(real_docroot), wsgi_req->path_info, wsgi_req->path_info_len, 0)) {
free(real_docroot);
return -1;
}
free(real_docroot);
}
return 0;
}
@@ -1380,6 +1618,30 @@ int uwsgi_simple_send_string2(char *socket_name, uint8_t modifier1, uint8_t modi
return 0;
}
char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, char *val, uint16_t vallen) {
if (wsgi_req->uh.pktsize + (2+keylen+2+vallen) > uwsgi.buffer_size) {
uwsgi_log("not enough buffer space to add %.*s variable, consider increasing it with the --buffer-size option\n", keylen, key);
return NULL;
}
char *ptr = wsgi_req->buffer + wsgi_req->uh.pktsize;
*ptr++= (uint8_t) (keylen & 0xff);
*ptr++= (uint8_t) ((keylen >> 8) & 0xff);
memcpy(ptr, key, keylen); ptr+=keylen;
*ptr++= (uint8_t) (vallen & 0xff);
*ptr++= (uint8_t) ((vallen >> 8) & 0xff);
memcpy(ptr, val, vallen);
wsgi_req->uh.pktsize += (2+keylen+2+vallen);
return ptr;
}
int uwsgi_simple_send_string(char *socket_name, uint8_t modifier1, uint8_t modifier2, char *item1, uint16_t item1_len, int timeout) {
struct uwsgi_header uh;
@@ -1433,66 +1695,115 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
count++;
}
if (ext) {
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
while(udd) {
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
udd->hits++;
// auto optimization
if (udd->prev) {
if (udd->hits > udd->prev->hits) {
struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
if (udd_parent) {
udd_parent->next = udd;
}
udd_prev->prev = udd;
udd_prev->next = udd->next;
if (!ext) return NULL;
udd->prev = udd_parent;
udd->next = udd_prev;
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
while(udd) {
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
udd->hits++;
// auto optimization
if (udd->prev) {
if (udd->hits > udd->prev->hits) {
struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
if (udd_parent) {
udd_parent->next = udd;
}
if (udd->next) {
udd->next->prev = udd_prev;
}
udd_prev->prev = udd;
udd_prev->next = udd->next;
udd->prev = udd_parent;
udd->next = udd_prev;
if (udd->prev == NULL) {
uwsgi.mimetypes = udd;
}
}
*size = udd->vallen;
return udd->value;
}
udd = udd->next;
*size = udd->vallen;
return udd->value;
}
udd = udd->next;
}
return NULL;
}
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len) {
int uwsgi_append_static_path(char *dir, char *file, int file_len) {
size_t len = strlen(dir);
if (len + 1 + file_len > PATH_MAX) {
return -1;
}
if (dir[len-1] == '/') {
memcpy(dir+len, file, file_len);
dir[len+file_len] = 0;
}
else {
dir[len] = '/';
memcpy(dir+len+1, file, file_len);
dir[len+1+file_len] = 0;
}
return len;
}
int uwsgi_static_stat(char *filename, struct stat *st) {
int ret = stat(filename, st);
// if non-existant return -1
if (ret < 0) return -1;
if (S_ISREG(st->st_mode)) return 0;
// check for index
if (S_ISDIR(st->st_mode)) {
struct uwsgi_string_list *usl = uwsgi.static_index;
while(usl) {
ret = uwsgi_append_static_path(filename, usl->value, usl->len);
if (ret >= 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %s\n", filename);
#endif
if (!uwsgi_static_stat(filename, st)) {
return 0;
}
// reset to original name
filename[ret] = 0;
}
usl = usl->next;
}
}
return -1;
}
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
struct stat st;
struct iovec headers_vec[8];
char real_filename[PATH_MAX];
char *filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
int mime_type_size = 0;
char http_last_modified[49];
char content_length[sizeof(UMAX64_STR)+1];
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
#endif
if (!realpath(filename, real_filename)) {
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
#endif
free(filename);
return -1;
}
free(filename);
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
return -1;
}
if (!stat(real_filename, &st)) {
int mime_type_size = 0;
char *mime_type = uwsgi_get_mime_type(path_info, path_info_len, &mime_type_size);
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
if (st.st_mtime <= ims) {
if (st->st_mtime <= ims) {
wsgi_req->status = 304;
headers_vec[0].iov_base = wsgi_req->protocol;
headers_vec[0].iov_len = wsgi_req->protocol_len;
@@ -1516,18 +1827,16 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
return 0;
}
}
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
char http_last_modified[49];
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
#endif
// HTTP status
headers_vec[0].iov_base = wsgi_req->protocol;
headers_vec[0].iov_len = wsgi_req->protocol_len;
headers_vec[1].iov_base = " 200 OK\r\n";
headers_vec[1].iov_len = 9;
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
// HTTP status
headers_vec[0].iov_base = wsgi_req->protocol;
headers_vec[0].iov_len = wsgi_req->protocol_len;
headers_vec[1].iov_base = " 200 OK\r\n";
headers_vec[1].iov_len = 9;
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
// uWSGI additional headers
struct uwsgi_string_list *ah = uwsgi.additional_headers;
@@ -1541,6 +1850,12 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
ah = ah->next;
}
#ifdef UWSGI_PCRE
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
uwsgi_add_expires_path_info(wsgi_req, st);
uwsgi_add_expires_uri(wsgi_req, st);
#endif
// Content-Type (if available)
if (mime_type_size > 0 && mime_type) {
headers_vec[0].iov_base = "Content-Type: ";
@@ -1551,45 +1866,30 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
headers_vec[2].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
wsgi_req->header_cnt++;
// check for content-type related headers
uwsgi_add_expires_type(wsgi_req, mime_type, mime_type_size, st);
}
// nginx
if (uwsgi.file_serve_mode == 1) {
headers_vec[0].iov_base = "X-Accel-Redirect: "; headers_vec[0].iov_len = 18 ;
headers_vec[1].iov_base = document_root; headers_vec[1].iov_len = document_root_len;
if (document_root[document_root_len-1] != '/') {
headers_vec[2].iov_base = "/"; headers_vec[2].iov_len = 1;
headers_vec[3].iov_base = path_info; headers_vec[3].iov_len = path_info_len;
headers_vec[4].iov_base = "\r\n"; headers_vec[4].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 5);
}
else {
headers_vec[2].iov_base = path_info; headers_vec[2].iov_len = path_info_len;
headers_vec[3].iov_base = "\r\n"; headers_vec[3].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 4);
}
headers_vec[1].iov_base = real_filename; headers_vec[1].iov_len = real_filename_len;
headers_vec[2].iov_base = "\r\n"; headers_vec[2].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
// this is the final header (\r\n added)
set_http_date(st.st_mtime, http_last_modified);
set_http_date(st->st_mtime, "Last-Modified", 13, http_last_modified, 1);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
wsgi_req->header_cnt += 2;
}
// apache
else if (uwsgi.file_serve_mode == 2) {
headers_vec[0].iov_base = "X-Sendfile: "; headers_vec[0].iov_len = 12 ;
headers_vec[1].iov_base = document_root; headers_vec[1].iov_len = document_root_len;
if (document_root[document_root_len-1] != '/') {
headers_vec[2].iov_base = "/"; headers_vec[2].iov_len = 1;
headers_vec[3].iov_base = path_info; headers_vec[3].iov_len = path_info_len;
headers_vec[4].iov_base = "\r\n"; headers_vec[4].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 5);
}
else {
headers_vec[2].iov_base = path_info; headers_vec[2].iov_len = path_info_len;
headers_vec[3].iov_base = "\r\n"; headers_vec[3].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 4);
}
headers_vec[1].iov_base = real_filename; headers_vec[1].iov_len = real_filename_len;
headers_vec[2].iov_base = "\r\n"; headers_vec[2].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
// this is the final header (\r\n added)
set_http_date(st.st_mtime, http_last_modified);
set_http_date(st->st_mtime, "Last-Modified", 13, http_last_modified, 1);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
wsgi_req->header_cnt += 2;
}
@@ -1598,12 +1898,12 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
// set Content-Length
headers_vec[0].iov_base = "Content-Length: ";
headers_vec[0].iov_len = 16;
headers_vec[1].iov_len = uwsgi_long2str2n(st.st_size, content_length, sizeof(UMAX64_STR)+1);
headers_vec[1].iov_len = uwsgi_long2str2n(st->st_size, content_length, sizeof(UMAX64_STR)+1);
headers_vec[1].iov_base = content_length;
headers_vec[2].iov_base = "\r\n";
headers_vec[2].iov_len = 2;
// this is the final header (\r\n added)
set_http_date(st.st_mtime, http_last_modified);
set_http_date(st->st_mtime, "Last-Modified", 13, http_last_modified, 1);
headers_vec[3].iov_base = http_last_modified;
headers_vec[3].iov_len = 48;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 4);
@@ -1617,24 +1917,137 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
wsgi_req->status = 200;
return 0;
}
}
void *uwsgi_static_offload_thread(void *req) {
struct uwsgi_offload_request *uof_req = (struct uwsgi_offload_request *) req;
uwsgi_real_file_serve(&uof_req->wsgi_req, uof_req->real_filename, uof_req->real_filename_len, &uof_req->st);
// close the connection with the webserver
if (!uof_req->wsgi_req.fd_closed || !uof_req->wsgi_req.body_as_file) {
// NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
uof_req->wsgi_req.socket->proto_close(&uof_req->wsgi_req);
}
// free buffer
free(uof_req->buffer);
// free hvec
free(uof_req->hvec);
free(uof_req);
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
uwsgi.workers[uwsgi.mywid].static_offload_threads--;
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
return NULL;
}
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len, int is_a_file) {
struct stat st;
char real_filename[PATH_MAX+1];
size_t real_filename_len = 0;
char *filename = NULL;
if (!is_a_file) {
filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
}
else {
filename = uwsgi_concat2n(document_root, document_root_len, "", 0);
}
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
#endif
if (!realpath(filename, real_filename)) {
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
#endif
free(filename);
return -1;
}
free(filename);
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
return -1;
}
if (!uwsgi_static_stat(real_filename, &st)) {
real_filename_len = strlen(real_filename);
// check for skippable ext
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
while(sse) {
if (real_filename_len >= sse->len) {
if (!uwsgi_strncmp(real_filename+(real_filename_len - sse->len), sse->len, sse->value, sse->len)) {
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes_fast(wsgi_req, real_filename, real_filename_len) == UWSGI_ROUTE_BREAK) return 0;
#endif
return -1;
}
}
sse = sse->next;
}
// Ok, the file must be served as static from uWSGI
if (uwsgi.static_offload_to_thread) {
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
uint64_t offload_thread_count = uwsgi.workers[uwsgi.mywid].static_offload_threads;
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
if (offload_thread_count > (uint64_t) uwsgi.static_offload_to_thread) {
uwsgi_log_verbose("OVERLOAD !!! unable to offload static file serving\n");
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
}
struct uwsgi_offload_request *uor = uwsgi_malloc(sizeof(struct uwsgi_offload_request));
// buffer
uor->buffer = uwsgi_malloc(uwsgi.buffer_size); memcpy(uor->buffer, wsgi_req->buffer, uwsgi.buffer_size);
// iovec
uor->hvec = uwsgi_malloc(sizeof(struct iovec) * uwsgi.vec_size); memcpy(uor->hvec, wsgi_req->hvec, sizeof(struct iovec) * uwsgi.vec_size);
// wsgi_req
memcpy(&uor->wsgi_req, wsgi_req, sizeof(struct wsgi_request));
uor->wsgi_req.buffer = uor->buffer;
uor->wsgi_req.hvec = uor->hvec;
// stat
memcpy(&uor->st, &st, sizeof(struct stat));
// filename
memcpy(uor->real_filename, real_filename, real_filename_len);
uor->real_filename_len = real_filename_len;
uor->real_filename[uor->real_filename_len] = 0;
// avoid closing the connection
wsgi_req->fd_closed = 1;
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
uwsgi.workers[uwsgi.mywid].static_offload_threads++;
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
if (pthread_create(&uor->tid, &uwsgi.static_offload_thread_attr, uwsgi_static_offload_thread, (void *) uor)) {
uwsgi_error("pthread_create()");
// bad condition, better to exit...
exit(1);
}
wsgi_req->status = -30;
return 0;
}
else {
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
}
}
return -1;
}
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t *len) {
int i;
*len = 0;
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
if (!uwsgi_strncmp(key, strlen(key), wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
*len = wsgi_req->hvec[i + 1].iov_len;
return wsgi_req->hvec[i + 1].iov_base;
}
}
return NULL;
}
+3 -4
View File
@@ -63,8 +63,7 @@ void uwsgi_init_queue() {
uwsgi.queue_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.queue_lock);
uwsgi.queue_lock = uwsgi_rwlock_init("queue");
uwsgi_log("*** Queue subsystem initialized: %dMB preallocated ***\n", (uwsgi.queue_blocksize * uwsgi.queue_size) / (1024 * 1024));
}
@@ -151,7 +150,7 @@ int uwsgi_queue_push(char *message, uint64_t size) {
ptr += sizeof(struct uwsgi_queue_item);
uqi->size = size;
uqi->ts = time(NULL);
uqi->ts = uwsgi_now();
memcpy(ptr, message, size);
uwsgi.queue_header->pos++;
@@ -179,7 +178,7 @@ int uwsgi_queue_set(uint64_t pos, char *message, uint64_t size) {
ptr += sizeof(struct uwsgi_queue_item);
uqi->size = size;
uqi->ts = time(NULL);
uqi->ts = uwsgi_now();
memcpy(ptr, message, size);
return 1;
View File
+87
View File
@@ -0,0 +1,87 @@
#ifdef UWSGI_PCRE
#include "uwsgi.h"
int uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra) {
const char *errstr;
int erroff;
*pattern = pcre_compile( (const char *)re, 0, &errstr, &erroff, NULL);
if (!*pattern) {
uwsgi_log("pcre error: %s at offset %d\n", errstr, erroff);
return -1;
}
*pattern_extra = (pcre_extra *) pcre_study((const pcre*)*pattern, 0, &errstr);
if (*pattern_extra == NULL && errstr != NULL) {
pcre_free(*pattern);
uwsgi_log("pcre (study) error: %s\n", errstr);
return -1;
}
return 0;
}
int uwsgi_regexp_match(pcre *pattern, pcre_extra *pattern_extra, char *subject, int length) {
return pcre_exec((const pcre*)pattern, (const pcre_extra *)pattern_extra, subject, length, 0, 0, NULL, 0 );
}
int uwsgi_regexp_match_ovec(pcre *pattern, pcre_extra *pattern_extra, char *subject, int length, int *ovec, int n ) {
if (n > 0) {
return pcre_exec((const pcre*)pattern, (const pcre_extra *)pattern_extra, subject, length, 0, 0, ovec, (n+1)*3 );
}
return pcre_exec((const pcre*)pattern, (const pcre_extra *)pattern_extra, subject, length, 0, 0, NULL, 0 );
}
int uwsgi_regexp_ovector(pcre *pattern, pcre_extra *pattern_extra) {
int n;
if (pcre_fullinfo((const pcre*)pattern, (const pcre_extra *)pattern_extra, PCRE_INFO_CAPTURECOUNT, &n))
return 0;
return n;
}
char *uwsgi_regexp_apply_ovec(char *src, int src_n, char *dst, int dst_n, int *ovector, int n) {
int i;
int dollar = 0;
char *res = uwsgi_malloc( dst_n + (src_n * n) + 1);
char *ptr = res;
for(i=0;i<dst_n;i++) {
if (dollar) {
if (isdigit((int)dst[i])) {
int pos = (dst[i] - 48);
if (pos <= n) {
pos = pos * 2;
memcpy(ptr, src + ovector[pos], ovector[pos+1]-ovector[pos]);
ptr+=ovector[pos+1]-ovector[pos];
}
}
else {
*ptr++= dst[i];
}
dollar = 0;
}
else {
if (dst[i] == '$') {
dollar = 1;
}
else {
*ptr++= dst[i];
}
}
}
*ptr++= 0;
return res;
}
#endif
+168
View File
@@ -0,0 +1,168 @@
#ifdef UWSGI_ROUTING
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
struct uwsgi_route *routes = uwsgi.routes;
if (!routes) return UWSGI_ROUTE_CONTINUE;
if (uwsgi_parse_vars(wsgi_req)) {
return UWSGI_ROUTE_BREAK;
}
while(routes) {
char **subject = (char **) (((char *)(wsgi_req))+routes->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+routes->subject_len);
#ifdef UWSGI_DEBUG
uwsgi_log("route subject = %.*s\n", *subject_len, *subject);
#endif
int n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, *subject, *subject_len, routes->ovector, routes->ovn);
if (n>= 0) {
int ret = routes->func(wsgi_req, routes);
if (ret != UWSGI_ROUTE_NEXT) {
return ret;
}
}
routes = routes->next;
}
return UWSGI_ROUTE_CONTINUE;
}
int uwsgi_apply_routes_fast(struct wsgi_request *wsgi_req, char *uri, int len) {
struct uwsgi_route *routes = uwsgi.routes;
if (!routes) return UWSGI_ROUTE_CONTINUE;
while(routes) {
int n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, uri, len, routes->ovector, routes->ovn);
if (n>= 0) {
int ret = routes->func(wsgi_req, routes);
if (ret != UWSGI_ROUTE_NEXT) {
return ret;
}
}
routes = routes->next;
}
return UWSGI_ROUTE_CONTINUE;
}
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
char *route = uwsgi_str(value);
char *space = strchr(route, ' ');
if (!space) {
uwsgi_log("invalid route syntax\n");
exit(1);
}
*space = 0;
struct uwsgi_route *ur = uwsgi.routes;
if (!ur) {
uwsgi.routes = uwsgi_calloc(sizeof(struct uwsgi_route));
ur = uwsgi.routes;
}
else {
while(ur) {
if (!ur->next) {
ur->next = uwsgi_calloc(sizeof(struct uwsgi_route));
ur = ur->next;
break;
}
ur = ur->next;
}
}
if (!strcmp(foobar, "http_host")) {
ur->subject = offsetof(struct wsgi_request, host);
ur->subject_len = offsetof(struct wsgi_request, host_len);
}
else if (!strcmp(foobar, "request_uri")) {
ur->subject = offsetof(struct wsgi_request, uri);
ur->subject_len = offsetof(struct wsgi_request, uri_len);
}
else if (!strcmp(foobar, "query_string")) {
ur->subject = offsetof(struct wsgi_request, query_string);
ur->subject_len = offsetof(struct wsgi_request, query_string_len);
}
else {
ur->subject = offsetof(struct wsgi_request, path_info);
ur->subject_len = offsetof(struct wsgi_request, path_info_len);
}
if (uwsgi_regexp_build(route, &ur->pattern, &ur->pattern_extra)) {
exit(1);
}
ur->ovn = uwsgi_regexp_ovector(ur->pattern, ur->pattern_extra);
if (ur->ovn > 0) {
ur->ovector = uwsgi_calloc(sizeof(int) * (3 * (ur->ovn + 1)) );
}
char *command = space+1;
char *colon = strchr(command, ':');
if (!colon) {
uwsgi_log("invalid route syntax\n");
exit(1);
}
*colon = 0;
struct uwsgi_router *r = uwsgi.routers;
while(r) {
if (!strcmp(r->name, command)) {
if (r->func(ur, colon+1) == 0) {
// apply is_last
struct uwsgi_route *last_ur = ur;
ur = uwsgi.routes;
while(ur) {
if (ur->func == last_ur->func) {
ur->is_last = 0;
}
ur = ur->next;
}
last_ur->is_last = 1;
return;
}
}
r = r->next;
}
uwsgi_log("unable to register route \"%s\"\n", value);
exit(1);
}
struct uwsgi_router *uwsgi_register_router(char *name, int (*func)(struct uwsgi_route *, char *)) {
struct uwsgi_router *ur = uwsgi.routers;
if (!ur) {
uwsgi.routers = uwsgi_calloc(sizeof(struct uwsgi_router));
uwsgi.routers->name = name;
uwsgi.routers->func = func;
return uwsgi.routers;
}
while(ur) {
if (!ur->next) {
ur->next = uwsgi_calloc(sizeof(struct uwsgi_router));
ur->next->name = name;
ur->next->func = func;
return ur->next;
}
ur = ur->next;
}
return NULL;
}
#endif
View File
+17 -7
View File
@@ -89,20 +89,30 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
#elif defined(__linux__) || defined(__sun__)
int sf_ret;
size_t written = 0;
if (async > 1) {
sf_ret = sendfile(sockfd, filefd, pos, chunk);
}
else {
sf_ret = sendfile(sockfd, filefd, pos, filesize);
if (sf_ret < 0) {
uwsgi_error("sendfile()");
return 0;
}
return sf_ret;
}
if (sf_ret < 0) {
uwsgi_error("sendfile()");
return 0;
while(written < filesize) {
sf_ret = sendfile(sockfd, filefd, pos, filesize-written);
if (sf_ret < 0) {
uwsgi_error("sendfile()");
return 0;
}
else if (sf_ret == 0) {
return 0;
}
written+= sf_ret;
}
return written;
return sf_ret;
#else
static size_t nosf_buf_size = 0;
static char *nosf_buf;
+197
View File
@@ -0,0 +1,197 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_setup_systemd() {
struct uwsgi_socket *uwsgi_sock = NULL;
int i;
char *listen_pid = getenv("LISTEN_PID");
if (listen_pid) {
if (atoi(listen_pid) == (int) getpid()) {
char *listen_fds = getenv("LISTEN_FDS");
if (listen_fds) {
int systemd_fds = atoi(listen_fds);
if (systemd_fds > 0) {
uwsgi_log("- SystemD socket activation detected -\n");
for (i = 3; i < 3 + systemd_fds; i++) {
uwsgi_sock = uwsgi_new_socket(NULL);
uwsgi_add_socket_from_fd(uwsgi_sock, i);
}
uwsgi.skip_zero = 1;
}
unsetenv("LISTEN_PID");
unsetenv("LISTEN_FDS");
}
}
}
}
void uwsgi_setup_upstart() {
struct uwsgi_socket *uwsgi_sock = NULL;
char *upstart_events = getenv("UPSTART_EVENTS");
if (upstart_events && !strcmp(upstart_events, "socket")) {
char *upstart_fds = getenv("UPSTART_FDS");
if (upstart_fds) {
uwsgi_log("- Upstart socket bridge detected (job: %s) -\n", getenv("UPSTART_JOB"));
uwsgi_sock = uwsgi_new_socket(NULL);
uwsgi_add_socket_from_fd(uwsgi_sock, atoi(upstart_fds));
uwsgi.skip_zero = 1;
}
unsetenv("UPSTART_EVENTS");
unsetenv("UPSTART_FDS");
}
}
void uwsgi_setup_zerg() {
struct uwsgi_socket *uwsgi_sock = NULL;
int i;
struct uwsgi_string_list *zn = uwsgi.zerg_node;
while (zn) {
if (uwsgi_zerg_attach(zn->value)) {
if (!uwsgi.zerg_fallback) {
exit(1);
}
}
zn = zn->next;
}
if (uwsgi.zerg) {
#ifdef UWSGI_DEBUG
uwsgi_log("attaching zerg sockets...\n");
#endif
int zerg_fd;
i = 0;
for (;;) {
zerg_fd = uwsgi.zerg[i];
if (zerg_fd == -1) {
break;
}
uwsgi_sock = uwsgi_new_socket(NULL);
uwsgi_add_socket_from_fd(uwsgi_sock, zerg_fd);
i++;
}
uwsgi_log("zerg sockets attached\n");
}
}
void uwsgi_setup_inherited_sockets() {
int j;
union uwsgi_sockaddr usa;
union uwsgi_sockaddr_ptr gsa;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
//a bit overengineering
if (uwsgi_sock->name[0] != 0 && !uwsgi_sock->bound) {
for (j = 3; j < (int) uwsgi.max_fd; j++) {
uwsgi_add_socket_from_fd(uwsgi_sock, j);
}
}
uwsgi_sock = uwsgi_sock->next;
}
//now close all the unbound fd
for (j = 3; j < (int) uwsgi.max_fd; j++) {
int useless = 1;
#ifdef UWSGI_MULTICAST
if (j == uwsgi.cluster_fd)
continue;
#endif
if (uwsgi.has_emperor) {
if (j == uwsgi.emperor_fd)
continue;
}
if (uwsgi.shared->worker_log_pipe[0] > -1) {
if (j == uwsgi.shared->worker_log_pipe[0])
continue;
}
if (uwsgi.shared->worker_log_pipe[1] > -1) {
if (j == uwsgi.shared->worker_log_pipe[1])
continue;
}
if (uwsgi.original_log_fd > -1) {
if (j == uwsgi.original_log_fd)
continue;
}
if (uwsgi.cache_server && uwsgi.cache_server_fd != -1) {
if (j == uwsgi.cache_server_fd)
continue;
}
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
int found = 0;
while (ugs) {
if (ugs->fd == j) {
found = 1;
break;
}
ugs = ugs->next;
}
if (found)
continue;
int y;
found = 0;
for (y = 0; y < ushared->gateways_cnt; y++) {
if (ushared->gateways[y].internal_subscription_pipe[0] == j) {
found = 1;
break;
}
if (ushared->gateways[y].internal_subscription_pipe[1] == j) {
found = 1;
break;
}
}
if (found)
continue;
socklen_t socket_type_len = sizeof(struct sockaddr_un);
gsa.sa = (struct sockaddr *) &usa;
if (!getsockname(j, gsa.sa, &socket_type_len)) {
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->fd == j && uwsgi_sock->bound) {
useless = 0;
break;
}
uwsgi_sock = uwsgi_sock->next;
}
if (useless) {
uwsgi_sock = uwsgi.shared_sockets;
while (uwsgi_sock) {
if (uwsgi_sock->fd == j && uwsgi_sock->bound) {
useless = 0;
break;
}
uwsgi_sock = uwsgi_sock->next;
}
}
}
if (useless) {
close(j);
}
}
}
+66 -3
View File
@@ -53,7 +53,7 @@ int uwsgi_signal_handler(uint8_t sig) {
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0 && (getpid() == uwsgi.shared->spooler_pid)) {
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
@@ -75,7 +75,7 @@ int uwsgi_signal_handler(uint8_t sig) {
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0 && (getpid() == uwsgi.shared->spooler_pid)) {
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
@@ -109,7 +109,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
return -1;
}
strcpy(use->receiver, receiver);
strncpy(use->receiver, receiver, strlen(receiver)+1);
use->handler = handler;
use->modifier1 = modifier1;
use->wid = uwsgi.mywid;
@@ -262,8 +262,39 @@ int uwsgi_add_timer(uint8_t sig, int secs) {
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
int i;
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while(uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = value+i;
}
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process) return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
@@ -289,6 +320,8 @@ int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month,
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
if (!uwsgi.master_process) return -1;
uwsgi_lock(uwsgi.rb_timer_table_lock);
if (ushared->rb_timers_cnt < 64) {
@@ -526,3 +559,33 @@ cycle:
return received_signal;
}
void uwsgi_receive_signal(int fd, char *name, int id) {
uint8_t uwsgi_signal;
ssize_t ret = read(fd, &uwsgi_signal, 1);
if (ret == 0) {
goto destroy;
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
uwsgi_error("[uwsgi-signal] read()");
goto destroy;
}
else if (ret > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on %s %d\n", uwsgi_signal, name, id);
}
}
return;
destroy:
// better to kill the whole worker...
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
end_me(0);
}
View File
+55
View File
@@ -350,6 +350,61 @@ static int get_snmp_integer(uint8_t * ptr, uint64_t * val) {
return size + oid_sz;
}
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
uwsgi.snmp = 1;
if (value) {
uwsgi.snmp_addr = value;
uwsgi.master_process = 1;
}
}
void uwsgi_opt_snmp_community(char *opt, char *value, void *foobar) {
uwsgi.snmp = 1;
uwsgi.snmp_community = value;
}
int uwsgi_setup_snmp(void) {
int snmp_fd = -1;
int i;
if (uwsgi.snmp) {
if (uwsgi.snmp_community) {
if (strlen(uwsgi.snmp_community) > 72) {
uwsgi_log("*** warning the supplied SNMP community string will be truncated to 72 chars ***\n");
memcpy(uwsgi.shared->snmp_community, uwsgi.snmp_community, 72);
}
else {
memcpy(uwsgi.shared->snmp_community, uwsgi.snmp_community, strlen(uwsgi.snmp_community) + 1);
}
}
uwsgi.shared->snmp_gvalue[0].type = SNMP_COUNTER64;
uwsgi.shared->snmp_gvalue[0].val = &uwsgi.workers[0].requests;
for (i = 0; i < uwsgi.numproc; i++) {
uwsgi.shared->snmp_gvalue[30 + i].type = SNMP_COUNTER64;
uwsgi.shared->snmp_gvalue[30 + i].val = &uwsgi.workers[i + 1].requests;
}
if (uwsgi.snmp_addr) {
snmp_fd = bind_to_udp(uwsgi.snmp_addr, 0, 0);
if (snmp_fd < 0) {
uwsgi_log("unable to bind to udp socket. SNMP service will be disabled.\n");
}
else {
uwsgi_log("SNMP server enabled on %s\n", uwsgi.snmp_addr);
event_queue_add_fd_read(uwsgi.master_queue, snmp_fd);
}
}
else {
uwsgi_log("SNMP agent enabled.\n");
}
}
return snmp_fd;
}
#else
#warning "*** SNMP support is disabled ***"
#endif
+1775
View File
File diff suppressed because it is too large Load Diff
+570
View File
@@ -0,0 +1,570 @@
#ifdef UWSGI_SPOOLER
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static void spooler_readdir(struct uwsgi_spooler *, char *dir);
#ifdef __linux__
static void spooler_scandir(struct uwsgi_spooler *, char *dir);
#endif
static void spooler_manage_task(struct uwsgi_spooler *, char *, char *);
// increment it whenever a signal is raised
static uint64_t wakeup = 0;
// function to allow waking up the spooler if blocked in event_wait
void spooler_wakeup() { wakeup++; }
void uwsgi_opt_add_spooler(char *opt, char *directory, void *mode) {
int i;
struct uwsgi_spooler *us;
if (access(directory, R_OK | W_OK | X_OK)) {
uwsgi_error("[spooler directory] access()");
exit(1);
}
if (uwsgi.spooler_numproc > 0) {
for(i=0;i<uwsgi.spooler_numproc;i++) {
us = uwsgi_new_spooler(directory);
if (mode) us->mode = (long) mode;
}
}
else {
us = uwsgi_new_spooler(directory);
if (mode) us->mode = (long) mode;
}
}
struct uwsgi_spooler *uwsgi_new_spooler(char *dir) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
if (!uspool) {
uwsgi.spoolers = uwsgi_calloc_shared(sizeof(struct uwsgi_spooler));
uspool = uwsgi.spoolers;
}
else {
while(uspool) {
if (uspool->next == NULL) {
uspool->next = uwsgi_calloc_shared(sizeof(struct uwsgi_spooler));
uspool = uspool->next;
break;
}
uspool = uspool->next;
}
}
if (!realpath(dir, uspool->dir)) {
uwsgi_error("[spooler] realpath()");
exit(1);
}
uspool->next = NULL;
return uspool;
}
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while(uspool) {
if (!strcmp(uspool->dir, name)) {
return uspool;
}
uspool = uspool->next;
}
return NULL;
}
pid_t spooler_start(struct uwsgi_spooler *uspool) {
int i;
pid_t pid = uwsgi_fork("uWSGI spooler");
if (pid < 0) {
uwsgi_error("fork()");
exit(1);
}
else if (pid == 0) {
// USR1 will be used to wake up the spooler
uwsgi_unix_signal(SIGUSR1, spooler_wakeup);
uwsgi.mywid = -1;
uwsgi.mypid = getpid();
uspool->pid = uwsgi.mypid;
// avoid race conditions !!!
uwsgi.i_am_a_spooler = uspool;
uwsgi_fixup_fds(0, 0, NULL);
uwsgi_close_all_sockets();
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->spooler_init) {
uwsgi.gp[i]->spooler_init();
}
}
spooler(uspool);
}
else if (pid > 0) {
uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uspool->dir, pid);
}
return pid;
}
void destroy_spool(char *dir, char *file) {
if (chdir(dir)) {
uwsgi_error("chdir()");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
if (unlink(file)) {
uwsgi_error("unlink()");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
}
int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core_id, char *buffer, int size, char *priority, time_t at, char *body, size_t body_len) {
struct timeval tv;
int fd;
struct uwsgi_header uh;
if (!uspool) {
uspool = uwsgi.spoolers;
}
// this lock is for threads, the pid value in filename will avoid multiprocess races
uwsgi_lock(uspool->lock);
gettimeofday(&tv, NULL);
if (priority) {
if (snprintf(filename, 1024, "%s/%s", uspool->dir, priority) <= 0) {
uwsgi_unlock(uspool->lock);
return 0;
}
// no need to check for errors...
(void) mkdir(filename, 0777);
if (snprintf(filename, 1024, "%s/%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uspool->dir, priority, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
uwsgi_unlock(uspool->lock);
return 0;
}
}
else {
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
uwsgi_unlock(uspool->lock);
return 0;
}
}
fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
uwsgi_error_open(filename);
uwsgi_unlock(uspool->lock);
return 0;
}
// now lock the file, it will no be runnable, until the lock is not removed
// a race could come if the spooler take the file before fcntl is called
// in such case the spooler will detect a zeroed file and will retry later
if (uwsgi_fcntl_lock(fd)) {
close(fd);
uwsgi_unlock(uspool->lock);
return 0;
}
uh.modifier1 = 17;
uh.modifier2 = 0;
uh.pktsize = (uint16_t) size;
#ifdef __BIG_ENDIAN__
uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif
if (write(fd, &uh, 4) != 4) {
goto clear;
}
if (write(fd, buffer, size) != size) {
goto clear;
}
if (body && body_len > 0) {
if ((size_t)write(fd, body, body_len) != body_len) {
goto clear;
}
}
if (at > 0) {
struct timeval tv[2];
tv[0].tv_sec = at;
tv[0].tv_usec = 0;
tv[1].tv_sec = at;
tv[1].tv_usec = 0;
#ifdef __sun__
if (futimesat(fd, NULL, tv)) {
#else
if (futimes(fd, tv)) {
#endif
uwsgi_error("futimes()");
}
}
// here the file will be unlocked too
close(fd);
if (!uwsgi.spooler_quiet)
uwsgi_log("[spooler] written %d bytes to file %s\n", size + body_len + 4, filename);
// and here waiting threads can continue
uwsgi_unlock(uspool->lock);
/* wake up the spoolers attached to the specified dir ... (HACKY)
no need to fear races, as USR1 is harmless an all of the uWSGI processes...
it could be a problem if a new process takes the old pid, but modern systems should avoid that
*/
struct uwsgi_spooler *spoolers = uwsgi.spoolers;
while(spoolers) {
if (!strcmp(spoolers->dir, uspool->dir)) {
if (spoolers->pid > 0 && spoolers->running == 0) {
(void) kill(spoolers->pid, SIGUSR1);
}
}
spoolers = spoolers->next;
}
return 1;
clear:
uwsgi_unlock(uspool->lock);
uwsgi_error("write()");
if (unlink(filename)) {
uwsgi_error("unlink()");
}
// unlock the file too
close(fd);
return 0;
}
void spooler(struct uwsgi_spooler *uspool) {
// prevent process blindly reading stdin to make mess
int nullfd;
// asked by Marco Beri
#ifdef __HAIKU__
#ifdef UWSGI_DEBUG
uwsgi_log("lowering spooler priority to %d\n", B_LOW_PRIORITY);
#endif
set_thread_priority(find_thread(NULL), B_LOW_PRIORITY);
#else
#ifdef UWSGI_DEBUG
uwsgi_log("lowering spooler priority to %d\n", PRIO_MAX);
#endif
setpriority(PRIO_PROCESS, getpid(), PRIO_MAX);
#endif
nullfd = open("/dev/null", O_RDONLY);
if (nullfd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (nullfd != 0) {
dup2(nullfd, 0);
close(nullfd);
}
int spooler_event_queue = event_queue_init();
int interesting_fd = -1;
if (uwsgi.master_process) {
event_queue_add_fd_read(spooler_event_queue, uwsgi.shared->spooler_signal_pipe[1]);
}
// reset the tasks counter
uspool->tasks = 0;
for (;;) {
if (chdir(uspool->dir)) {
uwsgi_error("chdir()");
exit(1);
}
if (uwsgi.spooler_ordered) {
#ifdef __linux__
spooler_scandir(uspool, NULL);
#else
spooler_readdir(uspool, NULL);
#endif
}
else {
spooler_readdir(uspool, NULL);
}
int timeout = uwsgi.shared->spooler_frequency;
if (wakeup > 0) {
timeout = 0;
}
if (event_queue_wait(spooler_event_queue, timeout, &interesting_fd) > 0) {
if (uwsgi.master_process) {
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[1]) {
uwsgi_receive_signal(interesting_fd, "spooler", (int) getpid());
}
}
}
// avoid races
uint64_t tmp_wakeup = wakeup;
if (tmp_wakeup > 0) {
tmp_wakeup--;
}
wakeup = tmp_wakeup;
// need to recycle ?
if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t)uwsgi.spooler_max_tasks) {
uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
end_me(0);
}
}
}
#ifdef __linux__
static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
struct dirent **tasklist;
int n;
if (!dir) dir = uspool->dir;
n = scandir(dir, &tasklist, 0, versionsort);
if (n < 0) {
uwsgi_error("scandir()");
return;
}
while(n--) {
spooler_manage_task(uspool, dir, tasklist[n]->d_name);
free(tasklist[n]);
}
free(tasklist);
}
#endif
static void spooler_readdir(struct uwsgi_spooler *uspool, char *dir) {
DIR *sdir;
struct dirent *dp;
if (!dir) dir = uspool->dir;
sdir = opendir(dir);
if (sdir) {
while ((dp = readdir(sdir)) != NULL) {
spooler_manage_task(uspool, dir, dp->d_name);
}
closedir(sdir);
}
else {
uwsgi_error("opendir()");
}
}
void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
int i, ret;
char spool_buf[0xffff];
struct uwsgi_header uh;
char *body = NULL;
size_t body_len = 0;
int spool_fd;
if (!dir) dir = uspool->dir;
if (!strncmp("uwsgi_spoolfile_on_", task, 19) || (uwsgi.spooler_ordered && is_a_number(task))) {
struct stat sf_lstat;
if (lstat(task, &sf_lstat)) {
return;
}
// a spool request for the future
if (sf_lstat.st_mtime > uwsgi_now()) {
return;
}
#ifdef __linux__
if (S_ISDIR(sf_lstat.st_mode) && uwsgi.spooler_ordered) {
if (chdir(task)) {
uwsgi_error("chdir()");
return;
}
char *prio_path = realpath(".", NULL);
spooler_scandir(uspool, prio_path);
free(prio_path);
if (chdir(dir)) {
uwsgi_error("chdir()");
}
return;
}
#endif
if (!S_ISREG(sf_lstat.st_mode)) {
return;
}
if (!access(task, R_OK | W_OK)) {
spool_fd = open(task, O_RDWR);
if (spool_fd < 0) {
if (errno != ENOENT)
uwsgi_error_open(task);
return;
}
// check if the file is locked by another process
if (uwsgi_fcntl_is_locked(spool_fd)) {
uwsgi_protected_close(spool_fd);
return;
}
// unlink() can destroy the lock !!!
if (access(task, R_OK | W_OK)) {
uwsgi_protected_close(spool_fd);
return;
}
ssize_t rlen = uwsgi_protected_read(spool_fd, &uh, 4);
if (rlen != 4) {
// it could be here for broken file or just opened one
if (rlen < 0)
uwsgi_error("read()");
uwsgi_protected_close(spool_fd);
return;
}
#ifdef __BIG_ENDIAN__
uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif
if (uwsgi_protected_read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
uwsgi_error("read()");
destroy_spool(dir, task);
uwsgi_protected_close(spool_fd);
return;
}
// body available ?
if (sf_lstat.st_size > (uh.pktsize+4)) {
body_len = sf_lstat.st_size - (uh.pktsize+4);
body = uwsgi_malloc(body_len);
if ((size_t)uwsgi_protected_read(spool_fd, body, body_len) != body_len) {
uwsgi_error("read()");
destroy_spool(dir, task);
uwsgi_protected_close(spool_fd);
free(body);
return;
}
}
// now the task is running and should not be waken up
uspool->running = 1;
if (!uwsgi.spooler_quiet)
uwsgi_log("[spooler %s pid: %d] managing request %s ...\n", uspool->dir, (int) uwsgi.mypid, task);
// chdir before running the task (if requested)
if (uwsgi.spooler_chdir) {
if (chdir(uwsgi.spooler_chdir)) {
uwsgi_error("chdir()");
}
}
int callable_found = 0;
for(i=0;i<256;i++) {
if (uwsgi.p[i]->spooler) {
time_t now = uwsgi_now();
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
if (ret == 0) continue;
callable_found = 1;
// increase task counter
uspool->tasks++;
if (ret == -2) {
if (!uwsgi.spooler_quiet)
uwsgi_log("[spooler %s pid: %d] done with task %s after %d seconds\n", uspool->dir, (int) uwsgi.mypid, task, uwsgi_now()-now);
destroy_spool(dir, task);
}
// re-spool it
break;
}
}
if (body)
free(body);
// here we free and unlock the task
uwsgi_protected_close(spool_fd);
uspool->running = 0;
if (chdir(dir)) {
uwsgi_error("chdir()");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
if (!callable_found) {
uwsgi_log("unable to find the spooler function, have you loaded it into the spooler process ?\n");
}
}
}
}
#else
#warning "*** Spooler support is disabled ***"
#endif
View File
+266
View File
@@ -0,0 +1,266 @@
#include "uwsgi.h"
/*
utility functions for fast generating json output for the stats subsystem
*/
struct uwsgi_stats *uwsgi_stats_new(size_t chunk_size) {
struct uwsgi_stats *us = uwsgi_malloc(sizeof(struct uwsgi_stats));
us->base = uwsgi_malloc(chunk_size);
us->base[0] = '{';
us->base[1] = '\n';
us->pos = 2;
us->chunk = chunk_size;
us->size = chunk_size;
us->tabs = 1;
return us;
}
int uwsgi_stats_symbol(struct uwsgi_stats *us, char sym) {
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
if (ptr+1 > watermark) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
}
*ptr = sym;
us->pos++;
return 0;
}
int uwsgi_stats_symbol_nl(struct uwsgi_stats *us, char sym) {
if (uwsgi_stats_symbol(us, sym)) {
return -1;
}
return uwsgi_stats_symbol(us, '\n');
}
int uwsgi_stats_comma(struct uwsgi_stats *us) {
return uwsgi_stats_symbol_nl(us, ',');
}
int uwsgi_stats_apply_tabs(struct uwsgi_stats *us) {
size_t i;
for(i=0;i<us->tabs;i++) {
if (uwsgi_stats_symbol(us, '\t')) return -1;
};
return 0;
}
int uwsgi_stats_object_open(struct uwsgi_stats *us) {
if (uwsgi_stats_apply_tabs(us)) return -1;
us->tabs++;
return uwsgi_stats_symbol_nl(us, '{');
}
int uwsgi_stats_object_close(struct uwsgi_stats *us) {
if (uwsgi_stats_symbol(us, '\n')) return -1;
us->tabs--;
if (uwsgi_stats_apply_tabs(us)) return -1;
return uwsgi_stats_symbol(us, '}');
}
int uwsgi_stats_list_open(struct uwsgi_stats *us) {
us->tabs++;
return uwsgi_stats_symbol_nl(us, '[');
}
int uwsgi_stats_list_close(struct uwsgi_stats *us) {
if (uwsgi_stats_symbol(us, '\n')) return -1;
us->tabs--;
if (uwsgi_stats_apply_tabs(us)) return -1;
return uwsgi_stats_symbol(us, ']');
}
int uwsgi_stats_keyval(struct uwsgi_stats *us, char *key, char *value) {
if (uwsgi_stats_apply_tabs(us)) return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
int ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
if (ret < 0) return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_keyval_comma(struct uwsgi_stats *us, char *key, char *value) {
int ret = uwsgi_stats_keyval(us, key, value);
if (ret) return -1;
return uwsgi_stats_comma(us);
}
int uwsgi_stats_keyvalnum(struct uwsgi_stats *us, char *key, char *value, unsigned long long num) {
if (uwsgi_stats_apply_tabs(us)) return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
int ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
if (ret < 0) return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_keyvalnum_comma(struct uwsgi_stats *us, char *key, char *value, unsigned long long num) {
int ret = uwsgi_stats_keyvalnum(us, key, value, num);
if (ret) return -1;
return uwsgi_stats_comma(us);
}
int uwsgi_stats_keyvaln(struct uwsgi_stats *us, char *key, char *value, int vallen) {
if (uwsgi_stats_apply_tabs(us)) return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
int ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
if (ret < 0) return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_keyvaln_comma(struct uwsgi_stats *us, char *key, char *value, int vallen) {
int ret = uwsgi_stats_keyvaln(us, key, value, vallen);
if (ret) return -1;
return uwsgi_stats_comma(us);
}
int uwsgi_stats_key(struct uwsgi_stats *us, char *key) {
if (uwsgi_stats_apply_tabs(us)) return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
int ret = snprintf(ptr, available, "\"%s\":", key);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\":", key);
if (ret < 0) return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
int ret = snprintf(ptr, available, "\"%s\"", str);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\"", str);
if (ret < 0) return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long num) {
if (uwsgi_stats_apply_tabs(us)) return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
int ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
if (ret < 0) return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_keylong_comma(struct uwsgi_stats *us, char *key, unsigned long long num) {
int ret = uwsgi_stats_keylong(us, key, num);
if (ret) return -1;
return uwsgi_stats_comma(us);
}
+309 -50
View File
@@ -18,13 +18,28 @@
*/
extern struct uwsgi_server uwsgi;
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, int regexp) {
struct uwsgi_subscribe_slot *current_slot = *slot;
if (keylen > 0xff) return NULL;
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
struct uwsgi_subscribe_slot *current_slot = slot[hash_key];
#ifdef UWSGI_DEBUG
uwsgi_log("****************************\n");
while(current_slot) {
uwsgi_log("slot %.*s %d\n", current_slot->keylen, current_slot->key, current_slot->hits);
current_slot = current_slot->next;
}
uwsgi_log("****************************\n");
current_slot = slot[hash_key];
#endif
while(current_slot) {
#ifdef UWSGI_PCRE
@@ -44,7 +59,11 @@ struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slo
slot_parent->next = current_slot;
}
else {
*slot = current_slot;
slot[hash_key] = current_slot;
}
if (current_slot->next) {
current_slot->next->prev = slot_prev;
}
slot_prev->prev = current_slot;
@@ -62,7 +81,7 @@ struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slo
#endif
current_slot = current_slot->next;
// check for loopy optimization
if (current_slot == *slot) break;
if (current_slot == slot[hash_key]) break;
}
return NULL;
@@ -73,21 +92,21 @@ struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slo
if (keylen > 0xff) return NULL;
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen, regexp);
uint64_t rr_pos = 0;
if (current_slot) {
// node found, move up in the list increasing hits
// slot found, move up in the list increasing hits
current_slot->hits++;
time_t current = time(NULL);
time_t now = uwsgi_now();
struct uwsgi_subscribe_node *node = current_slot->nodes;
while(node) {
// is the node alive ?
if (current - node->last_check > uwsgi.subscription_tolerance) {
if (now - node->last_check > uwsgi.subscription_tolerance) {
if (node->death_mark == 0)
uwsgi_log("[uwsgi-subscription] %.*s => marking %.*s as failed (no announce received in %d seconds)\n", (int) keylen, key, (int) node->len, node->name, uwsgi.subscription_tolerance);
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => marking %.*s as failed (no announce received in %d seconds)\n", (int) uwsgi.mypid, (int) keylen, key, (int) node->len, node->name, uwsgi.subscription_tolerance);
node->failcnt++;
node->death_mark = 1;
}
// is the node must be removed ?
if (node->death_mark && node->reference == 0) {
// remove the node and move to next
struct uwsgi_subscribe_node *dead_node = node;
@@ -98,22 +117,41 @@ struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slo
}
continue;
}
// only unmarked nodes can respond
if (node->death_mark == 0 && rr_pos == current_slot->rr) {
current_slot->rr++;
if (node->death_mark == 0 && node->wrr > 0) {
node->wrr--;
node->reference++;
return node;
}
node = node->next;
rr_pos++;
}
current_slot->rr = 1;
if (current_slot->nodes) {
if (current_slot->nodes->death_mark)
return NULL;
current_slot->nodes->reference++;
// no wrr > 0 node found, reset them
node = current_slot->nodes;
uint64_t min_weight = 0;
while(node) {
if (!node->death_mark) {
if (min_weight == 0 || node->weight < min_weight) min_weight = node->weight;
}
node = node->next;
}
return current_slot->nodes;
// now set wrr
node = current_slot->nodes;
struct uwsgi_subscribe_node *choosen_node = NULL;
while(node) {
if (!node->death_mark) {
node->wrr = node->weight/min_weight;
choosen_node = node;
}
node = node->next;
}
if (choosen_node) {
choosen_node->wrr--;
choosen_node->reference++;
}
return choosen_node;
}
return NULL;
@@ -145,6 +183,8 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
struct uwsgi_subscribe_slot *prev_slot = node_slot->prev;
struct uwsgi_subscribe_slot *next_slot = node_slot->next;
int hash_key = node_slot->hash;
// over-engineering to avoid race conditions
node->len = 0;
@@ -170,14 +210,28 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
// first check if i am the only node
if ((!prev_slot && !next_slot) || next_slot == node_slot) {
#ifdef UWSGI_PCRE
if (node_slot->pattern) {
pcre_free(node_slot->pattern);
}
if (node_slot->pattern_extra) {
pcre_free(node_slot->pattern_extra);
}
#endif
#ifdef UWSGI_SSL
if (uwsgi.subscriptions_sign_check_dir) {
EVP_PKEY_free(node_slot->sign_public_key);
EVP_MD_CTX_destroy(node_slot->sign_ctx);
}
#endif
free(node_slot);
*slot = NULL;
slot[hash_key] = NULL;
goto end;
}
// if i am the main entry point, set the next value
if (node_slot == *slot) {
*slot = next_slot;
if (node_slot == slot[hash_key]) {
slot[hash_key] = next_slot;
}
if (prev_slot) {
@@ -195,13 +249,13 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
pcre_free(node_slot->pattern_extra);
}
#endif
free(node_slot);
struct uwsgi_subscribe_slot *x_slot = *slot;
while(x_slot) {
x_slot = x_slot->next;
#ifdef UWSGI_SSL
if (uwsgi.subscriptions_sign_check_dir) {
EVP_PKEY_free(node_slot->sign_public_key);
EVP_MD_CTX_destroy(node_slot->sign_ctx);
}
#endif
free(node_slot);
}
end:
@@ -214,23 +268,50 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, usr->key, usr->keylen, 0), *old_slot = NULL, *a_slot;
struct uwsgi_subscribe_node *node, *old_node = NULL;
if (usr->address_len > 0xff) return NULL;
if (usr->address_len > 0xff || usr->address_len == 0) return NULL;
#ifdef UWSGI_SSL
if (uwsgi.subscriptions_sign_check_dir) {
if (usr->sign_len == 0 || usr->base_len == 0) return NULL;
}
#endif
if (current_slot) {
#ifdef UWSGI_SSL
if (uwsgi.subscriptions_sign_check_dir && !uwsgi_subscription_sign_check(current_slot, usr)) {
return NULL;
}
#endif
node = current_slot->nodes;
while(node) {
if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) {
#ifdef UWSGI_SSL
// this should avoid sending sniffed packets...
if (uwsgi.subscriptions_sign_check_dir && usr->unix_check <= node->unix_check) {
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n",(int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
return NULL;
}
#endif
// remove death mark and update cores and load
node->death_mark = 0;
node->last_check = time(NULL);
node->last_check = uwsgi_now();
node->cores = usr->cores;
node->load = usr->load;
node->weight = usr->weight;
if (!node->weight) node->weight = 1;
return node;
}
old_node = node;
node = node->next;
}
#ifdef UWSGI_SSL
if (uwsgi.subscriptions_sign_check_dir && usr->unix_check < (uwsgi_now()-(time_t)uwsgi.subscriptions_sign_check_tolerance)) {
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n",(int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
return NULL;
}
#endif
node = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
node->len = usr->address_len;
node->modifier1 = usr->modifier1;
@@ -242,24 +323,68 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
node->failcnt = 0;
node->cores = usr->cores;
node->load = usr->load;
node->last_check = time(NULL);
node->weight = usr->weight;
node->unix_check = usr->unix_check;
if (!node->weight) node->weight = 1;
node->wrr = 0;
node->last_check = uwsgi_now();
node->slot = current_slot;
memcpy(node->name, usr->address, usr->address_len);
if (old_node) {
old_node->next = node;
}
node->next = NULL;
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n",(int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address);
return node;
}
else {
#ifdef UWSGI_SSL
FILE *kf = NULL;
if (uwsgi.subscriptions_sign_check_dir) {
if (usr->unix_check < (uwsgi_now()-(time_t)uwsgi.subscriptions_sign_check_tolerance)) {
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n",(int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
return NULL;
}
char *keyfile = uwsgi_sanitize_cert_filename(uwsgi.subscriptions_sign_check_dir, usr->key, usr->keylen);
kf = fopen(keyfile, "r");
free(keyfile);
if (!kf) return NULL;
}
#endif
current_slot = uwsgi_malloc(sizeof(struct uwsgi_subscribe_slot));
uint32_t hash = djb33x_hash(usr->key, usr->keylen);
int hash_key = hash % 0xffff;
current_slot->hash = hash_key;
#ifdef UWSGI_SSL
if (uwsgi.subscriptions_sign_check_dir) {
current_slot->sign_public_key = PEM_read_PUBKEY(kf, NULL, NULL, NULL);
fclose(kf);
if (!current_slot->sign_public_key) {
uwsgi_log("unable to load public key for %.*s\n", usr->keylen, usr->key);
free(current_slot);
return NULL;
}
current_slot->sign_ctx = EVP_MD_CTX_create();
if (!current_slot->sign_ctx) {
uwsgi_log("unable to initialize EVP context for %.*s\n", usr->keylen, usr->key);
EVP_PKEY_free(current_slot->sign_public_key);
free(current_slot);
return NULL;
}
if (!uwsgi_subscription_sign_check(current_slot, usr)) {
EVP_PKEY_free(current_slot->sign_public_key);
EVP_MD_CTX_destroy(current_slot->sign_ctx);
free(current_slot);
return NULL;
}
}
#endif
current_slot->keylen = usr->keylen;
memcpy(current_slot->key, usr->key, usr->keylen);
current_slot->key[usr->keylen] = 0;
current_slot->hits = 0;
current_slot->rr = 0;
#ifdef UWSGI_PCRE
current_slot->pattern = NULL;
@@ -284,8 +409,12 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
current_slot->nodes->modifier2 = usr->modifier2;
current_slot->nodes->cores = usr->cores;
current_slot->nodes->load = usr->load;
current_slot->nodes->weight = usr->weight;
current_slot->nodes->unix_check = usr->unix_check;
if (!current_slot->nodes->weight) current_slot->nodes->weight = 1;
current_slot->nodes->wrr = 0;
memcpy(current_slot->nodes->name, usr->address, usr->address_len);
current_slot->nodes->last_check = time(NULL);
current_slot->nodes->last_check = uwsgi_now();
current_slot->nodes->next = NULL;
@@ -293,7 +422,7 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
// if key is a regexp, order it by keylen
if (regexp) {
old_slot = NULL;
a_slot = *slot;
a_slot = slot[hash_key];
while(a_slot) {
if (a_slot->keylen > current_slot->keylen) {
old_slot = a_slot;
@@ -312,7 +441,7 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
current_slot->next = old_slot;
}
else {
a_slot = *slot;
a_slot = slot[hash_key];
while(a_slot) {
old_slot = a_slot;
a_slot = a_slot->next;
@@ -329,7 +458,7 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
}
else {
#endif
a_slot = *slot;
a_slot = slot[hash_key];
while(a_slot) {
old_slot = a_slot;
a_slot = a_slot->next;
@@ -347,33 +476,50 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
}
#endif
if (!*slot || current_slot->prev == NULL) {
*slot = current_slot;
if (!slot[hash_key] || current_slot->prev == NULL) {
slot[hash_key] = current_slot;
}
uwsgi_log("[uwsgi-subscription] new pool: %.*s\n", usr->keylen, usr->key);
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
uwsgi_log("[uwsgi-subscription for pid %d] new pool: %.*s (hash key: %d)\n",(int) uwsgi.mypid, usr->keylen, usr->key, current_slot->hash);
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n",(int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address);
return current_slot->nodes;
}
}
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd) {
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign) {
char value_cores[sizeof(UMAX64_STR)+1];
char value_load[sizeof(UMAX64_STR)+1];
char value_modifier1[4];
char value_modifier2[4];
char value_weight[sizeof(UMAX64_STR)+1];
int value_cores_size = uwsgi_long2str2n(uwsgi.numproc*uwsgi.cores, value_cores, sizeof(UMAX64_STR));
int value_load_size = uwsgi_long2str2n(uwsgi.shared->load, value_load, sizeof(UMAX64_STR));
int value_weight_size = 0;
if (uwsgi.auto_weight) {
value_weight_size = uwsgi_long2str2n(uwsgi.numproc*uwsgi.cores, value_weight, sizeof(UMAX64_STR));
}
else {
value_weight_size = uwsgi_long2str2n(uwsgi.weight, value_weight, sizeof(UMAX64_STR));
}
char value_modifier1[4];
char value_modifier2[4];
int value_modifier1_size = uwsgi_long2str2n(modifier1, value_modifier1, 3);
int value_modifier2_size = uwsgi_long2str2n(modifier2, value_modifier2, 3);
if (!uwsgi.sockets) return;
if (socket_name == NULL && !uwsgi.sockets) return;
size_t ssb_size = 4 + (2 + 3) + (2 + keysize) + (2 + 7) + (2 + strlen(uwsgi.sockets->name)) + (2+9 + 2+value_modifier1_size) +
(2+9 + 2+value_modifier2_size) + (2+5 + 2+value_cores_size) + (2+4 + 2+value_load_size);
if (!socket_name) {
socket_name = uwsgi.sockets->name;
}
size_t ssb_size = 4 + (2 + 3) + (2 + keysize) + (2 + 7) + (2 + strlen(socket_name)) + (2+9 + 2+value_modifier1_size) +
(2+9 + 2+value_modifier2_size) + (2+5 + 2+value_cores_size) + (2+4 + 2+value_load_size) + (2+6 + 2+value_weight_size);
char *subscrbuf = uwsgi_malloc(ssb_size);
// leave space for uwsgi header
@@ -399,10 +545,10 @@ void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8
memcpy(ssb, "address", ustrlen);
ssb+=ustrlen;
ustrlen = strlen(uwsgi.sockets->name);
ustrlen = strlen(socket_name);
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, uwsgi.sockets->name, ustrlen);
memcpy(ssb, socket_name, ustrlen);
ssb+=ustrlen;
// modifier1 = "modifier1"
@@ -456,9 +602,122 @@ void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, value_load, value_load_size);
ssb+=ustrlen;
// weight
ustrlen = 6;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "weight", ustrlen);
ssb+=ustrlen;
ustrlen = value_weight_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, value_weight, value_weight_size);
ssb+=ustrlen;
#ifdef UWSGI_SSL
if (sign) {
// add space for "unix" item
char unix_dst[sizeof(UMAX64_STR)+1];
if (snprintf(unix_dst, sizeof(UMAX64_STR)+1, "%lu", (unsigned long) (uwsgi_now() + (time_t)cmd)) < 1) {
uwsgi_error("unable to generate unix time for subscription !!!\n");
free(subscrbuf);
return;
}
ssb_size += 2 + 4 + 2 + strlen(unix_dst);
char *new_buf = realloc(subscrbuf, ssb_size);
if (!new_buf) {
uwsgi_error("realloc()");
free(subscrbuf);
return;
}
// fix ssb (new_buf base could be changed)
ssb = (new_buf + (ssb-subscrbuf));
subscrbuf = new_buf;
ustrlen = 4;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "unix", ustrlen);
ssb+=ustrlen;
ustrlen = strlen(unix_dst);
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, unix_dst, strlen(unix_dst));
ssb+=ustrlen;
unsigned int signature_len = 0;
char *signature = uwsgi_rsa_sign(sign, subscrbuf+4, ssb_size-4, &signature_len);
if (signature && signature_len > 0) {
// add space for "sign" item
ssb_size += 2 + 4 + 2 + signature_len;
char *new_buf = realloc(subscrbuf, ssb_size);
if (!new_buf) {
uwsgi_error("realloc()");
free(signature);
free(subscrbuf);
return;
}
// fix ssb (new_buf base could be changed)
ssb = (new_buf + (ssb-subscrbuf));
subscrbuf = new_buf;
ustrlen = 4;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "sign", ustrlen);
ssb+=ustrlen;
ustrlen = signature_len;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, signature, signature_len);
ssb+=ustrlen;
free(signature);
}
}
#endif
send_udp_message(224, cmd, udp_address, subscrbuf, ssb_size-4);
free(subscrbuf);
}
#ifdef UWSGI_SSL
int uwsgi_subscription_sign_check(struct uwsgi_subscribe_slot *slot, struct uwsgi_subscribe_req *usr) {
if (EVP_VerifyInit_ex(slot->sign_ctx, uwsgi.subscriptions_sign_check_md, NULL) == 0) {
ERR_print_errors_fp(stderr);
return 0;
}
if (EVP_VerifyUpdate(slot->sign_ctx, usr->base, usr->base_len) == 0) {
ERR_print_errors_fp(stderr);
return 0;
}
if (EVP_VerifyFinal(slot->sign_ctx, (unsigned char *)usr->sign, usr->sign_len, slot->sign_public_key) != 1) {
#ifdef UWSGI_DEBUG
ERR_print_errors_fp(stderr);
#endif
return 0;
}
return 1;
}
#endif
int uwsgi_no_subscriptions(struct uwsgi_subscribe_slot **slot) {
int i;
for(i=0;i<UMAX16;i++) {
if (slot[i]) return 0;
}
return 1;
}
+4708
View File
File diff suppressed because it is too large Load Diff
+3714
View File
File diff suppressed because it is too large Load Diff
+271
View File
@@ -0,0 +1,271 @@
#ifdef UWSGI_XML
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_XML_LIBXML2
#include <libxml/parser.h>
#include <libxml/tree.h>
void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic_table[]) {
xmlDoc *doc = NULL;
xmlNode *element = NULL;
xmlNode *node = NULL;
xmlChar *node_mode;
char *colon;
char *xml_id;
char *xml_content;
int xml_size = 0;
if (uwsgi_check_scheme(filename)) {
colon = uwsgi_get_last_char(filename, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(filename, ':');
}
if (colon) {
colon[0] = 0;
colon++;
if (*colon == 0) {
uwsgi_log("invalid xml id\n");
exit(1);
}
uwsgi_log( "[uWSGI] using xml uwsgi id: %s\n", colon);
}
xml_content = uwsgi_open_and_read(filename, &xml_size, 0, magic_table);
doc = xmlReadMemory(xml_content, xml_size, filename, NULL, 0);
if (doc == NULL) {
uwsgi_log( "[uWSGI] could not parse file %s.\n", filename);
exit(1);
}
uwsgi_log( "[uWSGI] parsing config file %s\n", filename);
element = xmlDocGetRootElement(doc);
if (element == NULL) {
uwsgi_log( "[uWSGI] invalid xml config file.\n");
exit(1);
}
if (strcmp((char *) element->name, "uwsgi")) {
for (node = element->children; node; node = node->next) {
element = NULL;
if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, "uwsgi")) {
xml_id = (char *) xmlGetProp(node, (const xmlChar *) "id");
if (colon && xml_id) {
if ( strcmp(colon, xml_id) ) {
continue;
}
}
element = node;
break;
}
}
}
if (!element) {
uwsgi_log( "[uWSGI] invalid xml root element, <uwsgi> expected.\n");
exit(1);
}
}
// first check for options
for (node = element->children; node; node = node->next) {
node_mode = xmlGetProp(node, (const xmlChar *) "mode");
if (uwsgi.mode && node_mode) {
if (strcmp(uwsgi.mode, (char *) node_mode)) {
continue;
}
}
xml_id = (char *) xmlGetProp(node, (const xmlChar *) "id");
if (colon && xml_id) {
if (strcmp(colon, xml_id)) {
continue;
}
}
if (node->type == XML_CDATA_SECTION_NODE) {
if (node->content) {
add_exported_option((char *) "eval", strdup((char *) node->content), 0);
}
}
else if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, (char *) "app")) {
char *mountpoint = (char *) xmlGetProp(node, (const xmlChar *) "mountpoint");
char *domain = (char *) xmlGetProp(node, (const xmlChar *) "domain");
if (!node->children) {
add_exported_option("app", strdup(""), 0);
}
else if (node->children && node->children->content && !node->children->next) {
char *opt_value = strdup((char *) node->children->content);
if (mountpoint) {
opt_value = uwsgi_concat3(mountpoint,"=", opt_value);
}
else if (domain) {
opt_value = uwsgi_concat3(domain,"|=", opt_value);
}
add_exported_option("mount", opt_value, 0);
add_exported_option("app", strdup(""), 0);
}
else if (node->children && node->children->next && node->children->next->children && node->children->next->children->content) {
char *opt_value = strdup((char *) node->children->next->children->content);
if (mountpoint) {
opt_value = uwsgi_concat3(mountpoint,"=", opt_value);
}
else if (domain) {
opt_value = uwsgi_concat3(domain,"|=", opt_value);
}
add_exported_option("mount", opt_value, 0);
add_exported_option("app", strdup(""), 0);
}
}
else {
if (node->children) {
add_exported_option(strdup((char *) node->name), strdup((char *) node->children->content), 0);
}
else {
add_exported_option(strdup((char *) node->name), strdup("1"), 0);
}
}
}
}
/* We can safely free resources */
xmlFreeDoc(doc);
xmlCleanupParser();
}
#endif
#ifdef UWSGI_XML_EXPAT
#include <expat.h>
int uwsgi_xml_found_stanza = 0;
char *uwsgi_xml_found_opt_key = NULL;
static void startElement(void *xml_id, const XML_Char *name, const XML_Char **attrs) {
if (!uwsgi_xml_found_stanza) {
if (xml_id) {
if (!attrs[0]) return;
if (!attrs[1]) return;
if (strcmp("id", attrs[0])) return;
if (strcmp((char *)xml_id, attrs[1])) return;
}
if (!strcmp("uwsgi", name)) uwsgi_xml_found_stanza = 1;
}
else {
uwsgi_xml_found_opt_key = (char *) name;
}
}
static void textElement(void *xml_id, const char *s, int len) {
if (!uwsgi_xml_found_stanza) return ;
if (uwsgi_xml_found_opt_key) {
add_exported_option(strdup(uwsgi_xml_found_opt_key), uwsgi_concat2n((char *)s, len, (char *)"", 0), 0);
uwsgi_xml_found_opt_key = NULL;
}
}
static void endElement(void *xml_id, const XML_Char *name) {
if (!uwsgi_xml_found_stanza) return ;
if (!strcmp(name, "uwsgi")) {
uwsgi_xml_found_stanza = 0;
return;
}
if (!uwsgi_xml_found_opt_key) return;
add_exported_option(strdup(uwsgi_xml_found_opt_key), strdup("1"), 0);
uwsgi_xml_found_opt_key = NULL;
}
void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic_table[]) {
char *colon;
char *xml_content;
int xml_size = 0;
int done = 0;
if (uwsgi_check_scheme(filename)) {
colon = uwsgi_get_last_char(filename, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(filename, ':');
}
if (colon) {
colon[0] = 0;
colon++;
if (*colon == 0) {
uwsgi_log("invalid xml id\n");
exit(1);
}
uwsgi_log( "[uWSGI] using xml uwsgi id: %s\n", colon);
}
xml_content = uwsgi_open_and_read(filename, &xml_size, 0, magic_table);
uwsgi_log( "[uWSGI] parsing config file %s\n", filename);
XML_Parser parser = XML_ParserCreate(NULL);
XML_SetUserData(parser, NULL);
if (colon) {
XML_SetUserData(parser, colon);
}
XML_SetElementHandler(parser, startElement, endElement);
XML_SetCharacterDataHandler(parser, textElement);
do {
if (!XML_Parse(parser, xml_content, xml_size, done)) {
if (XML_GetErrorCode(parser) != XML_ERROR_JUNK_AFTER_DOC_ELEMENT) {
uwsgi_log("unable to parse xml file: %s (line %d)\n", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
exit(1);
}
else {
break;
}
}
} while(!done);
// we can safely free, as we have a copy of datas
XML_ParserFree(parser);
}
#endif
#else
#warning "*** XML configuration support is disabled ***"
#endif
+2 -2
View File
@@ -30,7 +30,7 @@ char *yaml_lstrip(char *line) {
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
if (line[i] == ' ' || line[i] == '\t') {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
}
@@ -51,7 +51,7 @@ int yaml_get_depth(char *line) {
depth++;
continue;
}
else if (line[i] == '\t') {
else if (line[i] == '\t' || line[i] == '\r') {
depth+=8;
continue;
}
-898
View File
@@ -1,898 +0,0 @@
#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);
}
-22
View File
@@ -1,22 +0,0 @@
#ifdef UWSGI_EVDIS
#include "uwsgi.h"
void evdis_loop(struct uwsgi_server *uwsgi) {
// populate event list
int kfd = kqueue();
if (kfd < 0) {
uwsgi_error("kqueue()");
exit(1);
}
}
#else
#warning "*** Event Dispatcher support is disabled ***"
#endif
View File
View File
+47
View File
@@ -0,0 +1,47 @@
[uwsgi]
for = 4031 14032 4033 14034 24035
socket = /tmp/%(_)/uwsgi.sock
socket = 192.*:%(_)
print = ciao %(_) hello %(_) bye %(_)
endfor =
socket = :4045
socket = :4046
socket = :4047
socket = :4048
socket = :4049
socket = :4050
socket = :4051
show-config =
if-env = PIPPO
print =
print = PIPPO e' definita e il suo valore e' %(_) boh
endif =
socket = :5051
socket = :5052
socket = :5053
socket = :5054
if-exists = /etc/services
print = il file %(_) esiste $(PATH)
endif =
if-exists = /etc/foobar
print = il file %(_) esiste $(PATH)
endif =
socket = :6060
if-file = /etc/fstab
socket = :7171
endif =
ifdir = /tmp
print = %(_) is a directory
endif=
+4
View File
@@ -19,4 +19,8 @@
<module>trac.web.main:dispatch_request</module>
</uwsgi>
<uwsgi>
<socket>:3031</socket>
</uwsgi>
</unbit>
View File
+18 -2
View File
@@ -1,5 +1,14 @@
<uwsgi>
<!--
DO NOT USE <app> TAG !!!
It is deprecated and will be removed from 1.2
-->
<plugins>psgi</plugins>
<plugins>rack</plugins>
<http>:9090</http>
@@ -24,6 +33,8 @@
<module>werkzeug.testapp:test_app</module>
</app>
<app mountpoint="/foobar">werkzeug.testapp:test_app</app>
<app mountpoint="/trac">
<module>trac.web.main:dispatch_request</module>
</app>
@@ -32,11 +43,12 @@
<module>werkzeug.testapp:test_app</module>
</app>
<!-- eval is broken -->
<app mountpoint="/bzr">
<eval>
<eval>
from bzrlib.transport.http import wsgi
application = wsgi.make_app("mybzr", "/bzr", readonly=False)
</eval>
</eval>
</app>
<app domain="sirius002:9090">
@@ -47,4 +59,8 @@ application = wsgi.make_app("mybzr", "/bzr", readonly=False)
<rack>config2.ru</rack>
</app>
<app mountpoint="precise64.local">
<psgi>test.psgi</psgi>
</app>
</uwsgi>
+21
View File
@@ -0,0 +1,21 @@
[uwsgi]
http-socket = :9090
route = ^/foo basicauth:foobar,kratos:
; a simple user:passowrd mapping
route = .* basicauth:nether realm 3,serena:alessandro
; htpasswd-like real-time parsing
route = .* basicauth:nether realm 2,.htpasswd
; user-only auth
route = .* basicauth:nether realm 4,roberta:
route = .* basicauth:nether realm 4,
route = ^/bar basicauth:foobar,kratos:
module = welcome
processes = 4
master = true
View File
View File

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