Compare commits

...
750 Commits
Author SHA1 Message Date
Unbit 5d6086c84a allows --attach-daemon without workers 2013-02-23 14:46:41 +01:00
Unbit a45be4f7a9 backported perl async fixes from 1.9 2013-02-23 13:35:41 +01:00
Unbit dd63bef92e backported --perl-arg and --perl-args 2013-02-23 13:28:51 +01:00
Unbit 621a05d879 another heroku python fix 2013-02-23 13:26:05 +01:00
Unbit b857690caf backported python plugin new build system (heroku friendly) 2013-02-23 12:07:45 +01:00
Unbit edb0a72dfd fixed a refcnt bug in psgi plugin 2013-02-23 08:26:08 +01:00
Unbit da4af442ad prepare for uWSGI 1.4.6 2013-02-20 16:03:27 +01:00
Unbit 04ff580075 improved muleloop in uwsgidecoraotors 2013-02-19 07:12:44 +01:00
Unbit 5925db13cf backported more logvars 2013-02-18 13:09:53 +01:00
Unbit d283fd1aae fixed master + emperor 2013-02-12 16:44:14 +01:00
Unbit 345b22d8f0 forget to reset SIGCHLD to SIG_DFL 2013-02-10 20:12:47 +01:00
Unbit b8fc89166d reset sigmask on startup 2013-02-10 19:52:50 +01:00
Unbit 50ffb9d258 reapply fixed-SERVER_PORT-in-routers-when-shared-sockets-are.patch 2013-02-09 17:34:31 +01:00
Unbit 9ae1b26d52 fixed suspend when harakiri is in place 2013-02-07 14:11:24 +01:00
Unbit f281d21a1b backported improved alarm_xmpp plugin 2013-01-31 09:59:54 +01:00
Unbit b9a2b92005 fixed PTHREAD_MUTEX_ROBUST [4] 2013-01-30 18:28:23 +01:00
Unbit 92a26d4ff6 fixed PTHREAD_MUTEX_ROBUST [3] 2013-01-30 18:26:24 +01:00
Unbit 51360416a7 fixed PTHREAD_MUTEX_ROBUST [2] 2013-01-30 18:20:22 +01:00
Unbit c7bc98a50c fixed PTHREAD_MUTEX_ROBUST 2013-01-30 18:16:24 +01:00
Unbit b4b5c0175a added __USE_UNIX98 to pthread.h 2013-01-30 18:14:37 +01:00
Unbit 7ed3eb36ee fixed PTHREAD_PRIO_INHERIT 2013-01-30 18:09:48 +01:00
Unbit 05c475f597 added --thunder-lock 2013-01-30 18:02:03 +01:00
Unbit c750dfc1e3 Revert "fixed SERVER_PORT in routers when shared sockets are in place"
This reverts commit 01b14f4395.
2013-01-30 16:57:59 +01:00
Unbit 01b14f4395 fixed SERVER_PORT in routers when shared sockets are in place 2013-01-30 16:32:19 +01:00
Unbit 46d7d4bf1d completed new logvars backport 2013-01-28 23:03:17 +01:00
Unbit 02d76f12e0 backported new logvars from 1.5 2013-01-28 22:44:54 +01:00
Unbit 719860a349 backported new rbtree implementation 2013-01-28 22:34:25 +01:00
Unbit 5cce0935fd backported master+emperor fix from 1.5 2013-01-28 16:37:13 +01:00
Unbit 24ef2a838f backported --touch-reload refactoring from 1.5 2013-01-28 16:23:57 +01:00
Unbit 8aa739b4b2 backported --emperor-procname 2013-01-26 04:20:00 +01:00
Unbit 9221e1953e fixed a cache collision bug 2013-01-23 20:22:28 +01:00
Roberto De Ioris 18592fb2bd fixed async mode when multiple fds are in place 2013-01-22 18:31:37 +01:00
Roberto De Ioris fc80eeb581 fixed bug in python uwsgi.workers() 2013-01-21 14:53:01 +01:00
Roberto De Ioris bc19b58681 prepare for uWSGI 1.4.5 2013-01-21 12:13:56 +01:00
Roberto De Ioris 8f2202eab5 reset cores/requests on worker startup 2013-01-21 12:13:32 +01:00
Roberto De Ioris aa2ecf14df correctly handle multithread exit 2013-01-21 12:09:25 +01:00
Roberto De Ioris 43f5792826 fixed test.psgi 2013-01-20 17:08:25 +01:00
unbit 36ff37e12c Update core/uwsgi.c 2013-01-18 09:21:16 +01:00
Roberto De Ioris 6dd6f961e8 removed a useless log 2013-01-16 19:34:41 +01:00
Roberto De Ioris 5dd5d92ffb fixed mule management 2013-01-16 17:10:22 +01:00
Roberto De Ioris 64f1b844bd fixed unix signal usage in mules and spooler 2013-01-16 16:50:10 +01:00
Roberto De Ioris e562c4691d fixed http-socket body storage leak 2013-01-16 16:27:47 +01:00
Roberto De Ioris 1cbab74f0e backported uwsgi::postfork and uwsgi::atexit 2013-01-16 14:52:13 +01:00
Roberto De Ioris 3053fdb25a backported --php-fallback 2013-01-14 16:44:30 +01:00
Roberto De Ioris f11f542242 improved mod_proxy_uwsgi 2013-01-13 12:37:22 +01:00
Roberto De Ioris 32ddf10cfa applied feature-extract-dump-the-specified-address-to-stdout.patch 2013-01-13 05:39:43 +01:00
Roberto De Ioris 1b54be396c applied Lua-bindings-for-lock-unlock-functions.patch 2013-01-13 05:38:01 +01:00
Roberto De Ioris f81a4f9736 fixed gevent leak 2013-01-12 17:18:53 +01:00
Roberto De Ioris 048b339593 allows building on debian etch 4 2013-01-10 22:26:24 +01:00
Roberto De Ioris 081a6b90bf added --python-version and --perl-version 2013-01-05 08:39:18 +01:00
Roberto De Ioris 97f1b6d649 fixed broodlord mode stats 2013-01-04 20:42:53 +01:00
Roberto De Ioris 593aba2b19 improved mod_proxy_uwsgi 2012-12-30 11:05:20 +01:00
Roberto De Ioris 47c9e5e3f0 fixed /proc check 2012-12-30 09:10:10 +01:00
Roberto De Ioris bca8bc0c4d fixed socket naming of fd 0 2012-12-30 09:07:38 +01:00
Roberto De Ioris a67dfdd542 fixed a https/corerouter corner-case bug 2012-12-21 11:32:33 +01:00
Roberto De Ioris d1bbe7e3f9 set HTTPS to on when behind stud 2012-12-21 09:01:10 +01:00
Roberto De Ioris 442c982aff backported --http-stud-prefix 2012-12-19 18:41:48 +01:00
Roberto De Ioris a2f50ccf2e report pos in failed uploads 2012-12-16 12:58:12 +01:00
Roberto De Ioris b1c5fef0dc fixed computation of post data 2012-12-16 12:18:13 +01:00
Roberto De Ioris f6d8ac52f4 applied more debug to https 2012-12-16 10:59:56 +01:00
Roberto De Ioris 94e4fcbfe1 added additional uwgsi-gevent error report 2012-12-15 20:36:26 +01:00
Roberto De Ioris c9e7b0f48e fixed wrong typecasting in yaml and fixed subscription system on 32 bit 2012-12-15 14:32:25 +01:00
Roberto De Ioris 2f932d8ca0 backported http internal router fixes 2012-12-13 15:34:47 +01:00
Roberto De Ioris c517320f7a prepare for next release (1.4.4) 2012-12-13 11:07:55 +01:00
Roberto De Ioris b0dae66264 applied 0001-allows-embedding-.cc-and-.m-files.patch 2012-12-13 11:07:37 +01:00
Roberto De Ioris 0d87ed7298 fix dup2() usage 2012-12-12 15:23:04 +01:00
Roberto De Ioris fd3291b11f uWSGI 1.4.3 2012-12-10 15:26:09 +01:00
Roberto De Ioris e5ac5d6352 added emperor:// to supported scheme 2012-12-10 14:16:13 +01:00
Roberto De Ioris 403bd604e2 backported fix for bug #66 2012-12-10 14:14:01 +01:00
Roberto De Ioris 045d8947ae applied 0001-missing-new-line-in-carbon-plugin-logs.patch 2012-12-10 14:12:29 +01:00
Roberto De Ioris a9f2c71863 applied 0001-fallback-to-REMOTE_ADDR-if-HTTP_X_FORWARDED_FOR-is-m.patch 2012-12-10 14:11:42 +01:00
Roberto De Ioris b504a1ebe8 applied 0001-fixed-log-format-in-cheaper_busyness.patch 2012-12-10 14:10:28 +01:00
Roberto De Ioris f05ce0d2fc applied 0001-improved-stdin-management-in-cron.patch 2012-12-10 14:08:55 +01:00
Roberto De Ioris a2f3c716b1 applied 0001-added-offload-thread-alias.patch 2012-12-10 14:06:39 +01:00
Roberto De Ioris 2d7ca36f60 preparing for 1.4.3 2012-12-10 14:05:30 +01:00
unbit 5370e535dd core: make smart-attach-daemon smart enough
Avoid call storming of pidfile check that leads to multiple daemons
running instead of one. Fix #65.
2012-11-28 20:52:59 +01:00
unbit 092767c29f Merge pull request #63 from xrmx/cpucount14
uwsgiconfig: permit to override CPUCOUNT with environment variable
2012-11-27 10:32:45 -08:00
Riccardo Magliocchetti 4e119e6838 uwsgiconfig: permit to override CPUCOUNT with environment variable
CPUCOUNT=X make

will force X cores instead of the autodetected ones
2012-11-27 19:25:49 +01:00
Roberto De Ioris 87ef444ea6 uWSGI 1.4.2 2012-11-24 11:27:06 +01:00
Roberto De Ioris 714be76f9b improved QUERY_STRING handling in router_rewrite, added --php-var 2012-11-24 11:26:25 +01:00
Roberto De Ioris af0f0da8c2 added --php-app-qs 2012-11-24 10:11:56 +01:00
Roberto De Ioris 8407372801 fixed PATH_TRANSLATED in php and improved offloading of bigger files 2012-11-24 10:11:12 +01:00
Roberto De Ioris d19c4e84fc applied 0001-fixed-corner-case-ssl-body-reading.patch 2012-11-24 10:10:08 +01:00
Roberto De Ioris 3342852a9a backported 0001-do-not-crash-on-non-existent-config-files.patch 2012-11-21 07:49:13 +01:00
Roberto De Ioris 586a02d849 backported fixes from 1.5 2012-11-21 07:42:32 +01:00
Roberto De Ioris 188dad744a uWSGI 1.4.1 2012-11-13 04:53:32 +01:00
Roberto De Ioris 6cf3bbea69 backported fixed for offloading, static maps and non-blocking connect 2012-11-13 04:41:14 +01:00
Roberto De Ioris 04736d371e backported 0001-corerouter-NOT-courerouter.patch 2012-11-12 13:33:14 +01:00
Roberto De Ioris cc9151f89e 'wsgi' option is an alias for 'module' not 'wsgi-file' 2012-11-12 11:57:55 +01:00
Roberto De Ioris e13734ae6c uWSGI 1.4 2012-11-12 10:45:05 +01:00
Roberto De Ioris cf62b03e33 endiness fixes and added support for not waiting for thread cancellation 2012-11-12 10:36:18 +01:00
Roberto De Ioris b2f292c2da some Changelong improvement 2012-11-12 09:46:47 +01:00
Roberto De Ioris b96b6a24a6 support for rack official commit afc9b0313c 2012-11-12 09:40:38 +01:00
Roberto De Ioris b2a1237781 added --undeferred-shared-socket 2012-11-11 19:41:00 +01:00
Roberto De Ioris a48af2e226 workaround missing IP_FREEBIND 2012-11-11 19:07:28 +01:00
Roberto De Ioris 33446c3179 better cap management 2012-11-11 18:59:05 +01:00
Roberto De Ioris 242e01e37a added 'wsgi' alias option 2012-11-11 17:32:18 +01:00
Roberto De Ioris 41eba2b486 report static nodes in corerouters stats 2012-11-10 11:51:19 +01:00
Roberto De Ioris 24763fdbd2 fixed xclient 2012-11-10 11:23:39 +01:00
Roberto De Ioris 951cbf3eba implemented retries and fallback on the rawrouter 2012-11-10 10:25:40 +01:00
Roberto De Ioris 8759b66206 ported rawrouter to the new api with xclient support 2012-11-10 09:33:33 +01:00
Roberto De Ioris 93aacace5f ready for 1.4-rc2 2012-11-09 22:37:54 +01:00
Roberta Giordano 8406fb12be fixed OSX sendfile 2012-11-09 21:55:26 +01:00
Roberto De Ioris 6af3ea267e added offload sendfile to OSX 2012-11-09 21:54:05 +01:00
Roberto De Ioris 9ff37ce019 be more verbose about offload threads 2012-11-09 21:46:28 +01:00
Roberto De Ioris f4187680bd offload sendfile supported on FreeBSD and DragonFly 2012-11-09 21:36:39 +01:00
Roberto De Ioris 57b72ac17d allows multiple offload threads 2012-11-09 21:24:30 +01:00
Roberto De Ioris 5c64839734 even the router_uwsgi plugin can offload 2012-11-09 20:18:43 +01:00
Roberto De Ioris e4de9a8bc7 improved offload threads subsystem 2012-11-09 20:04:27 +01:00
Roberto De Ioris 689b4afb44 moved offload functions to a dedicated file 2012-11-09 16:48:30 +01:00
Roberto De Ioris ceebaa7d9d fixed indentation 2012-11-09 12:16:39 +01:00
Roberto De Ioris 0fa2c543ec added pcre jit support 2012-11-09 12:04:13 +01:00
Roberto De Ioris 519df88126 allows cross-domain JSON requests to stats subsystem 2012-11-08 17:38:57 +01:00
Roberto De Ioris 75b275591d count per-core static requests 2012-11-08 09:05:46 +01:00
Roberto De Ioris 2f901f08cb fixed magic vars for symlinks 2012-11-08 07:33:43 +01:00
Roberto De Ioris b041fe4473 fixed wrong error message 2012-11-08 06:50:31 +01:00
Roberto De Ioris f5d6cb65f9 added uwsgi.Handler(http.Handler) go func 2012-11-07 15:52:37 +01:00
Roberto De Ioris 9c94aedb29 added Changelog for 1.4 2012-11-07 14:20:08 +01:00
Roberto De Ioris d248b290f2 added --php--allowed-script 2012-11-07 12:24:12 +01:00
Roberto De Ioris cb48070db1 fixed systemd support 2012-11-07 11:40:56 +01:00
unbit cd34bac104 Merge pull request #45 from prymitive/static_methods
disable static files offloading for methods other than GET and HEAD
2012-11-06 11:23:01 -08:00
Łukasz Mierzwa c966fbb163 disable static files offloading for methods other than GET and HEAD 2012-11-06 14:00:04 +01:00
Roberto De Ioris feac596efc fixed SSL buffer usage 2012-11-06 06:26:41 +01:00
Roberto De Ioris 981ddfcefe do not segfault on go if master-requiring api is called 2012-11-05 19:42:39 +01:00
Roberto De Ioris 5e561b6578 simplified go interface 2012-11-05 18:18:48 +01:00
unbit fab495fadc added Stephen Pierce to CONTRIBUTORS 2012-11-05 17:24:59 +01:00
Unbit ecbda6dc26 refactored go symbol loaders 2012-11-05 11:16:42 +01:00
Roberto De Ioris e23766e4d0 added go complextest 2012-11-05 10:37:07 +01:00
Roberto De Ioris 6d9de4c618 completed caching support for go 2012-11-05 10:32:37 +01:00
Roberto De Ioris 4ca14f6046 added two tests for go web apps, and completed request body advanced management 2012-11-05 09:09:38 +01:00
Roberto De Ioris d856c9920d added comments in uwsgi.go package 2012-11-05 07:51:00 +01:00
Roberto De Ioris fd62440265 Merge branch 'master' of github.com:unbit/uwsgi 2012-11-04 19:52:59 +01:00
Roberto De Ioris d4041c9e1d fixed goroutines support 2012-11-04 19:52:46 +01:00
unbit dc9e1bd324 Merge pull request #44 from StephenPierce/new-snmp-functions
New snmp functions
2012-11-04 10:44:39 -08:00
Roberto De Ioris 89bbd967ed added --goroutines shortcut 2012-11-04 11:00:06 +01:00
Roberto De Ioris 276ada315d fallback to DefaultServeMux if no RequestHandler has been defined 2012-11-04 10:54:06 +01:00
Roberto De Ioris bdd0d408a0 go modifier1 is officially assigned as 11 2012-11-04 10:41:51 +01:00
Roberta Giordano 5ddaa2e436 fixed go build in OSX 2012-11-04 10:31:12 +01:00
Roberto De Ioris f9d0e75056 automatically build uwsgi.go 2012-11-04 10:17:23 +01:00
Roberto De Ioris 7776a1f0be added preliminary go support 2012-11-04 09:24:06 +01:00
Stephen Pierce a33a57d8af Removed unneeded import 2012-11-02 16:02:46 -07:00
Stephen Pierce 9371e2b8de Added SNMP incr/decr functions for counter32/counter64/gauge types. Wrapped all operations (set/get/incr/decr) with lock to prevent contention. 2012-11-02 16:00:31 -07:00
Roberto De Ioris 6c1a842f7d improved reloading robustness 2012-11-02 14:30:14 +01:00
Roberto De Ioris d746deaf02 Merge branch 'master' of github.com:unbit/uwsgi 2012-11-02 12:38:09 +01:00
Roberto De Ioris 09fca72b4c fixed spooler max tasks handling 2012-11-02 12:37:41 +01:00
unbit 2ffc31e578 Merge pull request #41 from prymitive/valgrind
valgrind suppression file generator
2012-11-02 04:14:56 -07:00
unbit 2a254d195a Merge pull request #42 from prymitive/head
set http status on head static request
2012-11-02 04:14:33 -07:00
Roberto De Ioris 95d3ee4e61 added mongodb stats pusher 2012-11-02 12:06:08 +01:00
Roberto De Ioris 4d56474511 implemented stats pushers 2012-11-02 11:23:12 +01:00
Łukasz Mierzwa 46a33b268a set http status on head static request 2012-11-02 11:21:52 +01:00
Łukasz Mierzwa b0829cc2e3 more suppressions 2012-11-02 10:56:56 +01:00
Łukasz Mierzwa 93a0913182 valgrind suppression file generator 2012-11-02 10:38:00 +01:00
Roberto De Ioris 0605148e21 report signal_queue size in stats, fixed linux timerfd and inotify 2012-11-02 09:44:49 +01:00
Roberto De Ioris e7b5c7c8e4 allows generating minified json 2012-11-02 08:43:55 +01:00
Roberto De Ioris b2a0fd1914 truncate malformed/huge log lines 2012-10-31 19:55:21 +01:00
Roberto De Ioris 9cc89a6052 emperor is now tolerant to extreme Linux-OOM situations 2012-10-31 11:11:39 +01:00
Roberto De Ioris 1606b8b775 remove obsolete ruby threading definitions 2012-10-31 10:54:57 +01:00
unbit cfac385f8e Merge pull request #39 from prymitive/cppcheck
missing close() call in utils/uwsgi_num_from_file()
2012-10-31 02:29:54 -07:00
Łukasz Mierzwa 99fd4572cb missing close() call in utils/uwsgi_num_from_file() 2012-10-30 23:57:48 +01:00
Roberto De Ioris d3194ca011 remove monitored fd from async queue when in async mode 2012-10-30 18:31:04 +01:00
Roberto De Ioris af61a9e33f re-indented core/async.c 2012-10-30 18:01:35 +01:00
Roberto De Ioris 4896e22a62 preventively read a page of data in stats http mode 2012-10-30 09:42:17 +01:00
Roberto De Ioris 7882d12a80 better sockets management in stats servers 2012-10-30 09:31:15 +01:00
Roberto De Ioris 9342acc500 allows exported json stats in http format 2012-10-30 08:45:32 +01:00
Roberto De Ioris 929a919c9d exports spoolers data in stats server 2012-10-30 08:19:42 +01:00
Roberto De Ioris d1f6e97dd7 do not transfer static files if method is HEAD 2012-10-30 07:22:25 +01:00
Roberto De Ioris f9d76f90eb better configfile path management 2012-10-29 19:48:43 +01:00
Unbit 2de5e8994f allows building without routing 2012-10-29 16:51:21 +01:00
unbit 7e935253a2 Merge pull request #36 from prymitive/fr
count requests in (fast|http)router
2012-10-29 04:07:50 -07:00
Łukasz Mierzwa 4c20d83573 count requests in (fast|http)router / with cs->un checks 2012-10-29 11:44:56 +01:00
Łukasz Mierzwa 7035a676a2 count requests in (fast|http)router 2012-10-29 10:58:03 +01:00
Roberto De Ioris 736f99d10b added router_cache plugin 2012-10-29 10:11:42 +01:00
Roberto De Ioris ea422a4576 fixed cache size reporting in 32bit 2012-10-29 09:29:43 +01:00
Roberto De Ioris e274f53286 a couple of fedora17-specific fixes 2012-10-28 19:58:25 +01:00
Roberto De Ioris c03dcf4617 added logfile commodity plugin 2012-10-28 19:27:42 +01:00
Roberto De Ioris d70c7ceb89 added --log-route 2012-10-28 18:15:09 +01:00
Roberto De Ioris 9ae1354d1a added the systemd journal logger 2012-10-28 08:02:18 +01:00
Roberto De Ioris b29f0b9436 reimplemented --http-to-https 2012-10-27 20:12:19 +02:00
Roberto De Ioris e01cd802d8 re-implemented http expect/continue 2012-10-27 19:39:01 +02:00
Roberto De Ioris c7b57c9776 added --log-filter 2012-10-27 15:59:48 +02:00
Roberto De Ioris 3a48b898ad refactored router_access plugin 2012-10-27 15:37:14 +02:00
unbit 4f4771b527 Merge pull request #31 from brainbitsca/master
router_access - plugin to implement hosts_access
2012-10-27 06:03:58 -07:00
Roberto De Ioris b43df60d7f added uwsgi_kvlist_parse api function 2012-10-27 14:58:19 +02:00
Roberto De Ioris 10a5661218 added C Anthony Risinger as contributor 2012-10-27 12:15:53 +02:00
Roberto De Ioris a99670cfb5 fixed an incredibly stupid bug in http/https router 2012-10-27 11:58:10 +02:00
unbit 7967e8ac3c Merge pull request #33 from prymitive/harakiri
More accurate harakiri counting
2012-10-26 01:31:12 -07:00
colinlbc e105ebe273 remove stray uwsgi_log() 2012-10-25 14:47:50 -07:00
colinlbc 11d2c004c2 moved critical scrncpy out of #ifdef UWSGI_DEBUG 2012-10-25 14:30:47 -07:00
colinlbc e8bfa12372 Reworked things to get rid of several pointer errors.
Implemented svcname paramater for hosts access mode to set daemon name in hosts.allow,hosts.deny.
New router config syntax:

svcname defaults to uwsgi

uwsgi.ini:
router access:hosts
router access:hosts=svcname
router access:allow=addr
router access:deny=addr

hosts.deny:
svcname:ALL
2012-10-25 14:10:37 -07:00
Łukasz Mierzwa 317e9efa2d harakiri count is now accurate so we don't need to divide here 2012-10-25 15:23:35 +02:00
Łukasz Mierzwa 4b99bff520 don't increment harakiri counter on multiple SIGKILLs sent to the same process 2012-10-25 15:18:00 +02:00
colinlbc 99f584cff0 use char *remote_addr instead of wsgi_req->remote_addr 2012-10-24 03:03:13 -07:00
colinlbc fc6a79dcc9 corrected hosts_ctl to use STRING_UNKNOWN instead of wsgi_req->host. This
wants the remote_hostname, not the request host header.
2012-10-24 02:54:30 -07:00
colinlbc 75af812b83 Fixed a couple of silly mistakes in the access:action,host syntax parsing
Made changes based on unbit feedback:
- separated header, body output in 403 error
- used uwsgi_concat2n to copy strings out of wsgi_req->remote_addr and wsgi_req->host
2012-10-24 02:15:41 -07:00
Colin Ligertwood 0f4e1eb7e2 A simple access control router using libwrap. Currently only tested on OpenBSD 5.1.
I've used router_authbasic as a guide to write this. Placeholders exist for an
internal ACL scheme. Syntax follows:

router = ^/path acces:hosts         -- hosts access router using libwrap, works!
router = ^/path access:allow,ipaddr -- internal allow, unimplemented
router = ^/path access:deny,ipaddr  -- internal deny, unimplemented

It's just a few hours hacking and I'm not entirely sure how the internal access
control will work, but the hosts access stuff works in openbsd. It returns a 403
on denial.
2012-10-24 01:09:44 -07:00
Roberto De Ioris a3e0c2260f fixed a leak and a refcount bug in the tracebacker 2012-10-24 08:05:35 +02:00
Roberto De Ioris 3f63caa5eb fixed a typo 2012-10-24 07:13:33 +02:00
info@unbit.it 61bd3fb0e6 fixed kqueue support 2012-10-23 23:46:54 +02:00
Roberto De Ioris d6b4b8ea6e improved wsgi.input reports 2012-10-23 20:44:01 +02:00
Roberto De Ioris 3a451fb42f updates request switches at every gevent sleep/switch 2012-10-22 17:16:21 +02:00
Roberto De Ioris 7017712c6d non blocking wsgi.input in gevent 2012-10-22 15:58:36 +02:00
Roberto De Ioris 49140c3387 removed sendfile buildconf option 2012-10-22 14:07:33 +02:00
Roberto De Ioris 1d9edc3e34 ops, missing some ugly global vars 2012-10-22 10:03:56 +02:00
Roberto De Ioris fffe070e30 use threaded build only on build_uwsgi() 2012-10-22 09:41:24 +02:00
Roberto De Ioris 29ce04adce implemented reliable gevent non-blocking writes 2012-10-22 08:34:37 +02:00
unbit c487fb0cf0 Merge pull request #27 from xtfxme/improvement/gitignore-build-products
.gitignore build products and cache files
2012-10-21 21:29:47 -07:00
C Anthony Risinger 503fcd5ed5 .gitignore build products and cache files 2012-10-21 21:33:15 -05:00
Roberto De Ioris 7136beeff7 added uwsgi.offload_transfer() 2012-10-21 18:19:14 +02:00
Roberto De Ioris 64c7d71c35 completed https request body management 2012-10-21 14:04:10 +02:00
Roberto De Ioris d2d714e933 another series of https porting to the new api and ported multithread build system to python3 2012-10-21 12:36:15 +02:00
Roberto De Ioris f7399ef2ec use linux SOCK_NONBLOCK on uwsgi_connect() 2012-10-21 11:56:04 +02:00
Roberto De Ioris 4014bc53bd fixed handling of 'remaining' post data in http router 2012-10-21 11:31:47 +02:00
Roberto De Ioris b8f42a8d0b put a lock for print in multithreaded compilation 2012-10-21 10:31:24 +02:00
Roberto De Ioris b40442a0f8 fixed race condition on fork()/early-fail during worker respawn 2012-10-21 10:21:42 +02:00
Roberto De Ioris bee3bf5d43 added --so-send-timeout 2012-10-20 21:08:48 +02:00
Roberto De Ioris 59cc3d7c04 fixed PATH_INFO usage in embedded http mode 2012-10-20 20:58:19 +02:00
Roberto De Ioris 8dc072732b fixed building on ubuntu quantal 2012-10-20 19:45:09 +02:00
Roberto De Ioris 37b7c31849 fixed fastrouter leak with the new api 2012-10-20 19:39:08 +02:00
Roberto De Ioris 738b886267 get rid of ugly oracle/sun ifdef, will find a better solution later 2012-10-20 19:35:53 +02:00
Roberto De Ioris 8679f8b845 use accept4() if available 2012-10-20 19:20:52 +02:00
Roberta Giordano ecfae75886 fixed static-offload-to-thread on no-linux platforms 2012-10-20 18:52:07 +02:00
Roberto De Ioris cefc9fcc58 fixed http compilation 2012-10-20 18:17:50 +02:00
Roberto De Ioris 03104063cb improved http memory handling 2012-10-20 18:16:03 +02:00
Roberto De Ioris ef10dc054f fixed fastrouter 2012-10-20 17:55:04 +02:00
Roberto De Ioris 242497102e Merge branch 'master' of https://github.com/unbit/uwsgi 2012-10-20 17:30:58 +02:00
Roberto De Ioris 0242b464e7 another step for https porting 2012-10-20 17:29:45 +02:00
Roberto De Ioris 353b837f67 preliminary port of the http router to the new api 2012-10-20 16:54:16 +02:00
Roberto De Ioris d70ecab49f simplified the fastrouter 2012-10-20 13:47:23 +02:00
Roberto De Ioris c65adaaac7 first (destructive) commit for 1.4 2012-10-20 13:47:07 +02:00
unbit 4f0406c1cc Merge pull request #21 from akx/master
Add "include" config entry
2012-10-19 10:28:39 -07:00
Roberto De Ioris 6ea535a74d fixed gil usage in gevent plugin 2012-10-18 16:06:53 +02:00
Roberto De Ioris 2e66ae9abe added a test for static offloads 2012-10-18 14:55:49 +02:00
Aarni Koskela 39aa8ca8be Add "include" config entry (practically "inherit" with UWSGI_OPT_IMMEDIATE). 2012-10-18 15:26:38 +03:00
Roberto De Ioris ef80a7bba9 fixed offload to thread 2012-10-18 12:32:02 +02:00
Roberto De Ioris 8a65125ae5 added matheval support 2012-10-18 10:44:29 +02:00
Roberto De Ioris 86d9b4bc0e always get gil on python atexit 2012-10-18 08:27:51 +02:00
Roberto De Ioris 1d691139c7 ignore sockets presence on uwsgi.loop 2012-10-18 08:07:46 +02:00
Roberto De Ioris 94eb4f078e improved gevent usage of threads (it allows tracebacker and autoreloader to work in gevent) 2012-10-17 21:19:48 +02:00
Roberto De Ioris 47f3b39870 another refactoring for simple loop 2012-10-17 13:51:12 +02:00
Roberto De Ioris c67d26f8cc support for unlimited loop engines 2012-10-17 13:43:29 +02:00
Roberto De Ioris 9c99b29e47 refactored loop engines 2012-10-17 13:16:23 +02:00
unbit 5ce2020d6f Merge pull request #18 from dpetzold/master
Hard fail if --listen > somaxconn
2012-10-12 05:57:56 -07:00
Derrick Petzold d965587d9d uwsgi_linux_somaxconn -> uwsgi_num_from_file
Changed return type to long.
2012-10-09 19:15:44 +00:00
unbit 4f85c215cd Update CONTRIBUTORS
added Aarni Koskela to the CONTRIBUTORS
2012-10-09 21:04:05 +03:00
Unbit 1015ef9611 added (joke) alarm_speech plugin for OSX 2012-10-09 18:43:02 +02:00
Roberto De Ioris adcbc061b1 allows usage of objective-c in plugins 2012-10-09 14:50:14 +02:00
Roberto De Ioris 42229b08ce added shared require for rack 2012-10-09 13:32:22 +02:00
Roberto De Ioris 7bac625537 gevent plugin is now included in the default build profile 2012-10-09 10:28:28 +02:00
Roberto De Ioris a3e9a288d3 better usage of uwsgi_log_initial 2012-10-09 06:51:14 +02:00
Derrick Petzold 946a46df86 If the listen option is greater than the system max hard fail. 2012-10-08 19:57:44 +00:00
Roberto De Ioris e368b2da5e more reliable reloading system in cheaper modes 2012-10-07 10:54:33 +02:00
Roberto De Ioris 6b32ac086e improved lua plugin performance and status management 2012-10-07 08:45:50 +02:00
Roberto De Ioris 1651e3b0ef Merge branch 'master' of github.com:unbit/uwsgi 2012-10-06 19:18:45 +02:00
Roberto De Ioris fee6c65365 added --smart-attach-daemon/--smart-attach-daemon2 2012-10-06 19:18:26 +02:00
unbit 6070bd70a7 Merge pull request #15 from prymitive/wlrc
weighted least reference count (wlrc) load balancing algorithm
2012-10-06 04:54:42 -07:00
Łukasz Mierzwa 86ea390ba8 weighted least reference count (wlrc) load balancing algorithm 2012-10-06 12:27:56 +02:00
unbit e9158255a1 Merge pull request #13 from prymitive/lrc
make lrc act like rr under low load
2012-10-05 00:34:50 -07:00
Roberto De Ioris cd80885a49 Merge branch 'master' of github.com:unbit/uwsgi 2012-10-04 20:04:46 +02:00
Roberto De Ioris 8925ea06e1 improved router_http 2012-10-04 20:04:23 +02:00
unbit f1135c736a Merge pull request #12 from avar/pass_SERVER_ADDR_from_nginx
nginx/uwsgi_params: pass SERVER_ADDR to uwsgi
2012-10-04 01:41:18 -07:00
Łukasz Mierzwa c9f0786edd with this patch lrc acts more like rr algorithm when request rate is very low. Side effect is that when one adds new node to long running cluster, then lrc will try to catch new node request count up to other nodes value, but since it will only happen during low request rate, than I don't consider it as an issue 2012-10-04 10:31:47 +02:00
Roberto De Ioris 7e52f14786 improved development version string generation 2012-10-04 08:44:07 +02:00
Roberto De Ioris e35dcdbcdb migrated to github 2012-10-04 08:39:38 +02:00
roberto@quantal64 c59a3cb35a added support for PEP 405 virtualenvs 2012-10-03 20:49:58 +02:00
roberto@quantal64 a9703f8533 another fix for lrc 2012-10-03 08:51:36 +02:00
roberto@quantal64 0de510b777 fixed erlang plugin, improved xmpp alarm 2012-10-03 07:52:34 +02:00
roberto@quantal64 8a0fa1ffc4 fixed lrc algo 2012-10-03 07:02:32 +02:00
roberto@quantal64 4ca422a0a8 added --subscription-dotsplit 2012-10-03 06:56:37 +02:00
roberto@quantal64 a979abf0c6 added multiple algorithms support for subscription load balancing 2012-10-02 17:08:40 +02:00
roberto@quantal64 d12ddded55 added support for (working, high-performance) static file offloading in linux 2012-10-02 08:51:35 +02:00
roberto@quantal64 3beead6459 fixed leak in python3 headers management, prepare for truly working static file serving offload 2012-10-01 19:49:04 +02:00
roberto@sirius 248741a81f fixed non-blocking write on osx 2012-10-01 18:55:25 +02:00
roberto@quantal64 188b66e92c Added tag 1.3 for changeset 620e0cb6ccdb 2012-09-30 09:24:02 +02:00
roberto@quantal64 5ae1c6fbd1 uWSGI 1.3 2012-09-30 09:23:53 +02:00
roberto@quantal64 51b9b5d070 added cppcheck option, improved multicast 2012-09-29 09:16:09 +02:00
roberto@quantal64 dafe3bb12c fixed rack.input with buffered arg 2012-09-28 16:21:37 +02:00
roberto@mercury 973e508af7 reports details on memory allocation error, and bypass broken rack middlewares 2012-09-28 12:37:11 +02:00
roberto@mercury 8e31bb612e allows building the rack plugin without async support 2012-09-28 06:16:55 +02:00
roberto@longshot f920ac0fb0 use SSL_CTX_use_certificate_chain_file instead of SSL_CTX_use_certificate_file 2012-09-27 19:39:14 +02:00
roberto@longshot ae1b5afd7d reoved last libstrophe reference 2012-09-27 18:21:14 +02:00
roberto@quantal64 1f2bae130e added alarm_xmpp plugin 2012-09-27 17:45:42 +02:00
roberto@quantal64 4417e55862 completed http support for alarm_curl 2012-09-27 08:01:06 +02:00
roberto@quantal64 74a84bdd3a added support for mail subject in alarm_curl plugin 2012-09-26 19:55:58 +02:00
roberto@quantal64 b764252e7f applied verbose bind errors 2012-09-26 18:42:48 +02:00
roberto@quantal64 2fd71be9d9 allows building without alarms 2012-09-26 07:19:01 +02:00
roberto@quantal64 d65f873e77 sadly Rack::BodyProxy is still badly broken on 1.9 2012-09-26 07:10:13 +02:00
roberto@quantal64 1427c9ce1c added alarm_curl plugin 2012-09-24 08:36:04 +02:00
roberto@quantal64 c3de9320d7 pass alarm to stdin in cmd mode 2012-09-23 17:19:56 +02:00
roberto@quantal64 674151e485 added alarm subsystem 2012-09-23 16:25:40 +02:00
roberto@quantal64 9c042ffc1c Added tag 1.3-rc4 for changeset aeea5a5d2e8b 2012-09-22 09:48:11 +02:00
roberto@quantal64 c5dc74b021 uWSGI 1.3-rc4 2012-09-22 09:45:08 +02:00
roberto@quantal64 97137488f9 improved emperor mongodb tyrant mode 2012-09-22 09:38:15 +02:00
roberto@quantal64 8cff01a1c7 report imperial monitor in emperor statistics 2012-09-22 09:21:37 +02:00
roberto@quantal64 3c8452313e added emperor_mongodb plugin 2012-09-22 09:04:47 +02:00
roberto@quantal64 322b130fc9 refactored imperial monitors api 2012-09-22 08:58:17 +02:00
roberto@quantal64 6c001c2fda fixed usage of inlining 2012-09-22 07:57:42 +02:00
roberto@quantal64 5d4050817d added --dlopen 2012-09-22 05:52:28 +02:00
roberto@quantal64 0a1147a4f6 added --rb-patch-rack-bodyproxy for older ruby/rack versions 2012-09-21 11:02:29 +02:00
roberto@quantal64 f92cb0e6a2 fixed rack compilation 2012-09-21 09:51:36 +02:00
roberto@quantal64 8b79c76261 refactored daemonize2 2012-09-20 18:08:49 +02:00
roberto@quantal64 0015b51262 fixed POST-handling reports 2012-09-20 17:49:30 +02:00
roberto@quantal64 b1dc8cd9c6 improved async cores detection 2012-09-20 17:41:13 +02:00
roberto@quantal64 3269e2d288 added support for dependancies in plugins 2012-09-20 17:16:30 +02:00
roberto@quantal64 71a9747d96 applied latest carbon patches from Łukasz Mierzwa 2012-09-20 16:43:20 +02:00
roberto@quantal64 455d041ce4 fixed http router parser 2012-09-20 16:36:08 +02:00
roberto@arch 88205f8dd1 added mongodblog plugin 2012-09-19 15:15:03 +02:00
roberto@centos6 7d9dadddf6 support for loading file for elf sections 2012-09-18 00:42:53 +02:00
roberto@centos6 57e78dd76f implemented rack.input each 2012-09-17 16:26:44 +02:00
roberto@centos6 7d0d2b33f4 improved rack.input disk buffering (second part) 2012-09-17 15:51:31 +02:00
roberto@quantal64 03c739102d reimplementing rack.input without IO wrapper 2012-09-17 13:43:43 +02:00
roberto@quantal64 392bb8d7b1 allows building with python3 and without embedded module 2012-09-17 07:41:11 +02:00
roberto@quantal64 505b35be29 do not try to remove sockets in abstract namespace 2012-09-17 06:47:07 +02:00
roberto@quantal64 fdb002ad9b added %0 - %9 magic vars for splitting paths 2012-09-17 06:33:52 +02:00
roberto@quantal64 557c46373f improved %c 2012-09-15 16:15:47 +02:00
roberto@quantal64 3cde8be505 allows building without embedded and multiple interpreters 2012-09-15 12:14:12 +02:00
roberto@quantal64 c2cf1f3a62 fixed threading + lazy 2012-09-14 15:52:23 +02:00
roberto@quantal64 956cb1f13c Added tag 1.3-rc3 for changeset 883b946db903 2012-09-13 18:47:08 +02:00
roberto@quantal64 f698b558e1 uWSGI 1.3-rc3 2012-09-13 18:46:56 +02:00
roberto@quantal64 ca832900a0 ensure master_cleanup is run by the master 2012-09-13 16:58:05 +02:00
roberto@quantal64 6a6227a8e7 added a warning for --map-socket invalid syntax 2012-09-13 14:09:55 +02:00
roberto@quantal64 8539cdb5a7 ported build system to python 3.3 2012-09-13 14:05:47 +02:00
Ævar Arnfjörð Bjarmason 15194e6b55 nginx/uwsgi_params: pass SERVER_ADDR to uwsgi
nginx is capable of passing SERVER_ADDR to us like Apache would do via
mod_Ruwsgi, it just doesn't do so because that variable wasn't listed
in nginx/uwsgi_params.

This and other variables are passed from nginx from the nginx code in
src/http/ngx_http_variables.c. This was tested with nginx 1.0.15.
2012-09-13 08:17:22 +00:00
roberto@quantal64 5cea1de1ba added master_cleanup hook and carbon flush on stop/reload 2012-09-12 19:03:22 +02:00
roberto@quantal64 e735b9e31f applied busyness_backlog.diff by Łukasz Mierzwa 2012-09-12 18:12:55 +02:00
roberto@quantal64 9ff8f8899f added --log-drain 2012-09-12 08:08:32 +02:00
roberto@quantal64 d908c4ef35 allows building without udp 2012-09-07 19:45:58 +02:00
roberto@quantal64 207f50726d oops, use classic perl syntax for push 2012-09-07 19:36:21 +02:00
roberto@quantal64 212559fcce put sleep() in each psgi cleanup hook to show its power :P 2012-09-07 19:13:34 +02:00
roberto@quantal64 cf480e499c implemented psgi cleanup handlers, and fixed a leak in rpc call 2012-09-07 19:09:22 +02:00
roberto@quantal64 f2e27f5154 improved process limit detection 2012-09-07 14:54:57 +02:00
roberto@quantal64 d932a4feae fixed typcasting 2012-09-07 14:40:06 +02:00
roberto@quantal64 da6e05072f explicit link with librt for alternatives clock 2012-09-07 06:58:26 +02:00
roberto@quantal64 13277d9d71 improved cheaper_busyness 2012-09-06 17:10:03 +02:00
roberto@quantal64 f17f8b337f fixed idle mode 2012-09-06 16:21:12 +02:00
roberto@quantal64 ffb454e414 headers must be sent before close() 2012-09-06 15:22:17 +02:00
roberto@quantal64 424f5a09e7 call close() always, even if client disconnect 2012-09-06 15:02:12 +02:00
roberto@quantal64 c29a6f6446 removed STOP/TSTP signal from gateways 2012-09-06 11:20:21 +02:00
roberto@quantal64 6f7edf0941 fixed uwsgi_buffer realloc len 2012-09-04 19:18:38 +02:00
roberto@quantal64 a4c4b7e8d2 fixed uwsgi_buffer realloc 2012-09-04 18:13:16 +02:00
roberto@quantal64 837f6f3a54 initialize spooler locks before app loading 2012-09-04 08:21:40 +02:00
roberto@quantal64 13041da6bf fixed piping 2012-09-04 08:13:02 +02:00
roberto@quantal64 046824dae7 fixed usage of mmap() 2012-09-03 14:11:42 +02:00
roberto@quantal64 269a588d9d uWSGI 1.3-rc2 2012-09-01 11:42:42 +02:00
roberto@quantal64 50ae12518a Added tag 1.3-rc2 for changeset 14524da00a8b 2012-09-01 11:42:31 +02:00
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
266 changed files with 31149 additions and 15578 deletions
+5
View File
@@ -0,0 +1,5 @@
*.o
*.py[co]
/uwsgi
/uwsgibuild.*
+11
View File
@@ -45,3 +45,14 @@ 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
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
620e0cb6ccdb0ce27561b4240cb3a0ef4c3527fd 1.3
+3
View File
@@ -18,3 +18,6 @@ Lukas Lalinsky
Steven Fernandez
Łukasz Mierzwa
Roy Marples
Aarni Koskela
C Anthony Risinger
Stephen Pierce
+110
View File
@@ -1,3 +1,113 @@
*** current ***
* 1.4.1
- fixed typos in corerouter plugins
- fixed offloading when the number of threads is higher than 1
- fixed static_maps for non-existent paths
- fixed uwsgi_connect() on modern Linux systems to reset the socket to blocking mode
*** november 2012 ***
* 1.4
- gevent improvements
- improved http/https router and fastrouter
- Go official support
- a new set of infos are exported to the stats system
- improved systemd support
- log filtering and routing
- improved tracebacker
- offload transfer for static files, and network transfers
- matheval support
- plugins can be written in Obj-C
- smart attach daemon
- added support for PEP 405 virtualenvs
- rawrouter with xclient support
- internal routing plugin for cache
*** semptember 2012 ***
* 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
- 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
- redislog and mongodblog plugins
- added python logger
- mongodb and postgres imperial monitors
- implemented psgix.logger and psgix.cleanup
- full rack spec compliance
- preliminary ipv6 support
- gevent graceful reloads
- support for multiple loggers and logformat
- lazy-apps to load apps after fork() but without changing reloading subsystem
- emperor heartbeat subsystem
- cheaper busyness plugin
- pluggable clock sources
- added router_rewrite and router_http plugins
- external spoolers
- support for section:// and fd:// loaders
- alarm subsystem (with curl and xmpp plugins)
*** 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]
+3
View File
@@ -3,3 +3,6 @@ all:
clean:
python uwsgiconfig.py --clean
check:
python uwsgiconfig.py --check
+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));
+424
View File
@@ -0,0 +1,424 @@
/*
apxs2 -i -c mod_proxy_uwsgi.c
*/
#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);
// this is not a security problem (in Linux) as uWSGI destroy the env memory area readable in /proc
// and generally if you host untrusted apps in your server and allows them to read others uid /proc/<pid>
// files you have higher problems...
const char *auth = apr_table_get(r->headers_in, "Authorization");
if (auth) {
apr_table_setn(r->subprocess_env, "HTTP_AUTHORIZATION", auth);
}
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) {
if (strcmp(path_info, "/")) {
apr_table_set(r->subprocess_env, "SCRIPT_NAME", apr_pstrndup(r->pool, script_name, strlen(script_name)-strlen(path_info)));
}
else {
if (!strcmp(script_name, "/")) {
apr_table_set(r->subprocess_env, "SCRIPT_NAME", "");
}
}
}
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[3] = 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
size_t w_len = strlen(worker->name);
char *u_path_info = r->filename + 6 + w_len;
int delta = 0;
if (u_path_info[0] != '/') {
delta = 1;
}
apr_table_add(r->subprocess_env, "PATH_INFO", url+w_len-delta);
/* 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
minterpreters = true
async = true
ldap = auto
pcre = auto
routing = auto
alarm = 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, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter
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 -47
View File
@@ -1,48 +1,3 @@
[uwsgi]
xml = auto
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
ldap = auto
pcre = auto
routing = auto
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = python, ping, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
[python]
paste = true
web3 = true
main_plugin = python,gevent
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
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
main_plugin = go
inherit = base
bin_name = libuwsgi.so
as_shared_library = true
+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
-31
View File
@@ -1,31 +0,0 @@
[uwsgi]
xml = true
ini = true
snmp = true
sctp = false
erlang = false
spooler = true
embedded = true
udp = true
multicast = true
threading = true
sendfile = true
proxy = true
minterpreters = true
async = true
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rack
[python]
paste = true
web3 = true
+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
-30
View File
@@ -1,30 +0,0 @@
[uwsgi]
xml = true
ini = true
yaml = true
snmp = true
sctp = false
erlang = false
spooler = false
embedded = false
udp = true
multicast = false
threading = true
sendfile = true
nagios = true
proxy = true
minterpreters = true
async = true
ugreen = false
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins = rack
bin_name = uwsgi
plugin_dir = .
embedded_plugins =
+5 -6
View File
@@ -2,25 +2,24 @@
xml = true
ini = true
yaml = true
json = true
json = false
sqlite3 = false
zeromq = false
snmp = false
sctp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = true
pcre = false
pcre = true
routing = true
alarm = true
debug = false
unbit = true
xml_implementation = libxml2
xml_implementation = expat
yaml_implementation = auto
malloc_implementation = libc
plugins =
-49
View File
@@ -1,49 +0,0 @@
[uwsgi]
xml = false
ini = true
yaml = false
json = false
sqlite3 = false
zeromq = false
snmp = false
sctp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = false
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins =
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
[python]
paste = true
web3 = true
-418
View File
@@ -1,418 +0,0 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_init_cache() {
int i;
if (!uwsgi.cache_blocksize)
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) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.cache_hashtable, 0, sizeof(uint64_t) * UMAX16);
uwsgi.cache_unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache_unused_stack) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.cache_unused_stack, 0, sizeof(uint64_t) * uwsgi.cache_max_items);
// the first cache item is always zero
uwsgi.shared->cache_first_available_item = 1;
uwsgi.shared->cache_unused_stack_ptr = 0;
//uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (uwsgi.cache_store) {
uwsgi.cache_filesize = (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items);
int cache_fd;
struct stat cst;
if (stat(uwsgi.cache_store, &cst)) {
uwsgi_log("creating a new cache store file: %s\n", uwsgi.cache_store);
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (cache_fd >= 0) {
// fill the caching store
if (ftruncate(cache_fd, uwsgi.cache_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
if ((size_t) cst.st_size != uwsgi.cache_filesize || !S_ISREG(cst.st_mode)) {
uwsgi_log("invalid cache store file. Please remove it or fix cache blocksize/items to match its size\n");
exit(1);
}
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
uwsgi_log("recovered cache from backing store file: %s\n", uwsgi.cache_store);
}
if (cache_fd < 0) {
uwsgi_error_open(uwsgi.cache_store);
exit(1);
}
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, uwsgi.cache_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
uwsgi_cache_fix();
}
else {
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
}
}
if (!uwsgi.cache_items) {
uwsgi_error("mmap()");
exit(1);
}
/*
uwsgi.cache = mmap(NULL, uwsgi.cache_blocksize * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache) {
uwsgi_error("mmap()");
exit(1);
}
*/
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
uwsgi_log("*** Cache subsystem initialized: %dMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n", ((uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024),
(unsigned long long) sizeof(struct uwsgi_cache_item), (unsigned long long) sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, (unsigned long long) uwsgi.cache_blocksize * uwsgi.cache_max_items);
}
uint32_t djb33x_hash(char *key, int keylen) {
register uint32_t hash = 5381;
int i;
for(i=0;i<keylen;i++) {
hash = ((hash << 5) + hash) ^ key[i];
}
return hash;
}
inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
uint64_t slot = uwsgi.cache_hashtable[hash_key];
struct uwsgi_cache_item *uci;
//uwsgi_log("found slot %d for key %d\n", slot, hash_key);
uci = &uwsgi.cache_items[slot];
// first round
if (uci->djbhash != hash) goto cycle;
if (uci->keysize != keylen) goto cycle;
if (memcmp(uci->key, key, keylen)) goto cycle;
return slot;
cycle:
while(uci->next) {
slot = uci->next;
uci = &uwsgi.cache_items[slot];
if (uci->djbhash != hash) continue;
if (uci->keysize != keylen) continue;
if (!memcmp(uci->key, key, keylen)) return slot;
}
return 0;
}
uint32_t uwsgi_cache_exists(char *key, uint16_t keylen) {
return uwsgi_cache_get_index(key, keylen);
}
char *uwsgi_cache_get(char *key, uint16_t keylen, uint64_t *valsize) {
uint64_t index = uwsgi_cache_get_index(key, keylen);
if (index) {
if (uwsgi.cache_items[index].flags & UWSGI_CACHE_FLAG_UNGETTABLE) return NULL;
*valsize = uwsgi.cache_items[index].valsize;
uwsgi.cache_items[index].hits++;
return uwsgi.cache+(index*uwsgi.cache_blocksize);
}
return NULL;
}
int uwsgi_cache_del(char *key, uint16_t keylen) {
uint64_t index = 0;
struct uwsgi_cache_item *uci;
int ret = -1;
index = uwsgi_cache_get_index(key, keylen);
if (index) {
uci = &uwsgi.cache_items[index] ;
uci->keysize = 0;
uci->valsize = 0;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = index;
// try to return to initial condition...
if (index == uwsgi.shared->cache_first_available_item-1) {
uwsgi.shared->cache_first_available_item--;
//uwsgi_log("FACI: %llu STACK PTR: %llu\n", (unsigned long long) uwsgi.shared->cache_first_available_item, (unsigned long long) uwsgi.shared->cache_unused_stack_ptr);
}
ret = 0;
// relink collisioned entry
if (uci->prev) {
uwsgi.cache_items[uci->prev].next = uci->next;
}
if (uci->next) {
uwsgi.cache_items[uci->next].prev = uci->prev;
}
if (!uci->prev && !uci->next) {
// reset hashtable entry
//uwsgi_log("!!! resetted hashtable entry !!!\n");
uwsgi.cache_hashtable[uci->djbhash % 0xffff] = 0;
}
uci->djbhash = 0;
uci->prev = 0;
uci->next = 0;
}
return ret;
}
void uwsgi_cache_fix() {
uint64_t i;
for(i=0;i< uwsgi.cache_max_items;i++) {
// valid record ?
if (uwsgi.cache_items[i].keysize) {
if (!uwsgi.cache_items[i].prev) {
// put value in hash_table
uwsgi.cache_hashtable[ uwsgi.cache_items[i].djbhash % 0xffff] = i;
}
}
else {
// put this record in unused stack
uwsgi.shared->cache_first_available_item = i;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = i;
}
}
}
int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint16_t flags) {
uint64_t index = 0, last_index = 0 ;
struct uwsgi_cache_item *uci, *ucii;
int ret = -1;
int slot;
if (!keylen || !vallen) return -1;
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
if (uwsgi.shared->cache_first_available_item >= uwsgi.cache_max_items && !uwsgi.shared->cache_unused_stack_ptr) {
uwsgi_log("*** DANGER cache is FULL !!! ***\n");
goto end;
}
//uwsgi_log("putting cache data in key %.*s %d\n", keylen, key, vallen);
index = uwsgi_cache_get_index(key, keylen);
if (!index) {
if (uwsgi.shared->cache_unused_stack_ptr) {
//uwsgi_log("!!! REUSING CACHE SLOT !!! (faci: %llu)\n", (unsigned long long) uwsgi.shared->cache_first_available_item);
index = uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr];
uwsgi.shared->cache_unused_stack_ptr--;
}
else {
index = uwsgi.shared->cache_first_available_item;
if (uwsgi.shared->cache_first_available_item < uwsgi.cache_max_items) {
uwsgi.shared->cache_first_available_item++;
}
}
uci = &uwsgi.cache_items[index] ;
if (expires) expires += time(NULL);
uci->expires = expires;
uci->djbhash = djb33x_hash(key, keylen);
uci->hits = 0;
uci->flags = flags;
memcpy(uci->key, key, keylen);
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
// set this as late as possibile (to reduce races risk)
uci->valsize = vallen;
uci->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
slot = uci->djbhash % 0xffff;
if (uwsgi.cache_hashtable[slot] == 0) {
uwsgi.cache_hashtable[slot] = index;
}
else {
//uwsgi_log("HASH COLLISION !!!!\n");
// append to first available next
last_index = uwsgi.cache_hashtable[slot];
ucii = &uwsgi.cache_items[ last_index ];
while(ucii->next) {
last_index = ucii->next;
ucii = &uwsgi.cache_items[ last_index ];
}
ucii->next = index;
uci->prev = last_index;
}
}
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = &uwsgi.cache_items[index] ;
if (expires) {
expires += time(NULL);
uci->expires = expires;
}
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
uci->valsize = vallen;
ret = 0;
}
end:
return ret;
}
/* THIS PART IS HEAVILY OPTIMIZED: PERFORMANCE NOT ELEGANCE !!! */
void *cache_thread_loop(void *fd_ptr) {
int *fd_tmp = (int *) fd_ptr;
int fd = *fd_tmp;
int i;
ssize_t len;
char uwsgi_packet[UMAX16+4];
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi_packet;
char *val;
uint64_t vallen;
char *key;
uint16_t keylen;
struct pollfd ctl_poll;
char *watermark;
struct sockaddr_un ctl_sun;
socklen_t ctl_sun_len;
ctl_poll.events = POLLIN;
for(;;) {
ctl_sun_len = sizeof(struct sockaddr_un);
pthread_mutex_lock(&uwsgi.cache_server_lock);
ctl_poll.fd = accept(fd, (struct sockaddr *) &ctl_sun, &ctl_sun_len);
pthread_mutex_unlock(&uwsgi.cache_server_lock);
if (ctl_poll.fd < 0) {
uwsgi_error("cache accept()");
continue;
}
i = 0;
while(i < 4) {
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (len <= 0) {
uwsgi_error("cache poll()");
goto clear;
}
len = read(ctl_poll.fd, uwsgi_packet+i, 4-i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i+=len;
}
if (uh->pktsize == 0) goto clear;
while(i < 4+uh->pktsize) {
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (len <= 0) {
uwsgi_error("cache poll()");
goto clear;
}
len = read(ctl_poll.fd, uwsgi_packet+i, (4+uh->pktsize)-i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i+=len;
}
watermark = uwsgi_packet+4+uh->pktsize;
// get first parameter
memcpy(&keylen, uwsgi_packet+4, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
#endif
if (uwsgi_packet+6+keylen > watermark) goto clear;
key = uwsgi_packet+6+keylen+2;
memcpy(&keylen, key-2, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
#endif
if (key+keylen > watermark) goto clear;
val = uwsgi_cache_get(key, keylen, &vallen);
if (val && vallen > 0) {
if (write(ctl_poll.fd, val, vallen) < 0) {
uwsgi_error("cache write()");
}
}
clear:
close(ctl_poll.fd);
}
return NULL;
}
int uwsgi_cache_server(char *socket, int threads) {
int *fd = uwsgi_malloc(sizeof(int));
int i;
pthread_t thread_id;
char *tcp_port = strchr(socket, ':');
if (tcp_port) {
*fd = bind_to_tcp(socket, uwsgi.listen_queue, tcp_port);
}
else {
*fd = bind_to_unix(socket, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
pthread_mutex_init(&uwsgi.cache_server_lock, NULL);
if (threads < 1) threads = 1;
uwsgi_log("*** cache-optimized server enabled on fd %d (%d threads) ***\n", *fd, threads);
for(i=0;i<threads;i++) {
pthread_create(&thread_id, NULL, cache_thread_loop, (void *) fd);
}
return *fd;
}
-363
View File
@@ -1,363 +0,0 @@
#include "uwsgi.h"
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;
// get cluster configuration
if (uwsgi.cluster != NULL) {
// get multicast socket
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
// ask for cluster options only if bot pre-existent options are set
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
// now wait max 60 seconds and resend multicast request every 10 seconds
for (;;) {
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
continue;
}
waitfd:
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
if (rlen < 0) {
break;
}
else if (rlen > 0) {
// receive the packet
char clusterbuf[4096];
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
uwsgi_configure(-1);
goto options_parsed;
}
else {
goto waitfd;
}
}
}
}
options_parsed:
if (!uwsgi.cluster_nodes)
uwsgi_cluster_add_me();
}
}
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
int i;
struct uwsgi_cluster_node *ucn;
char *tcp_port;
#ifdef UWSGI_DEBUG
uwsgi_log("adding node\n");
#endif
tcp_port = strchr(nucn->name, ':');
#ifndef UWSGI_ZEROMQ
if (tcp_port == NULL) {
#else
char *zmq_dash = strchr(nucn->name, '-');
if (tcp_port == NULL && zmq_dash == NULL) {
#endif
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
return;
}
// first check for already present node
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0) {
if (!strcmp(ucn->name, nucn->name)) {
ucn->status = UWSGI_NODE_OK;
ucn->last_seen = time(NULL);
// update requests
ucn->requests = nucn->requests;
return;
}
}
}
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] == 0) {
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
ucn->workers = nucn->workers;
ucn->ucn_addr.sin_family = AF_INET;
if (tcp_port) {
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
tcp_port[0] = 0;
}
if (nucn->name[0] == 0) {
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", nucn->name);
#endif
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
}
ucn->type = type;
// here memory can be freed, as it is allocated by uwsgi_concat2n
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
tcp_port[0] = ':';
}
ucn->last_seen = time(NULL);
ucn->requests = nucn->requests;
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
return;
}
}
uwsgi_log("unable to add node %s\n", nucn->name);
}
int uwsgi_cluster_add_me() {
const char *key1 = "hostname";
const char *key2 = "address";
const char *key3 = "workers";
const char *key4 = "requests";
char *ptrbuf;
uint16_t ustrlen;
char numproc[6];
#ifdef UWSGI_ZEROMQ
char uuid_zmq_str[37];
uuid_t uuid_zmq;
if (!uwsgi.sockets && !uwsgi.zeromq) {
#else
if (!uwsgi.sockets) {
#endif
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
exit(1);
}
snprintf(numproc, 6, "%d", uwsgi.numproc);
size_t len;
if (uwsgi.sockets) {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
uuid_generate(uuid_zmq);
uuid_unparse(uuid_zmq, uuid_zmq_str);
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#endif
else {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
char *buf = uwsgi_malloc(len);
ptrbuf = buf;
ustrlen = strlen(key1);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key1, strlen(key1));
ptrbuf += strlen(key1);
ustrlen = strlen(uwsgi.hostname);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
ptrbuf += strlen(uwsgi.hostname);
if (uwsgi.sockets && uwsgi.sockets->name) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uwsgi.sockets->name);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
ptrbuf += strlen(uwsgi.sockets->name);
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uuid_zmq_str);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
ptrbuf += strlen(uuid_zmq_str);
}
#endif
ustrlen = strlen(key3);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key3, strlen(key3));
ptrbuf += strlen(key3);
ustrlen = strlen(numproc);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, numproc, strlen(numproc));
ptrbuf += strlen(numproc);
ustrlen = strlen(key4);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key4, strlen(key4));
ptrbuf += strlen(key4);
ustrlen = 1;
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, "0", 1);
ptrbuf += 1;
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
free(buf);
#ifdef UWSGI_DEBUG
uwsgi_log("add_me() successfull\n");
#endif
return 0;
}
int uwsgi_cluster_join(char *name) {
int fd;
char *cp;
int broadcast = 0;
if (name[0] == ':') {
fd = bind_to_udp(name, 0, 1);
broadcast = 1;
}
else {
fd = bind_to_udp(name, 1, 0);
}
if (fd >= 0) {
cp = strchr(name, ':');
cp[0] = 0;
uwsgi.mc_cluster_addr.sin_family = AF_INET;
if (broadcast) {
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
}
else {
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
}
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
cp[0] = ':';
// announce my presence to all the nodes
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
}
else {
exit(1);
}
return fd;
}
char *uwsgi_cluster_best_node() {
int i;
int best_node = -1;
struct uwsgi_cluster_node *ucn;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
if (best_node == -1) {
best_node = i;
}
else {
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
best_node = i;
}
}
}
}
if (best_node == -1) {
return NULL;
}
uwsgi.shared->nodes[best_node].last_choosen = time(NULL);
return uwsgi.shared->nodes[best_node].name;
}
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
}
if (!uwsgi_strncmp("address", 7, key, keylen)) {
strncpy(ucn->name, val, UMIN(vallen, 100));
}
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->workers = atoi(tmpstr);
free(tmpstr);
}
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->requests = strtoul(tmpstr, NULL, 0);
free(tmpstr);
}
}
#endif
+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';
+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
+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";
+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
+269
View File
@@ -0,0 +1,269 @@
#include "../uwsgi.h"
extern struct uwsgi_server uwsgi;
// generate a uwsgi signal on alarm
void uwsgi_alarm_init_signal(struct uwsgi_alarm_instance *uai) {
uai->data8 = atoi(uai->arg);
}
void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
uwsgi_route_signal(uai->data8);
}
// run a command on alarm
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
uai->data_ptr = uai->arg;
}
void uwsgi_alarm_func_cmd(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
int pipe[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe)) {
return;
}
uwsgi_socket_nb(pipe[0]);
uwsgi_socket_nb(pipe[1]);
if (write(pipe[1], msg, len) != (ssize_t) len) {
close(pipe[0]);
close(pipe[1]);
return;
}
uwsgi_run_command(uai->data_ptr, pipe, -1);
close(pipe[0]);
close(pipe[1]);
}
// pass the log line to a mule
void uwsgi_alarm_init_mule(struct uwsgi_alarm_instance *uai) {
uai->data32 = atoi(uai->arg);
if (uai->data32 > (uint32_t) uwsgi.mules_cnt) {
uwsgi_log_alarm("] invalid mule_id (%d mules available), fallback to 0\n", uwsgi.mules_cnt);
uai->data32 = 0;
}
}
void uwsgi_alarm_func_mule(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
// skip if mules are not available
if (uwsgi.mules_cnt == 0)
return;
int fd = uwsgi.shared->mule_queue_pipe[0];
if (uai->data32 > 0) {
int mule_id = uai->data32 - 1;
fd = uwsgi.mules[mule_id].queue_pipe[0];
}
mule_send_msg(fd, msg, len);
}
// register a new alarm
void uwsgi_register_alarm(char *name, void (*init) (struct uwsgi_alarm_instance *), void (*func) (struct uwsgi_alarm_instance *, char *, size_t)) {
struct uwsgi_alarm *old_ua = NULL, *ua = uwsgi.alarms;
while (ua) {
// skip already initialized alarms
if (!strcmp(ua->name, name)) {
return;
}
old_ua = ua;
ua = ua->next;
}
ua = uwsgi_calloc(sizeof(struct uwsgi_alarm));
ua->name = name;
ua->init = init;
ua->func = func;
if (old_ua) {
old_ua->next = ua;
}
else {
uwsgi.alarms = ua;
}
}
// register embedded alarms
void uwsgi_register_embedded_alarms() {
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
}
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
struct uwsgi_alarm *ua = uwsgi.alarms;
while (ua) {
if (!strcmp(ua->name, plugin)) {
break;
}
ua = ua->next;
}
if (!ua)
return -1;
struct uwsgi_alarm_instance *old_uai = NULL, *uai = uwsgi.alarm_instances;
while (uai) {
old_uai = uai;
uai = uai->next;
}
uai = uwsgi_calloc(sizeof(struct uwsgi_alarm_instance));
uai->name = name;
uai->alarm = ua;
uai->arg = arg;
uai->last_msg = uwsgi_malloc(uwsgi.log_master_bufsize);
if (old_uai) {
old_uai->next = uai;
}
else {
uwsgi.alarm_instances = uai;
}
ua->init(uai);
return 0;
}
// get an alarm instance by its name
static struct uwsgi_alarm_instance *uwsgi_alarm_get_instance(char *name) {
struct uwsgi_alarm_instance *uai = uwsgi.alarm_instances;
while (uai) {
if (!strcmp(name, uai->name)) {
return uai;
}
uai = uai->next;
}
return NULL;
}
static int uwsgi_alarm_log_add(char *alarms, char *regexp) {
struct uwsgi_alarm_log *old_ual = NULL, *ual = uwsgi.alarm_logs;
while (ual) {
old_ual = ual;
ual = ual->next;
}
ual = uwsgi_calloc(sizeof(struct uwsgi_alarm_log));
if (uwsgi_regexp_build(regexp, &ual->pattern, &ual->pattern_extra)) {
return -1;
}
if (old_ual) {
old_ual->next = ual;
}
else {
uwsgi.alarm_logs = ual;
}
// map instances to the log
char *list = uwsgi_str(alarms);
char *p = strtok(list, ",");
while (p) {
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
if (!uai)
return -1;
struct uwsgi_alarm_ll *old_uall = NULL, *uall = ual->alarms;
while (uall) {
old_uall = uall;
uall = uall->next;
}
uall = uwsgi_calloc(sizeof(struct uwsgi_alarm_ll));
uall->alarm = uai;
if (old_uall) {
old_uall->next = uall;
}
else {
ual->alarms = uall;
}
p = strtok(NULL, ",");
}
return 0;
}
// initialize alarms, instances and log regexps
void uwsgi_alarms_init() {
// first of all, create instance of alarms
struct uwsgi_string_list *usl = uwsgi.alarm_list;
while (usl) {
char *line = uwsgi_str(usl->value);
char *space = strchr(line, ' ');
if (!space) {
uwsgi_log("invalid alarm syntax: %s\n", usl->value);
exit(1);
}
*space = 0;
char *plugin = space + 1;
char *colon = strchr(plugin, ':');
if (!colon) {
uwsgi_log("invalid alarm syntax: %s\n", usl->value);
exit(1);
}
*colon = 0;
char *arg = colon + 1;
// here the alarm is mapped to a name and initialized
if (uwsgi_alarm_add(line, plugin, arg)) {
uwsgi_log("invalid alarm: %s\n", usl->value);
exit(1);
}
usl = usl->next;
}
// then map log-alarm
usl = uwsgi.alarm_logs_list;
while (usl) {
char *line = uwsgi_str(usl->value);
char *space = strchr(line, ' ');
if (!space) {
uwsgi_log("invalid log-alarm syntax: %s\n", usl->value);
exit(1);
}
*space = 0;
char *regexp = space + 1;
// here the log-alarm is created
if (uwsgi_alarm_log_add(line, regexp)) {
uwsgi_log("invalid log-alarm: %s\n", usl->value);
exit(1);
}
usl = usl->next;
}
}
// check if a log should raise an alarm
void uwsgi_alarm_log_check(char *msg, size_t len) {
if (!uwsgi_strncmp(msg, len, "[uwsgi-alarm", 12))
return;
struct uwsgi_alarm_log *ual = uwsgi.alarm_logs;
while (ual) {
if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) {
uwsgi_alarm_log_run(ual, msg, len);
}
ual = ual->next;
}
}
// call the alarm func
void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
time_t now = uwsgi_now();
// avoid alarm storming/loop if last message is the same
if (!uwsgi_strncmp(msg, len, uai->last_msg, uai->last_msg_size)) {
if (now - uai->last_run < uwsgi.alarm_freq)
return;
}
uai->alarm->func(uai, msg, len);
uai->last_run = uwsgi_now();
memcpy(uai->last_msg, msg, len);
uai->last_msg_size = len;
}
// call the alarms mapped to a log line
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
struct uwsgi_alarm_ll *uall = ual->alarms;
while (uall) {
uwsgi_alarm_run(uall->alarm, msg, len);
uall = uall->next;
}
}
+150 -124
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];
}
@@ -14,23 +37,23 @@ void runqueue_remove(struct uwsgi_async_request *u_request) {
struct uwsgi_async_request *parent = u_request->prev;
struct uwsgi_async_request *child = u_request->next;
if (parent) {
parent->next = child;
}
if (child) {
child->prev = parent;
}
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
if (parent) {
parent->next = child;
}
if (child) {
child->prev = parent;
}
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
if (u_request == uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last = parent;
}
free(u_request);
free(u_request);
uwsgi.async_runqueue_cnt--;
}
@@ -40,21 +63,21 @@ void runqueue_push(struct wsgi_request *wsgi_req) {
struct uwsgi_async_request *uar;
if (uwsgi.async_runqueue == NULL) {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
uwsgi.async_runqueue_cnt++;
@@ -76,27 +99,28 @@ struct wsgi_request *find_first_available_wsgi_req() {
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
time_t current_time = time(NULL);
uint64_t current_time = (uint64_t) uwsgi_now();
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for(;;) {
for (;;) {
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
if (urbt == NULL) return;
if (urbt == NULL)
return;
if (urbt->key <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
if (urbt->value <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
uaf = wsgi_req->waiting_fds;
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
while(uaf) {
while (uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
current_uaf = uaf;
@@ -106,11 +130,11 @@ void async_expire_timeouts() {
wsgi_req->waiting_fds = NULL;
// put th request in the runqueue
runqueue_push(wsgi_req);
continue;
}
continue;
}
break;
}
break;
}
}
@@ -118,10 +142,11 @@ void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0) return ;
if (fd < 0)
return;
// find first slot
while(uad) {
while (uad) {
last_uad = uad;
uad = uad->next;
}
@@ -144,48 +169,49 @@ void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_read(uwsgi.async_queue, fd);
}
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);
}
}
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0) return ;
if (fd < 0)
return;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
// find first slot
while (uad) {
last_uad = uad;
uad = uad->next;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_write();
uad->prev = last_uad;
uad->next = NULL;
uad->prev = last_uad;
uad->next = NULL;
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_write(uwsgi.async_queue, fd);
event_queue_add_fd_write(uwsgi.async_queue, fd);
}
@@ -193,7 +219,12 @@ void async_schedule_to_req(void) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
}
void *async_loop(void *arg1) {
void async_loop() {
if (uwsgi.async < 2) {
uwsgi_log("the async loop engine requires async mode (--async <n>)\n");
exit(1);
}
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
@@ -214,10 +245,12 @@ 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
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
if (!uwsgi.schedule_to_req)
uwsgi.schedule_to_req = async_schedule_to_req;
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
@@ -225,78 +258,77 @@ void *async_loop(void *arg1) {
timeout = 0;
}
else {
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
timeout = 0;
}
if (min_timeout) {
timeout = min_timeout->key - time(NULL);
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
}
if (min_timeout) {
timeout = min_timeout->value - uwsgi_now();
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
}
}
else {
timeout = -1;
}
}
}
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
// timeout ???
if (uwsgi.async_nevents == 0) {
async_expire_timeouts();
async_expire_timeouts();
}
for(i=0;i<uwsgi.async_nevents;i++) {
for (i = 0; i < uwsgi.async_nevents; i++) {
// 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 ?
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
while (uwsgi_sock) {
if (interesting_fd == uwsgi_sock->fd) {
is_a_new_connection = 1;
is_a_new_connection = 1;
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 );
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock);
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi_sock->arg) < 0) {
uwsgi_error("fcntl()");
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
/* 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
@@ -322,22 +354,21 @@ void *async_loop(void *arg1) {
if (uwsgi.wsgi_req) {
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
// reset timeout
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
// parsing complete
if (!proto_parser_status) {
// remove fd from event poll and fd proto table
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
#endif
// remove fd from event poll and fd proto table
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
// put request in the runqueue
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;
@@ -356,27 +387,26 @@ void *async_loop(void *arg1) {
}
// remove all the fd monitors and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
while (uwsgi.wsgi_req->waiting_fds) {
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
if (uwsgi.wsgi_req->async_timeout) {
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
uwsgi.wsgi_req->async_ready_fd = 1;
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
break;
}
}
@@ -395,20 +425,18 @@ void *async_loop(void *arg1) {
// request ended ?
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
// remove all the monitored fds and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
while (uwsgi.wsgi_req->waiting_fds) {
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
// remove from the list
@@ -422,7 +450,7 @@ void *async_loop(void *arg1) {
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from suspended list
// remove this request from suspended list
runqueue_remove(current_request);
}
@@ -433,6 +461,4 @@ void *async_loop(void *arg1) {
}
return NULL;
}
+126
View File
@@ -0,0 +1,126 @@
#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_fix(struct uwsgi_buffer *ub, size_t len) {
if (ub->limit > 0 && len > ub->limit)
return -1;
if (ub->len < len) {
char *new_buf = realloc(ub->buf, len);
if (!new_buf) {
uwsgi_error("uwsgi_buffer_fix()");
return -1;
}
ub->buf = new_buf;
ub->len = len;
}
return 0;
}
int uwsgi_buffer_ensure(struct uwsgi_buffer *ub, size_t len) {
size_t remains = ub->len - ub->pos;
if (remains < len) {
size_t new_len = ub->len + (len - remains);
if (ub->limit > 0 && new_len > ub->limit) {
new_len = ub->limit;
if (new_len == ub->len)
return -1;
}
char *new_buf = realloc(ub->buf, new_len);
if (!new_buf) {
uwsgi_error("uwsgi_buffer_ensure()");
return -1;
}
ub->buf = new_buf;
ub->len = new_len;
}
return 0;
}
int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
size_t remains = ub->len - ub->pos;
if (len > remains) {
size_t chunk_size = UMAX(len, (size_t) uwsgi.page_size);
if (ub->limit > 0 && ub->len + chunk_size > ub->limit) {
// retry with another minimal size
if (len < (size_t) uwsgi.page_size) {
chunk_size = len;
}
if (ub->len + chunk_size > ub->limit)
return -1;
}
char *new_buf = realloc(ub->buf, ub->len + chunk_size);
if (!new_buf) {
uwsgi_error("uwsgi_buffer_append()");
return -1;
}
ub->buf = new_buf;
ub->len += chunk_size;
}
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("uwsgi_buffer_send()");
return -1;
}
}
else if (ret == 0) {
uwsgi_log("timeout while sending buffer !!!\n");
return -1;
}
else {
return -1;
}
}
return 0;
}
int uwsgi_buffer_num64(struct uwsgi_buffer *ub, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%lld", (long long) num);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
return uwsgi_buffer_append(ub, buf, ret);
}
+473
View File
@@ -0,0 +1,473 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_init_cache() {
if (!uwsgi.cache_blocksize)
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) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.cache_hashtable, 0, sizeof(uint64_t) * UMAX16);
uwsgi.cache_unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache_unused_stack) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.cache_unused_stack, 0, sizeof(uint64_t) * uwsgi.cache_max_items);
// the first cache item is always zero
uwsgi.shared->cache_first_available_item = 1;
uwsgi.shared->cache_unused_stack_ptr = 0;
//uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (uwsgi.cache_store) {
uwsgi.cache_filesize = (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items);
int cache_fd;
struct stat cst;
if (stat(uwsgi.cache_store, &cst)) {
uwsgi_log("creating a new cache store file: %s\n", uwsgi.cache_store);
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (cache_fd >= 0) {
// fill the caching store
if (ftruncate(cache_fd, uwsgi.cache_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
if ((size_t) cst.st_size != uwsgi.cache_filesize || !S_ISREG(cst.st_mode)) {
uwsgi_log("invalid cache store file. Please remove it or fix cache blocksize/items to match its size\n");
exit(1);
}
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
uwsgi_log("recovered cache from backing store file: %s\n", uwsgi.cache_store);
}
if (cache_fd < 0) {
uwsgi_error_open(uwsgi.cache_store);
exit(1);
}
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, uwsgi.cache_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
uwsgi_cache_fix();
}
else {
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
int i;
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
}
}
if (!uwsgi.cache_items) {
uwsgi_error("mmap()");
exit(1);
}
/*
uwsgi.cache = mmap(NULL, uwsgi.cache_blocksize * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache) {
uwsgi_error("mmap()");
exit(1);
}
*/
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
uwsgi_log("*** Cache subsystem initialized: %lluMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n", (unsigned long long) ((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) {
register uint32_t hash = 5381;
int i;
for (i = 0; i < keylen; i++) {
hash = ((hash << 5) + hash) ^ key[i];
}
return hash;
}
static inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
uint32_t hash_key = hash % 0xffff;
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 (hash_key != uci->djbhash % 0xffff) return 0;
if (uci->djbhash != hash)
goto cycle;
if (uci->keysize != keylen)
goto cycle;
if (memcmp(uci->key, key, keylen))
goto cycle;
return slot;
cycle:
while (uci->next) {
slot = uci->next;
uci = &uwsgi.cache_items[slot];
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)
continue;
if (uci->keysize != keylen)
continue;
if (!memcmp(uci->key, key, keylen))
return slot;
}
return 0;
}
uint32_t uwsgi_cache_exists(char *key, uint16_t keylen) {
return uwsgi_cache_get_index(key, keylen);
}
char *uwsgi_cache_get(char *key, uint16_t keylen, uint64_t * valsize) {
uint64_t index = uwsgi_cache_get_index(key, keylen);
if (index) {
if (uwsgi.cache_items[index].flags & UWSGI_CACHE_FLAG_UNGETTABLE)
return NULL;
*valsize = uwsgi.cache_items[index].valsize;
uwsgi.cache_items[index].hits++;
return uwsgi.cache + (index * uwsgi.cache_blocksize);
}
return NULL;
}
int uwsgi_cache_del(char *key, uint16_t keylen, uint64_t index) {
struct uwsgi_cache_item *uci;
int ret = -1;
if (!index)
index = uwsgi_cache_get_index(key, keylen);
if (index) {
uci = &uwsgi.cache_items[index];
uci->keysize = 0;
uci->valsize = 0;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = index;
// try to return to initial condition...
if (index == uwsgi.shared->cache_first_available_item - 1) {
uwsgi.shared->cache_first_available_item--;
//uwsgi_log("FACI: %llu STACK PTR: %llu\n", (unsigned long long) uwsgi.shared->cache_first_available_item, (unsigned long long) uwsgi.shared->cache_unused_stack_ptr);
}
ret = 0;
// relink collisioned entry
if (uci->prev) {
uwsgi.cache_items[uci->prev].next = uci->next;
}
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");
uwsgi.cache_hashtable[uci->djbhash % 0xffff] = 0;
}
uci->djbhash = 0;
uci->prev = 0;
uci->next = 0;
uci->expires = 0;
}
return ret;
}
void uwsgi_cache_fix() {
uint64_t i;
for (i = 0; i < uwsgi.cache_max_items; i++) {
// valid record ?
if (uwsgi.cache_items[i].keysize) {
if (!uwsgi.cache_items[i].prev) {
// put value in hash_table
uwsgi.cache_hashtable[uwsgi.cache_items[i].djbhash % 0xffff] = i;
}
}
else {
// put this record in unused stack
uwsgi.shared->cache_first_available_item = i;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = i;
}
}
}
int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint16_t flags) {
uint64_t index = 0, last_index = 0;
struct uwsgi_cache_item *uci, *ucii;
int ret = -1;
if (!keylen || !vallen)
return -1;
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE)
return -1;
if (uwsgi.shared->cache_first_available_item >= uwsgi.cache_max_items && !uwsgi.shared->cache_unused_stack_ptr) {
uwsgi_log("*** DANGER cache is FULL !!! ***\n");
goto end;
}
//uwsgi_log("putting cache data in key %.*s %d\n", keylen, key, vallen);
index = uwsgi_cache_get_index(key, keylen);
if (!index) {
if (uwsgi.shared->cache_unused_stack_ptr) {
//uwsgi_log("!!! REUSING CACHE SLOT !!! (faci: %llu)\n", (unsigned long long) uwsgi.shared->cache_first_available_item);
index = uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr];
uwsgi.shared->cache_unused_stack_ptr--;
}
else {
index = uwsgi.shared->cache_first_available_item;
if (uwsgi.shared->cache_first_available_item < uwsgi.cache_max_items) {
uwsgi.shared->cache_first_available_item++;
}
}
uci = &uwsgi.cache_items[index];
if (expires)
expires += uwsgi_now();
uci->expires = expires;
uci->djbhash = djb33x_hash(key, keylen);
uci->hits = 0;
uci->flags = flags;
memcpy(uci->key, key, keylen);
memcpy(uwsgi.cache + (index * uwsgi.cache_blocksize), val, vallen);
// set this as late as possibile (to reduce races risk)
uci->valsize = vallen;
uci->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
int slot = uci->djbhash % 0xffff;
// reset values
uci->prev = 0;
uci->next = 0;
if (uwsgi.cache_hashtable[slot] == 0) {
uwsgi.cache_hashtable[slot] = index;
}
else {
//uwsgi_log("HASH COLLISION !!!!\n");
// append to first available next
last_index = uwsgi.cache_hashtable[slot];
ucii = &uwsgi.cache_items[last_index];
while (ucii->next) {
last_index = ucii->next;
ucii = &uwsgi.cache_items[last_index];
}
ucii->next = index;
uci->prev = last_index;
}
}
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = &uwsgi.cache_items[index];
if (expires) {
expires += uwsgi_now();
uci->expires = expires;
}
memcpy(uwsgi.cache + (index * uwsgi.cache_blocksize), val, vallen);
uci->valsize = vallen;
ret = 0;
}
end:
return ret;
}
/* THIS PART IS HEAVILY OPTIMIZED: PERFORMANCE NOT ELEGANCE !!! */
void *cache_thread_loop(void *fd_ptr) {
int *fd_tmp = (int *) fd_ptr;
int fd = *fd_tmp;
int i;
ssize_t len;
char uwsgi_packet[UMAX16 + 4];
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi_packet;
char *val;
uint64_t vallen;
char *key;
uint16_t keylen;
struct pollfd ctl_poll;
char *watermark;
struct sockaddr_un ctl_sun;
socklen_t ctl_sun_len;
ctl_poll.events = POLLIN;
for (;;) {
ctl_sun_len = sizeof(struct sockaddr_un);
pthread_mutex_lock(&uwsgi.cache_server_lock);
ctl_poll.fd = accept(fd, (struct sockaddr *) &ctl_sun, &ctl_sun_len);
pthread_mutex_unlock(&uwsgi.cache_server_lock);
if (ctl_poll.fd < 0) {
uwsgi_error("cache accept()");
continue;
}
i = 0;
while (i < 4) {
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (len <= 0) {
uwsgi_error("cache poll()");
goto clear;
}
len = read(ctl_poll.fd, uwsgi_packet + i, 4 - i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i += len;
}
if (uh->pktsize == 0)
goto clear;
while (i < 4 + uh->pktsize) {
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (len <= 0) {
uwsgi_error("cache poll()");
goto clear;
}
len = read(ctl_poll.fd, uwsgi_packet + i, (4 + uh->pktsize) - i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i += len;
}
watermark = uwsgi_packet + 4 + uh->pktsize;
// get first parameter
memcpy(&keylen, uwsgi_packet + 4, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
#endif
if (uwsgi_packet + 6 + keylen > watermark)
goto clear;
key = uwsgi_packet + 6 + keylen + 2;
memcpy(&keylen, key - 2, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
#endif
if (key + keylen > watermark)
goto clear;
val = uwsgi_cache_get(key, keylen, &vallen);
if (val && vallen > 0) {
if (write(ctl_poll.fd, val, vallen) < 0) {
uwsgi_error("cache write()");
}
}
clear:
close(ctl_poll.fd);
}
return NULL;
}
int uwsgi_cache_server(char *socket, int threads) {
int *fd = uwsgi_malloc(sizeof(int));
int i;
pthread_t thread_id;
char *tcp_port = strchr(socket, ':');
if (tcp_port) {
*fd = bind_to_tcp(socket, uwsgi.listen_queue, tcp_port);
}
else {
*fd = bind_to_unix(socket, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
pthread_mutex_init(&uwsgi.cache_server_lock, NULL);
if (threads < 1)
threads = 1;
uwsgi_log("*** cache-optimized server enabled on fd %d (%d threads) ***\n", *fd, threads);
for (i = 0; i < threads; i++) {
pthread_create(&thread_id, NULL, cache_thread_loop, (void *) fd);
}
return *fd;
}
int uwsgi_cache_enabled() {
if (uwsgi.cache_max_items > 0)
return 1;
return 0;
}
void uwsgi_cache_wlock() {
uwsgi.lock_ops.wlock(uwsgi.cache_lock);
}
void uwsgi_cache_rlock() {
uwsgi.lock_ops.rlock(uwsgi.cache_lock);
}
void uwsgi_cache_rwunlock() {
uwsgi.lock_ops.rwunlock(uwsgi.cache_lock);
}
+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);
}
+464
View File
@@ -0,0 +1,464 @@
#include "uwsgi.h"
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;
// get cluster configuration
if (uwsgi.cluster != NULL) {
// get multicast socket
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
// ask for cluster options only if bot pre-existent options are set
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
// now wait max 60 seconds and resend multicast request every 10 seconds
for (;;) {
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
continue;
}
waitfd:
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
if (rlen < 0) {
break;
}
else if (rlen > 0) {
// receive the packet
char clusterbuf[4096];
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
uwsgi_configure();
goto options_parsed;
}
else {
goto waitfd;
}
}
}
}
options_parsed:
if (!uwsgi.cluster_nodes)
uwsgi_cluster_add_me();
}
}
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
int i;
struct uwsgi_cluster_node *ucn;
char *tcp_port;
#ifdef UWSGI_DEBUG
uwsgi_log("adding node\n");
#endif
tcp_port = strchr(nucn->name, ':');
#ifndef UWSGI_ZEROMQ
if (tcp_port == NULL) {
#else
char *zmq_dash = strchr(nucn->name, '-');
if (tcp_port == NULL && zmq_dash == NULL) {
#endif
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
return;
}
// first check for already present node
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0) {
if (!strcmp(ucn->name, nucn->name)) {
ucn->status = UWSGI_NODE_OK;
ucn->last_seen = uwsgi_now();
// update requests
ucn->requests = nucn->requests;
return;
}
}
}
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] == 0) {
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
ucn->workers = nucn->workers;
ucn->ucn_addr.sin_family = AF_INET;
if (tcp_port) {
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
tcp_port[0] = 0;
}
if (nucn->name[0] == 0) {
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", nucn->name);
#endif
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
}
ucn->type = type;
// here memory can be freed, as it is allocated by uwsgi_concat2n
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
tcp_port[0] = ':';
}
ucn->last_seen = uwsgi_now();
ucn->requests = nucn->requests;
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
return;
}
}
uwsgi_log("unable to add node %s\n", nucn->name);
}
int uwsgi_cluster_add_me() {
const char *key1 = "hostname";
const char *key2 = "address";
const char *key3 = "workers";
const char *key4 = "requests";
char *ptrbuf;
uint16_t ustrlen;
char numproc[6];
#ifdef UWSGI_ZEROMQ
char uuid_zmq_str[37];
uuid_t uuid_zmq;
if (!uwsgi.sockets && !uwsgi.zeromq) {
#else
if (!uwsgi.sockets) {
#endif
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
exit(1);
}
snprintf(numproc, 6, "%d", uwsgi.numproc);
size_t len;
if (uwsgi.sockets) {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
uuid_generate(uuid_zmq);
uuid_unparse(uuid_zmq, uuid_zmq_str);
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#endif
else {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
char *buf = uwsgi_malloc(len);
ptrbuf = buf;
ustrlen = strlen(key1);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key1, strlen(key1));
ptrbuf += strlen(key1);
ustrlen = strlen(uwsgi.hostname);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
ptrbuf += strlen(uwsgi.hostname);
if (uwsgi.sockets && uwsgi.sockets->name) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uwsgi.sockets->name);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
ptrbuf += strlen(uwsgi.sockets->name);
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uuid_zmq_str);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
ptrbuf += strlen(uuid_zmq_str);
}
#endif
ustrlen = strlen(key3);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key3, strlen(key3));
ptrbuf += strlen(key3);
ustrlen = strlen(numproc);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, numproc, strlen(numproc));
ptrbuf += strlen(numproc);
ustrlen = strlen(key4);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key4, strlen(key4));
ptrbuf += strlen(key4);
ustrlen = 1;
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, "0", 1);
ptrbuf += 1;
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
free(buf);
#ifdef UWSGI_DEBUG
uwsgi_log("add_me() successfull\n");
#endif
return 0;
}
int uwsgi_cluster_join(char *name) {
int fd;
char *cp;
int broadcast = 0;
if (name[0] == ':') {
fd = bind_to_udp(name, 0, 1);
broadcast = 1;
}
else {
fd = bind_to_udp(name, 1, 0);
}
if (fd >= 0) {
cp = strchr(name, ':');
cp[0] = 0;
uwsgi.mc_cluster_addr.sin_family = AF_INET;
if (broadcast) {
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
}
else {
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
}
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
cp[0] = ':';
// announce my presence to all the nodes
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
}
else {
exit(1);
}
return fd;
}
char *uwsgi_cluster_best_node() {
int i;
int best_node = -1;
struct uwsgi_cluster_node *ucn;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
if (best_node == -1) {
best_node = i;
}
else {
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
best_node = i;
}
}
}
}
if (best_node == -1) {
return NULL;
}
uwsgi.shared->nodes[best_node].last_choosen = uwsgi_now();
return uwsgi.shared->nodes[best_node].name;
}
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
}
if (!uwsgi_strncmp("address", 7, key, keylen)) {
strncpy(ucn->name, val, UMIN(vallen, 100));
}
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->workers = atoi(tmpstr);
free(tmpstr);
}
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->requests = strtoul(tmpstr, NULL, 0);
free(tmpstr);
}
}
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.workers[0].cores[0].req.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.workers[0].cores[0].req.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;
}
+312
View File
@@ -0,0 +1,312 @@
#include "../uwsgi.h"
extern struct uwsgi_server uwsgi;
/*
External uwsgi daemons
There are 3 kind of daemons (read: external applications) that can be managed
by uWSGI.
1) dumb daemons (attached with --attach-daemon)
they must not daemonize() and when they exit() the master is notified (via waitpid)
and the process is respawned
2) smart daemons with daemonization
you specify a pidfile and a command
- on startup - if the pidfile does not exists or contains a not-available pid (checked with kill(pid, 0))
the daemon is respawned
- on master ckeck - if the pidfile does not exist or if it point to a non-existent pid
the daemon is respawned
3) smart daemons without daemonization
same as 2, but the daemonization and pidfile creation is managed by uWSGI
status:
0 -> never started
1 -> just started
2 -> started and monitored (only in pidfile based)
*/
void uwsgi_daemons_smart_check() {
static time_t last_run = 0;
time_t now = uwsgi_now();
if (now - last_run <= 0) {
return;
}
last_run = now;
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pidfile) {
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
if (checked_pid <= 0) {
// monitored instance
if (ud->status == 2) {
uwsgi_spawn_daemon(ud);
}
else {
ud->pidfile_checks++;
if (ud->pidfile_checks >= (unsigned int) ud->freq) {
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
uwsgi_spawn_daemon(ud);
}
}
}
else if (checked_pid != ud->pid) {
uwsgi_log("[uwsgi-daemons] found changed pid for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
ud->pid = checked_pid;
}
// all ok, pidfile and process found
else {
ud->status = 2;
}
}
ud = ud->next;
}
}
// this function is called when a dumb daemon dies and we do not wat to respawn it
int uwsgi_daemon_check_pid_death(pid_t diedpid) {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid == diedpid && !ud->pidfile) {
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
return -1;
}
ud = ud->next;
}
return 0;
}
// this function is called when a dumb daemon dies and we want to respawn it
int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid == diedpid && !ud->pidfile) {
uwsgi_spawn_daemon(ud);
return 1;
}
ud = ud->next;
}
return 0;
}
int uwsgi_check_pidfile(char *filename) {
struct stat st;
pid_t ret = -1;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(filename);
goto end;
}
if (fstat(fd, &st)) {
uwsgi_error("fstat()");
goto end2;
}
char *pidstr = uwsgi_calloc(st.st_size + 1);
if (read(fd, pidstr, st.st_size) != st.st_size) {
uwsgi_error("read()");
goto end3;
}
pid_t pid = atoi(pidstr);
if (pid <= 0)
goto end3;
if (!kill(pid, 0)) {
ret = pid;
}
end3:
free(pidstr);
end2:
close(fd);
end:
return ret;
}
void uwsgi_daemons_spawn_all() {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (!ud->registered) {
if (ud->pidfile) {
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
if (checked_pid <= 0) {
uwsgi_spawn_daemon(ud);
}
else {
ud->pid = checked_pid;
uwsgi_log("[uwsgi-daemons] found valid/active pidfile for \"%s\" (pid: %d)\n", ud->command, (int) ud->pid);
}
}
else {
uwsgi_spawn_daemon(ud);
}
ud->registered = 1;
}
ud = ud->next;
}
}
void uwsgi_detach_daemons() {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid > 0 && !ud->pidfile)
kill(-ud->pid, SIGKILL);
ud = ud->next;
}
}
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
int devnull = -1;
int throttle = 0;
if (uwsgi.current_time - ud->last_spawn <= 3) {
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
}
pid_t pid = uwsgi_fork("uWSGI external daemon");
if (pid < 0) {
uwsgi_error("fork()");
return;
}
if (pid > 0) {
ud->pid = pid;
ud->status = 1;
ud->pidfile_checks = 0;
if (ud->respawns == 0) {
ud->born = uwsgi_now();
}
ud->respawns++;
ud->last_spawn = uwsgi_now();
}
else {
// close uwsgi sockets
uwsgi_close_all_sockets();
uwsgi_close_all_fds();
if (ud->daemonize) {
/* refork... */
pid = fork();
if (pid < 0) {
uwsgi_error("fork()");
exit(1);
}
if (pid != 0) {
_exit(0);
}
uwsgi_write_pidfile(ud->pidfile);
}
// /dev/null will became stdin
devnull = open("/dev/null", O_RDONLY);
if (devnull < 0) {
uwsgi_error("/dev/null open()");
exit(1);
}
if (devnull != 0) {
if (dup2(devnull, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(devnull);
}
if (setsid() < 0) {
uwsgi_error("setsid()");
exit(1);
}
if (!ud->pidfile) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
}
if (throttle) {
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
sleep(throttle);
}
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
uwsgi_exec_command_with_args(ud->command);
uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command);
// never here;
exit(1);
}
return;
}
void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;
char *pidfile = NULL;
int daemonize = 0;
int freq = 10;
char *command = uwsgi_str(value);
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2")) {
char *space = strchr(command, ' ');
if (!space) {
uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
exit(1);
}
*space = 0;
pidfile = command;
// check for freq
char *comma = strchr(pidfile, ',');
if (comma) {
*comma = 0;
freq = atoi(comma + 1);
}
command = space + 1;
if (!strcmp(opt, "smart-attach-daemon2")) {
daemonize = 1;
}
}
if (!uwsgi_ud) {
uwsgi.daemons = uwsgi_malloc(sizeof(struct uwsgi_daemon));
uwsgi_ud = uwsgi.daemons;
}
else {
while (uwsgi_ud) {
old_ud = uwsgi_ud;
uwsgi_ud = uwsgi_ud->next;
}
uwsgi_ud = uwsgi_malloc(sizeof(struct uwsgi_daemon));
old_ud->next = uwsgi_ud;
}
uwsgi_ud->command = command;
uwsgi_ud->pid = 0;
uwsgi_ud->status = 0;
uwsgi_ud->freq = freq;
uwsgi_ud->registered = 0;
uwsgi_ud->next = NULL;
uwsgi_ud->respawns = 0;
uwsgi_ud->last_spawn = 0;
uwsgi_ud->daemonize = daemonize;
uwsgi_ud->pidfile = pidfile;
uwsgi.daemons_cnt++;
}
+1405
View File
File diff suppressed because it is too large Load Diff
+1154
View File
File diff suppressed because it is too large Load Diff
+161
View File
@@ -0,0 +1,161 @@
#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);
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, 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;
}
+16 -15
View File
@@ -13,7 +13,7 @@ void ini_rstrip(char *line) {
off_t i;
for(i = strlen(line)-1;i>=0; i--) {
for (i = strlen(line) - 1; i >= 0; i--) {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
line[i] = 0;
continue;
@@ -27,7 +27,7 @@ char *ini_lstrip(char *line) {
off_t i;
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
for (i = 0; i < (int) strlen(line); i++) {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
@@ -43,7 +43,7 @@ char *ini_get_key(char *key) {
off_t i;
char *ptr = key;
for(i=0;i< (int) strlen(key);i++) {
for (i = 0; i < (int) strlen(key); i++) {
ptr++;
if (key[i] == '=') {
key[i] = 0;
@@ -59,7 +59,7 @@ char *ini_get_line(char *ini, off_t size) {
off_t i;
char *ptr = ini;
for(i=0;i<size;i++) {
for (i = 0; i < size; i++) {
ptr++;
if (ini[i] == '\n') {
ini[i] = 0;
@@ -92,18 +92,19 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
char *section_asked = "uwsgi";
char *colon;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
section_asked = colon+1;
section_asked = colon + 1;
}
}
@@ -113,7 +114,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
while(len) {
while (len) {
ini_line = ini_get_line(ini, len);
if (ini_line == NULL) {
break;
@@ -125,8 +126,8 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
ini_rstrip(key);
if (key[0] != 0) {
if (key[0] == '[') {
section = key+1;
section[strlen(section)-1] = 0;
section = key + 1;
section[strlen(section) - 1] = 0;
}
else if (key[0] == ';' || key[0] == '#') {
// this is a comment
@@ -139,7 +140,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
add_exported_option((char *)key, val, 0);
add_exported_option((char *) key, val, 0);
}
}
}
+295
View File
@@ -0,0 +1,295 @@
#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.stats_pusher_default_freq = 3;
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.offload_threads_events = 64;
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
#ifdef UWSGI_ALARM
uwsgi.alarm_freq = 3;
#endif
#ifdef UWSGI_MULTICAST
uwsgi.multicast_ttl = 1;
#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);
// this is a trick for avoiding too much memory areas
void *ts = uwsgi_calloc_shared(sizeof(void *) * uwsgi.max_apps * uwsgi.cores);
void *buffers = uwsgi_malloc_shared(uwsgi.buffer_size * uwsgi.cores);
void *hvec = uwsgi_malloc_shared(sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
void *post_buf = NULL;
if (uwsgi.post_buffering > 0)
post_buf = uwsgi_malloc_shared(uwsgi.post_buffering_bufsize * 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 = ts + ((sizeof(void *) * uwsgi.max_apps) * j);
// raw per-request buffer
uwsgi.workers[i].cores[j].buffer = buffers + (uwsgi.buffer_size * j);
// iovec for uwsgi vars
uwsgi.workers[i].cores[j].hvec = hvec + ((sizeof(struct iovec) * uwsgi.vec_size) * j);
if (post_buf)
uwsgi.workers[i].cores[j].post_buf = post_buf + (uwsgi.post_buffering_bufsize * j);
}
// 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);
}
uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
if (uwsgi.post_buffering > 0) {
total_memory += (uwsgi.post_buffering_bufsize * uwsgi.cores);
}
total_memory *= (uwsgi.numproc + uwsgi.master_process);
uwsgi_log("mapped %llu bytes (%llu KB) for %d cores\n", total_memory, total_memory / 1024, uwsgi.cores * uwsgi.numproc);
}
pid_t uwsgi_daemonize2() {
if (uwsgi.has_emperor) {
logto(uwsgi.daemonize2);
}
else {
if (!uwsgi.is_a_reload) {
uwsgi_log("*** daemonizing uWSGI ***\n");
daemonize(uwsgi.daemonize2);
}
else if (uwsgi.log_reopen) {
logto(uwsgi.daemonize2);
}
}
uwsgi.mypid = getpid();
uwsgi.workers[0].pid = uwsgi.mypid;
if (uwsgi.pidfile && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile);
}
if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
return uwsgi.mypid;
}
+29 -29
View File
@@ -31,17 +31,17 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
int i;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
object_asked = colon+1;
object_asked = colon + 1;
}
}
@@ -49,7 +49,7 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
#ifdef JANSSON_MAJOR_VERSION
#ifdef JANSSON_MAJOR_VERSION
root = json_loads(json_data, 0, &error);
#else
root = json_loads(json_data, &error);
@@ -66,46 +66,46 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
uwsgi_log("you must define a object named %s in your JSON data\n", object_asked);
exit(1);
}
config_iter = json_object_iter(config);
while(config_iter) {
while (config_iter) {
key = json_object_iter_key(config_iter);
config_value = json_object_iter_value(config_iter);
config_value = json_object_iter_value(config_iter);
if (json_is_string(config_value)) {
add_exported_option((char *)key, (char *) json_string_value(config_value), 0);
add_exported_option((char *) key, (char *) json_string_value(config_value), 0);
}
else if (json_is_true(config_value)) {
add_exported_option((char *)key, strdup("1"), 0);
add_exported_option((char *) key, strdup("1"), 0);
}
else if (json_is_false(config_value) || json_is_null(config_value)) {
add_exported_option((char *)key, strdup("0"), 0);
add_exported_option((char *) key, strdup("0"), 0);
}
else if (json_is_integer(config_value)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_value)), 0);
add_exported_option((char *) key, uwsgi_num2str(json_integer_value(config_value)), 0);
}
else if (json_is_array(config_value)) {
for(i=0;i<(int)json_array_size(config_value);i++) {
config_array_item = json_array_get(config_value, i);
for (i = 0; i < (int) json_array_size(config_value); i++) {
config_array_item = json_array_get(config_value, i);
if (json_is_string(config_array_item)) {
add_exported_option((char *)key, (char *) json_string_value(config_array_item), 0);
}
else if (json_is_true(config_array_item)) {
add_exported_option((char *)key, strdup("1"), 0);
}
else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
add_exported_option((char *)key, strdup("0"), 0);
}
else if (json_is_integer(config_array_item)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
}
add_exported_option((char *) key, (char *) json_string_value(config_array_item), 0);
}
else if (json_is_true(config_array_item)) {
add_exported_option((char *) key, strdup("1"), 0);
}
else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
add_exported_option((char *) key, strdup("0"), 0);
}
else if (json_is_integer(config_array_item)) {
add_exported_option((char *) key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
}
}
}
config_iter = json_object_iter_next(config, config_iter);
}
}
#endif
+68 -67
View File
@@ -19,25 +19,25 @@ void ldap2uwsgi(char *ldapname, char *uwsginame) {
int i;
for(i=0;i< (int) strlen(ldapname);i++) {
if (isupper( (int)ldapname[i])) {
for (i = 0; i < (int) strlen(ldapname); i++) {
if (isupper((int) ldapname[i])) {
*ptr++ = '-';
*ptr++ = tolower( (int) ldapname[i]);
*ptr++ = tolower((int) ldapname[i]);
}
else {
*ptr++ = ldapname[i];
}
}
*ptr++= 0;
*ptr++ = 0;
}
int calc_ldap_name(char *name) {
int i;
int counter = 0;
for(i=0;i< (int)strlen(name);i++) {
if (isupper( (int) name[i])) {
for (i = 0; i < (int) strlen(name); i++) {
if (isupper((int) name[i])) {
counter++;
}
}
@@ -52,7 +52,7 @@ struct uwsgi_ldap_entry {
};
void uwsgi_name_to_ldap(char *src, char *dst) {
void uwsgi_name_to_ldap(char *src, char *dst) {
int i;
char *ptr = dst;
@@ -61,16 +61,16 @@ void uwsgi_name_to_ldap(char *src, char *dst) {
strcat(dst, " 'uWSGI");
ptr+= 7;
ptr += 7;
for(i=0;i< (int)strlen(src);i++) {
if (src[i] == '-') {
i++;
*ptr++= toupper( (int) src[i]);
}
else {
*ptr++= src[i];
}
for (i = 0; i < (int) strlen(src); i++) {
if (src[i] == '-') {
i++;
*ptr++ = toupper((int) src[i]);
}
else {
*ptr++ = src[i];
}
}
strcat(dst, "'");
@@ -82,7 +82,7 @@ struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num,
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
for (i = 0; i < count; i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
@@ -96,9 +96,9 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
for (i = 0; i < count; i++) {
ule = &root[i];
if (uwsgi_list_has_str(ule->names, name+1)) {
if (uwsgi_list_has_str(ule->names, name + 1)) {
return ule;
}
}
@@ -114,23 +114,24 @@ struct uwsgi_ldap_entry *get_ldap_names(int *count) {
*count = 0;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*uwsgi_count_options(op));
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry) * uwsgi_count_options(op));
while( op && op->name ) {
while (op && op->name) {
uwsgi_name_to_ldap((char *)op->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 (entry)
goto next;
entry = &ule[*count] ;
entry = &ule[*count];
entry->num = *count;
strcpy(entry->names, ldap_name);
*count = *count+1;
*count = *count + 1;
entry->has_arg = op->type;
next:
op++;
}
@@ -150,7 +151,7 @@ void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
for (i = 0; i < items; i++) {
entry = &ule[i];
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
@@ -168,19 +169,19 @@ void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for(i=0;i<items;i++) {
entry = &ule[i];
for (i = 0; i < items; i++) {
char *list2 = uwsgi_concat2(entry->names+1, "");
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names + 1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
p = strtok(NULL, " ");
}
free(list2);
free(list2);
}
@@ -198,38 +199,38 @@ void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
for (i = 0; i < items; i++) {
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for(i=0;i<items;i++) {
for (i = 0; i < items; i++) {
entry = &ule[i];
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
char *list2 = uwsgi_concat2(entry->names + 1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
p = strtok(NULL, " ");
}
free(list2);
free(list2);
}
}
@@ -264,7 +265,7 @@ void uwsgi_ldap_config(char *url) {
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
url_slash = strchr(url, '/');
@@ -281,25 +282,25 @@ void uwsgi_ldap_config(char *url) {
#endif
#if LDAP_API_VERSION >= 3000
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
if ((ret = ldap_initialize(&ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ( (ldp = ldap_init( ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
if ((ldp = ldap_init(ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
if ((ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
if ( (ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
if ((ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
@@ -318,17 +319,17 @@ void uwsgi_ldap_config(char *url) {
entry = ldap_first_entry(ldp, results);
int found = 0;
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr,"uWSGI",5)) {
for (attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr, "uWSGI", 5)) {
found = 1;
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
uwsgi_attr = malloc(calc_ldap_name(attr) + 1);
if (!uwsgi_attr) {
uwsgi_error("malloc()");
exit(1);
}
ldap2uwsgi(attr+5, uwsgi_attr);
ldap2uwsgi(attr + 5, uwsgi_attr);
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP attribute: %s = --%s\n", attr, uwsgi_attr);
@@ -336,7 +337,7 @@ void uwsgi_ldap_config(char *url) {
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_attr/uwsgi_val;
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
char *uwsgi_val = malloc(bervalues[0]->bv_len + 1);
if (!uwsgi_val) {
uwsgi_error("malloc()");
exit(1);
@@ -345,7 +346,7 @@ void uwsgi_ldap_config(char *url) {
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
add_exported_option((char*) uwsgi_attr, uwsgi_val, 0);
add_exported_option((char *) uwsgi_attr, uwsgi_val, 0);
free(bervalues);
}
else {
+320 -103
View File
@@ -20,7 +20,7 @@ static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
return uwsgi.registered_locks;
}
while(uli) {
while (uli) {
if (!uli->next) {
uli->next = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
if (rw) {
@@ -45,7 +45,16 @@ static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
#ifdef UWSGI_LOCK_USE_MUTEX
#ifdef OBSOLETE_LINUX_KERNEL
#undef EOWNERDEAD
#endif
#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)
@@ -55,87 +64,110 @@ static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlock_t)
#endif
#ifndef PTHREAD_PRIO_INHERIT
int pthread_mutexattr_setprotocol (pthread_mutexattr_t *__attr,
int __protocol);
#define PTHREAD_PRIO_INHERIT 1
#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);
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);
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);
}
if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share mutex\n");
exit(1);
}
#ifdef EOWNERDEAD
#ifndef PTHREAD_MUTEX_ROBUST
#define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP
#endif
if (pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) {
uwsgi_log("unable to set PTHREAD_PRIO_INHERIT\n");
exit(1);
}
if (uwsgi_pthread_robust_mutexes_enabled) {
if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST)) {
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) {
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);
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) {
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);
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;
return uli->pid;
#endif
}
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
}
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);
uli->pid = uwsgi.mypid;
#endif
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
@@ -145,30 +177,57 @@ void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
}
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(uli);
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_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_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);
}
if (pthread_rwlock_init((pthread_rwlock_t *) uli->lock_ptr, &attr)) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
pthread_rwlockattr_destroy(&attr);
@@ -194,36 +253,97 @@ struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
#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_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);
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() );
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() );
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() );
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); }
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)
@@ -260,19 +380,27 @@ pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
return uli->pid;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
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);}
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); }
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); }
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
}
#else
@@ -302,10 +430,10 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
// used by ftok
static int counter = 1;
union semun {
int val;
int val;
struct semid_ds *buf;
ushort *array;
} semu ;
} semu;
int semid;
key_t myKey;
@@ -318,10 +446,10 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
exit(1);
}
counter++;
semid = semget(myKey, 1, IPC_CREAT|0666);
semid = semget(myKey, 1, IPC_CREAT | 0666);
}
else {
semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL| 0666);
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0666);
}
if (semid < 0) {
@@ -336,7 +464,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
uwsgi_error("semctl()");
exit(1);
}
return uli;
}
@@ -352,7 +480,7 @@ void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
if (semop(semid, &sb, 1)) {
uwsgi_error("semop()");
}
}
}
void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
@@ -367,14 +495,22 @@ void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
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); }
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) {
@@ -385,13 +521,17 @@ void uwsgi_ipcsem_clear(void) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uwsgi.workers) goto clear;
if (!uwsgi.workers)
goto clear;
if (uwsgi.mywid == 0) goto clear;
if (uwsgi.mywid == 0)
goto clear;
if (uwsgi.master_process && getpid() == uwsgi.workers[0].pid) goto clear;
if (uwsgi.master_process && getpid() == uwsgi.workers[0].pid)
goto clear;
if (!uwsgi.master_process && uwsgi.mywid == 1) goto clear;
if (!uwsgi.master_process && uwsgi.mywid == 1)
goto clear;
return;
@@ -400,7 +540,7 @@ clear:
#ifdef UWSGI_DEBUG
uwsgi_log("removing sysvipc semaphores...\n");
#endif
while(uli) {
while (uli) {
int semid = 0;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semctl(semid, 0, IPC_RMID)) {
@@ -411,15 +551,17 @@ clear:
}
pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_ipcsem_check(uli); }
pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) {
return uwsgi_lock_ipcsem_check(uli);
}
void uwsgi_setup_locking() {
// use the fastest avaikable locking
// use the fastest available locking
if (uwsgi.lock_engine) {
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
uwsgi_log("lock engine: ipcsem\n");
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;
@@ -436,7 +578,7 @@ void uwsgi_setup_locking() {
}
}
uwsgi_log("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
uwsgi_log_initial("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
#ifdef UWSGI_IPCSEM_ATEXIT
atexit(uwsgi_ipcsem_clear);
#endif
@@ -451,13 +593,53 @@ void uwsgi_setup_locking() {
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");
}
if (uwsgi.use_thunder_lock) {
// process shared thunder lock
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
}
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_CUR;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = 0;
@@ -472,16 +654,51 @@ int uwsgi_fcntl_lock(int fd) {
int uwsgi_fcntl_is_locked(int fd) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_CUR;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = 0;
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)) {
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;
}
}
void uwsgi_user_lock(int lock_num) {
uwsgi_lock(uwsgi.user_lock[lock_num]);
}
void uwsgi_user_unlock(int lock_num) {
uwsgi_unlock(uwsgi.user_lock[lock_num]);
}
+1258
View File
File diff suppressed because it is too large Load Diff
+171
View File
@@ -0,0 +1,171 @@
#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 (*func) (void)) {
struct uwsgi_loop *old_loop = NULL, *loop = uwsgi.loops;
while (loop) {
// check if the loop engine is already registered
if (!strcmp(name, loop->name))
return;
old_loop = loop;
loop = loop->next;
}
loop = uwsgi_calloc(sizeof(struct uwsgi_loop));
loop->name = name;
loop->loop = func;
if (old_loop) {
old_loop->next = loop;
}
else {
uwsgi.loops = loop;
}
}
void *uwsgi_get_loop(char *name) {
struct uwsgi_loop *loop = uwsgi.loops;
while (loop) {
if (!strcmp(name, loop->name)) {
return loop->loop;
}
loop = loop->next;
}
return NULL;
}
/*
this is the default (simple) loop.
it will run simple_loop_run function for each spawned thread
simple_loop_run monitors sockets and signals descriptors
and manages them.
*/
void simple_loop() {
uwsgi_loop_cores_run(simple_loop_run);
}
void uwsgi_loop_cores_run(void *(*func) (void *)) {
int i;
#ifdef UWSGI_THREADING
for (i = 1; i < uwsgi.threads; i++) {
long j = i;
pthread_create(&uwsgi.workers[uwsgi.mywid].cores[i].thread_id, &uwsgi.threads_attr, func, (void *) j);
}
#endif
long y = 0;
func((void *) y);
}
void uwsgi_setup_thread_req(long core_id, struct wsgi_request *wsgi_req) {
int i;
sigset_t smask;
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);
}
}
}
}
void simple_loop_run_int(int core_id) {
long y = core_id;
simple_loop_run((void *) y);
}
void *simple_loop_run(void *arg1) {
long core_id = (long) arg1;
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) {
uwsgi_setup_thread_req(core_id, wsgi_req);
}
#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;
}
+609 -545
View File
File diff suppressed because it is too large Load Diff
+579 -179
View File
@@ -5,9 +5,48 @@ extern struct uwsgi_server uwsgi;
void worker_wakeup() {
}
void uwsgi_master_cleanup_hooks(void) {
int j;
// could be an inherited atexit hook
if (uwsgi.mywid > 0)
return;
uwsgi.cleaning = 1;
for (j = 0; j < uwsgi.gp_cnt; j++) {
if (uwsgi.gp[j]->master_cleanup) {
uwsgi.gp[j]->master_cleanup();
}
}
for (j = 0; j < 256; j++) {
if (uwsgi.p[j]->master_cleanup) {
uwsgi.p[j]->master_cleanup();
}
}
}
int uwsgi_calc_cheaper(void) {
int i;
static time_t last_check = 0;
int check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!last_check)
last_check = uwsgi_now();
time_t now = uwsgi_now();
if (!check_interval)
check_interval = 1;
if ((now - last_check) < check_interval)
return 1;
last_check = now;
int needed_workers = uwsgi.cheaper_algo();
@@ -103,7 +142,7 @@ int uwsgi_cheaper_algo_spare(void) {
overload_count++;
idle_count = 0;
healthy:
healthy:
// are we overloaded ?
if (overload_count > uwsgi.cheaper_overload) {
@@ -178,24 +217,24 @@ int uwsgi_cheaper_algo_backlog(void) {
int i;
#ifdef __linux__
int backlog = uwsgi.shared->ti.tcpi_unacked;
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
#else
int backlog = 0;
#endif
if (backlog > (int)uwsgi.cheaper_overload) {
if (backlog > (int) uwsgi.cheaper_overload) {
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step)
break;
}
}
// return the maximum number of workers to spawn
return decheaped;
int decheaped = 0;
// search for cheaped workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step)
break;
}
}
// return the maximum number of workers to spawn
return decheaped;
}
else if (backlog < (int) uwsgi.cheaper_overload) {
@@ -210,7 +249,7 @@ int uwsgi_cheaper_algo_backlog(void) {
return -1;
}
}
return 0;
}
@@ -226,6 +265,12 @@ void uwsgi_reload(char **argv) {
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
// call master cleanup hooks
uwsgi_master_cleanup_hooks();
// call atexit user exec
uwsgi_exec_atexit();
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
@@ -238,8 +283,8 @@ void uwsgi_reload(char **argv) {
}
/* check fd table (a module can obviosly open some fd on initialization...) */
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int)uwsgi.max_fd);
for (i = 3; i < (int)uwsgi.max_fd; i++) {
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
for (i = 3; i < (int) uwsgi.max_fd; i++) {
int found = 0;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
@@ -252,6 +297,17 @@ void uwsgi_reload(char **argv) {
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi.shared_sockets;
while (uwsgi_sock) {
if (i == uwsgi_sock->fd) {
uwsgi_log("found fd %d mapped to shared socket %d (%s)\n", i, uwsgi_get_shared_socket_num(uwsgi_sock), uwsgi_sock->name);
found = 1;
break;
}
uwsgi_sock = uwsgi_sock->next;
}
if (!found) {
if (uwsgi.has_emperor) {
if (i == uwsgi.emperor_fd) {
@@ -278,7 +334,7 @@ void uwsgi_reload(char **argv) {
found = 1;
}
}
}
if (!found) {
@@ -437,6 +493,28 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
int uwsgi_respawn_worker(int wid) {
int respawns = uwsgi.workers[wid].respawn_count;
// we count the respawns before errors...
uwsgi.workers[wid].respawn_count++;
// ... same for update time
uwsgi.workers[wid].last_spawn = uwsgi.current_time;
// ... and memory/harakiri
uwsgi.workers[wid].harakiri = 0;
uwsgi.workers[wid].user_harakiri = 0;
uwsgi.workers[wid].pending_harakiri = 0;
uwsgi.workers[wid].rss_size = 0;
uwsgi.workers[wid].vsz_size = 0;
// internal statuses should be reset too
uwsgi.workers[wid].cheaped = 0;
uwsgi.workers[wid].busy = 0;
// SUSPENSION is managed by the user, not the master...
//uwsgi.workers[wid].suspended = 0;
uwsgi.workers[wid].sig = 0;
// this is required for various checks
uwsgi.workers[wid].delta_requests = 0;
int i;
if (uwsgi.threaded_logger) {
@@ -450,35 +528,46 @@ int uwsgi_respawn_worker(int wid) {
signal(SIGTSTP, worker_wakeup);
uwsgi.mywid = wid;
uwsgi.mypid = getpid();
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
// pid is updated by the master
//uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
// OVERENGINEERING (just to be safe)
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
/*
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
*/
// do not reset worker counters on reload !!!
//uwsgi.workers[uwsgi.mywid].requests = 0;
// ...but maintain a delta counter (yes this is racy in multithread)
uwsgi.workers[uwsgi.mywid].delta_requests = 0;
//uwsgi.workers[uwsgi.mywid].delta_requests = 0;
//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
//uwsgi.workers[uwsgi.mywid].respawn_count++;
//uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
uwsgi.workers[uwsgi.mywid].cheaped = 0;
uwsgi.workers[uwsgi.mywid].busy = 0;
uwsgi.workers[uwsgi.mywid].suspended = 0;
uwsgi.workers[uwsgi.mywid].sig = 0;
/*
uwsgi.workers[uwsgi.mywid].cheaped = 0;
uwsgi.workers[uwsgi.mywid].busy = 0;
uwsgi.workers[uwsgi.mywid].suspended = 0;
uwsgi.workers[uwsgi.mywid].sig = 0;
*/
// reset the apps count with a copy from the master
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
// reset wsgi_request structures
for(i=0;i<uwsgi.cores;i++) {
memset(&uwsgi.workers[uwsgi.mywid].cores[i].req, 0, sizeof(struct wsgi_request));
}
uwsgi_fixup_fds(wid, 0, NULL);
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
if (uwsgi.master_process) {
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
for (i = 0; i < 0xFF; i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
@@ -492,6 +581,9 @@ int uwsgi_respawn_worker(int wid) {
uwsgi_error("fork()");
}
else {
// the pid is set only in the master, as the worker should never use it
uwsgi.workers[wid].pid = pid;
if (respawns > 0) {
uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
}
@@ -533,20 +625,36 @@ void uwsgi_manage_signal_cron(time_t now) {
uc_month = ucron->month;
uc_week = ucron->week;
if (ucron->minute == -1)
uc_minute = uwsgi_cron_delta->tm_min;
if (ucron->hour == -1)
uc_hour = uwsgi_cron_delta->tm_hour;
if (ucron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (ucron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
// negative values as interval -1 = * , -5 = */5
if (ucron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (ucron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (ucron->month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (ucron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (ucron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (ucron->day != -1 && ucron->week != -1) {
if (ucron->day >= 0 && ucron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
@@ -590,8 +698,10 @@ void uwsgi_manage_command_cron(time_t now) {
return;
}
while (current_cron) {
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
uc_minute = current_cron->minute;
uc_hour = current_cron->hour;
@@ -599,20 +709,36 @@ void uwsgi_manage_command_cron(time_t now) {
uc_month = current_cron->month;
uc_week = current_cron->week;
if (current_cron->minute == -1)
uc_minute = uwsgi_cron_delta->tm_min;
if (current_cron->hour == -1)
uc_hour = uwsgi_cron_delta->tm_hour;
if (current_cron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (current_cron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (current_cron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
// negative values as interval -1 = * , -5 = */5
if (current_cron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (current_cron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (current_cron->month < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (current_cron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (current_cron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (current_cron->day != -1 && current_cron->week != -1) {
if (current_cron->day >= 0 && current_cron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
@@ -646,184 +772,458 @@ void uwsgi_manage_command_cron(time_t now) {
}
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
struct uwsgi_stats *uwsgi_master_generate_stats() {
void uwsgi_send_stats(int fd) {
int i;
int i, j;
struct sockaddr_un client_src;
struct uwsgi_app *ua;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
struct uwsgi_stats *us = uwsgi_stats_new(8192);
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
if (uwsgi_stats_keyval_comma(us, "version", UWSGI_VERSION))
goto end;
#ifdef __linux__
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]))
goto end;
if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]))
goto end;
#endif
stats_send_llu("\"load\": %llu,\n", uwsgi.shared->load);
int signal_queue = 0;
if (ioctl(uwsgi.shared->worker_signal_pipe[1], FIONREAD, &signal_queue)) {
uwsgi_error("uwsgi_master_generate_stats() -> ioctl()\n");
}
fprintf(output, "\"pid\": %d,\n", (int) (getpid()));
fprintf(output, "\"uid\": %d,\n", (int) (getuid()));
fprintf(output, "\"gid\": %d,\n", (int) (getgid()));
if (uwsgi_stats_keylong_comma(us, "signal_queue", (unsigned long long) signal_queue))
goto end;
if (uwsgi_stats_keylong_comma(us, "load", (unsigned long long) uwsgi.shared->load))
goto end;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) getpid()))
goto end;
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) getuid()))
goto end;
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) getgid()))
goto end;
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
if (uwsgi_stats_keyval_comma(us, "cwd", cwd)) {
free(cwd);
goto end;
}
free(cwd);
if (uwsgi.daemons) {
fprintf(output, "\"daemons\": [\n");
if (uwsgi_stats_key(us, "daemons"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
fprintf(output, "\t{ \"cmd\": \"%s\", \"pid\": %d, \"respawns\": %llu }", ud->command, (int) ud->pid, (unsigned long long) ud->respawns - 1);
if (ud->next)
fprintf(output, ",\n");
else {
fprintf(output, "\n");
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyval_comma(us, "cmd", ud->command))
goto end;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) ud->pid))
goto end;
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) (ud->respawns - 1)))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
if (ud->next) {
if (uwsgi_stats_comma(us))
goto end;
}
ud = ud->next;
}
fprintf(output, "],\n");
if (uwsgi_stats_list_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
}
fprintf(output, "\"locks\": [\n");
if (uwsgi_stats_key(us, "locks"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
while (uli) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keylong(us, uli->id, (unsigned long long) uli->pid))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
if (uli->next) {
fprintf(output, "\t{ \"%s\": %d },\n", uli->id, (int) uli->pid);
}
else {
fprintf(output, "\t{ \"%s\": %d }\n", uli->id, (int) uli->pid);
if (uwsgi_stats_comma(us))
goto end;
}
uli = uli->next;
}
fprintf(output, "],\n");
if (uwsgi_stats_list_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
fprintf(output, "\"workers\": [\n");
if (uwsgi_stats_key(us, "sockets"))
goto end;
for (i = 0; i < uwsgi.numproc; i++) {
fprintf(output, "\t{");
if (uwsgi_stats_list_open(us))
goto end;
fprintf(output, "\"id\": %d, ", uwsgi.workers[i + 1].id);
fprintf(output, "\"pid\": %d, ", (int) uwsgi.workers[i + 1].pid);
stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i + 1].requests);
stats_send_llu("\"delta_requests\": %llu, ", uwsgi.workers[i + 1].delta_requests);
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i + 1].exceptions);
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i + 1].signals);
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi.workers[i + 1].cheaped) {
fprintf(output, "\"status\": \"cheap\", ");
}
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
fprintf(output, "\"status\": \"pause\", ");
}
else {
if (uwsgi.workers[i + 1].sig) {
fprintf(output, "\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
}
else if (uwsgi.workers[i + 1].busy) {
fprintf(output, "\"status\": \"busy\", ");
}
else {
fprintf(output, "\"status\": \"idle\", ");
}
}
if (uwsgi_stats_keyval_comma(us, "name", uwsgi_sock->name))
goto end;
stats_send_llu("\"rss\": %llu, ", uwsgi.workers[i + 1].rss_size);
stats_send_llu("\"vsz\": %llu, ", uwsgi.workers[i + 1].vsz_size);
if (uwsgi_stats_keyval_comma(us, "proto", uwsgi_sock->proto_name ? uwsgi_sock->proto_name : "uwsgi"))
goto end;
stats_send_llu("\"running_time\": %llu, ", uwsgi.workers[i + 1].running_time);
stats_send_llu("\"last_spawn\": %llu, ", uwsgi.workers[i + 1].last_spawn);
stats_send_llu("\"respawn_count\": %llu, ", uwsgi.workers[i + 1].respawn_count);
stats_send_llu("\"tx\": %llu, ", uwsgi.workers[i + 1].tx);
stats_send_llu("\"avg_rt\": %llu, ", uwsgi.workers[i + 1].avg_response_time);
if (uwsgi_stats_keylong_comma(us, "queue", (unsigned long long) uwsgi_sock->queue))
goto end;
fprintf(output, "\"apps\": [\n");
if (uwsgi_stats_keylong_comma(us, "shared", (unsigned long long) uwsgi_sock->shared))
goto end;
for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
ua = &uwsgi.workers[i + 1].apps[j];
fprintf(output, "\t\t{ ");
if (uwsgi_stats_keylong(us, "can_offload", (unsigned long long) uwsgi_sock->can_offload))
goto end;
fprintf(output, "\"id\": %d, ", j);
fprintf(output, "\"modifier1\": %d, ", ua->modifier1);
fprintf(output, "\"mountpoint\": \"%.*s\", ", ua->mountpoint_len, ua->mountpoint);
if (uwsgi_stats_object_close(us))
goto end;
stats_send_llu("\"startup_time\": %llu, ", ua->startup_time);
stats_send_llu("\"requests\": %llu, ", ua->requests);
stats_send_llu("\"exceptions\": %llu, ", ua->exceptions);
if (ua->chdir) {
fprintf(output, "\"chdir\": \"%s\", ", ua->chdir);
}
else {
fprintf(output, "\"chdir\": \"\" ");
}
if (j == uwsgi.workers[i + 1].apps_cnt - 1) {
fprintf(output, "}\n");
}
else {
fprintf(output, "},\n");
}
}
fprintf(output, "\t\t]");
if (i == uwsgi.numproc - 1) {
fprintf(output, "}\n");
}
else {
fprintf(output, "},\n");
uwsgi_sock = uwsgi_sock->next;
if (uwsgi_sock) {
if (uwsgi_stats_comma(us))
goto end;
}
}
fprintf(output, "]}\n");
fclose(output);
if (uwsgi_stats_list_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
if (uwsgi_stats_key(us, "workers"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
for (i = 0; i < uwsgi.numproc; i++) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) uwsgi.workers[i + 1].id))
goto end;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
goto end;
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "exceptions", (unsigned long long) uwsgi.workers[i + 1].exceptions))
goto end;
if (uwsgi_stats_keylong_comma(us, "harakiri_count", (unsigned long long) uwsgi.workers[i + 1].harakiri_count))
goto end;
if (uwsgi_stats_keylong_comma(us, "signals", (unsigned long long) uwsgi.workers[i + 1].signals))
goto end;
if (ioctl(uwsgi.workers[i + 1].signal_pipe[1], FIONREAD, &signal_queue)) {
uwsgi_error("uwsgi_master_generate_stats() -> ioctl()\n");
}
if (uwsgi_stats_keylong_comma(us, "signal_queue", (unsigned long long) signal_queue))
goto end;
if (uwsgi.workers[i + 1].cheaped) {
if (uwsgi_stats_keyval_comma(us, "status", "cheap"))
goto end;
}
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
if (uwsgi_stats_keyval_comma(us, "status", "pause"))
goto end;
}
else {
if (uwsgi.workers[i + 1].sig) {
if (uwsgi_stats_keyvalnum_comma(us, "status", "sig", (unsigned long long) uwsgi.workers[i + 1].signum))
goto end;
}
else if (uwsgi.workers[i + 1].busy) {
if (uwsgi_stats_keyval_comma(us, "status", "busy"))
goto end;
}
else {
if (uwsgi_stats_keyval_comma(us, "status", "idle"))
goto end;
}
}
if (uwsgi_stats_keylong_comma(us, "rss", (unsigned long long) uwsgi.workers[i + 1].rss_size))
goto end;
if (uwsgi_stats_keylong_comma(us, "vsz", (unsigned long long) uwsgi.workers[i + 1].vsz_size))
goto end;
if (uwsgi_stats_keylong_comma(us, "running_time", (unsigned long long) uwsgi.workers[i + 1].running_time))
goto end;
if (uwsgi_stats_keylong_comma(us, "last_spawn", (unsigned long long) uwsgi.workers[i + 1].last_spawn))
goto end;
if (uwsgi_stats_keylong_comma(us, "respawn_count", (unsigned long long) uwsgi.workers[i + 1].respawn_count))
goto end;
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) uwsgi.workers[i + 1].tx))
goto end;
if (uwsgi_stats_keylong_comma(us, "avg_rt", (unsigned long long) uwsgi.workers[i + 1].avg_response_time))
goto end;
// applications list
if (uwsgi_stats_key(us, "apps"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
int j;
for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
struct uwsgi_app *ua = &uwsgi.workers[i + 1].apps[j];
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j))
goto end;
if (uwsgi_stats_keylong_comma(us, "modifier1", (unsigned long long) ua->modifier1))
goto end;
if (uwsgi_stats_keyvaln_comma(us, "mountpoint", ua->mountpoint, ua->mountpoint_len))
goto end;
if (uwsgi_stats_keylong_comma(us, "startup_time", ua->startup_time))
goto end;
if (uwsgi_stats_keylong_comma(us, "requests", ua->requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "exceptions", ua->exceptions))
goto end;
if (ua->chdir) {
if (uwsgi_stats_keyval(us, "chdir", ua->chdir))
goto end;
}
else {
if (uwsgi_stats_keyval(us, "chdir", ""))
goto end;
}
if (uwsgi_stats_object_close(us))
goto end;
if (j < uwsgi.workers[i + 1].apps_cnt - 1) {
if (uwsgi_stats_comma(us))
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
// cores list
if (uwsgi_stats_key(us, "cores"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
for (j = 0; j < uwsgi.cores; j++) {
struct uwsgi_core *uc = &uwsgi.workers[i + 1].cores[j];
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j))
goto end;
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uc->requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "static_requests", (unsigned long long) uc->static_requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "routed_requests", (unsigned long long) uc->routed_requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "offloaded_requests", (unsigned long long) uc->offloaded_requests))
goto end;
if (uwsgi_stats_keylong(us, "in_request", (unsigned long long) uc->in_request))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
if (j < uwsgi.cores - 1) {
if (uwsgi_stats_comma(us))
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
if (i < uwsgi.numproc - 1) {
if (uwsgi_stats_comma(us))
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end;
#ifdef UWSGI_SPOOLER
struct uwsgi_spooler *uspool = uwsgi.spoolers;
if (uspool) {
if (uwsgi_stats_comma(us))
goto end;
if (uwsgi_stats_key(us, "spoolers"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
while (uspool) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyval_comma(us, "dir", uspool->dir))
goto end;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uspool->pid))
goto end;
if (uwsgi_stats_keylong_comma(us, "tasks", (unsigned long long) uspool->tasks))
goto end;
if (uwsgi_stats_keylong_comma(us, "respawns", (unsigned long long) uspool->respawned))
goto end;
if (uwsgi_stats_keylong(us, "running", (unsigned long long) uspool->running))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
uspool = uspool->next;
if (uspool) {
if (uwsgi_stats_comma(us))
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end;
}
#endif
if (uwsgi_stats_object_close(us))
goto end;
return us;
end:
free(us->base);
free(us);
return NULL;
}
void uwsgi_register_cheaper_algo(char *name, int(*func) (void)) {
void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
if (!uca) {
uwsgi.cheaper_algos = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
uca = uwsgi.cheaper_algos;
}
else {
while (uca) {
if (!uca) {
uwsgi.cheaper_algos = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
uca = uwsgi.cheaper_algos;
}
else {
while (uca) {
if (!uca->next) {
uca->next = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
uca = uca->next;
uca = uca->next;
break;
}
uca = uca->next;
}
uca = uca->next;
}
}
}
uca->name = name;
uca->func = func;
uca->next = NULL;
uca->name = name;
uca->func = func;
uca->next = NULL;
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-cheaper-algo] registered \"%s\"\n", uca->name);
uwsgi_log("[uwsgi-cheaper-algo] registered \"%s\"\n", uca->name);
#endif
}
void trigger_harakiri(int i) {
int j;
uwsgi_log("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri + 1);
if (uwsgi.harakiri_verbose) {
#ifdef __linux__
int proc_file;
char proc_buf[4096];
char proc_name[64];
ssize_t proc_len;
if (snprintf(proc_name, 64, "/proc/%d/syscall", uwsgi.workers[i].pid) > 0) {
memset(proc_buf, 0, 4096);
proc_file = open(proc_name, O_RDONLY);
if (proc_file >= 0) {
proc_len = read(proc_file, proc_buf, 4096);
if (proc_len > 0) {
uwsgi_log("HARAKIRI: -- syscall> %s", proc_buf);
}
close(proc_file);
}
}
if (snprintf(proc_name, 64, "/proc/%d/wchan", uwsgi.workers[i].pid) > 0) {
memset(proc_buf, 0, 4096);
proc_file = open(proc_name, O_RDONLY);
if (proc_file >= 0) {
proc_len = read(proc_file, proc_buf, 4096);
if (proc_len > 0) {
uwsgi_log("HARAKIRI: -- wchan> %s\n", proc_buf);
}
close(proc_file);
}
}
#endif
}
if (uwsgi.workers[i].pid > 0) {
for (j = 0; j < uwsgi.gp_cnt; j++) {
if (uwsgi.gp[j]->harakiri) {
uwsgi.gp[j]->harakiri(i);
}
}
for (j = 0; j < 256; j++) {
if (uwsgi.p[j]->harakiri) {
uwsgi.p[j]->harakiri(i);
}
}
kill(uwsgi.workers[i].pid, SIGUSR2);
// allow SIGUSR2 to be delivered
sleep(1);
kill(uwsgi.workers[i].pid, SIGKILL);
if (!uwsgi.workers[i].pending_harakiri)
uwsgi.workers[i].harakiri_count++;
uwsgi.workers[i].pending_harakiri++;
}
// to avoid races
}
+464
View File
@@ -0,0 +1,464 @@
/*
uWSGI mules are very simple workers only managing signals or running custom code in background.
By default they born in signal-only mode, but if you patch them (passing the script/code to run) they will became fully customized daemons.
*/
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_mule_handler(void);
void mule_send_msg(int fd, char *message, size_t len) {
socklen_t so_bufsize_len = sizeof(int);
int so_bufsize = 0;
if (write(fd, message, len) != (ssize_t) len) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** MULE MSG QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
}
else {
uwsgi_error("mule_send_msg()");
}
}
}
void uwsgi_mule(int id) {
int i;
pid_t pid = uwsgi_fork(uwsgi.mules[id - 1].name);
if (pid == 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
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);
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi.muleid = id;
// avoid race conditions
uwsgi.mules[id - 1].id = id;
uwsgi.mules[id - 1].pid = getpid();
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 < 256; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
if (uwsgi.mules[id - 1].patch) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
// never here
end_me(1);
}
}
}
}
uwsgi_mule_handler();
}
else if (pid > 0) {
uwsgi.mules[id - 1].id = id;
uwsgi.mules[id - 1].pid = pid;
uwsgi_log("spawned uWSGI mule %d (pid: %d)\n", id, (int) pid);
}
}
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
struct uwsgi_mule_farm *umf = farm->mules;
while (umf) {
if (umf->mule->id == muleid) {
return 1;
}
umf = umf->next;
}
return 0;
}
int farm_has_signaled(int fd) {
int i;
for (i = 0; i < uwsgi.farms_cnt; i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while (umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].signal_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
return 0;
}
int farm_has_msg(int fd) {
int i;
for (i = 0; i < uwsgi.farms_cnt; i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while (umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].queue_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
return 0;
}
void uwsgi_mule_add_farm_to_queue(int queue) {
int i;
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
event_queue_add_fd_read(queue, uwsgi.farms[i].signal_pipe[1]);
event_queue_add_fd_read(queue, uwsgi.farms[i].queue_pipe[1]);
}
}
}
void uwsgi_mule_handler() {
ssize_t len;
uint8_t uwsgi_signal;
int rlen;
int interesting_fd;
// this must be configurable
char message[65536];
int mule_queue = event_queue_init();
event_queue_add_fd_read(mule_queue, uwsgi.signal_socket);
event_queue_add_fd_read(mule_queue, uwsgi.my_signal_socket);
event_queue_add_fd_read(mule_queue, uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1]);
event_queue_add_fd_read(mule_queue, uwsgi.shared->mule_queue_pipe[1]);
uwsgi_mule_add_farm_to_queue(mule_queue);
for (;;) {
rlen = event_queue_wait(mule_queue, -1, &interesting_fd);
if (rlen <= 0) {
continue;
}
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
}
}
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
len = read(interesting_fd, message, 65536);
if (len < 0) {
uwsgi_error("read()");
}
else {
int i, found = 0;
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule_msg) {
if (uwsgi.p[i]->mule_msg(message, len)) {
found = 1;
break;
}
}
}
if (!found)
uwsgi_log("*** mule %d received a %d bytes message ***\n", uwsgi.muleid, len);
}
}
}
}
struct uwsgi_mule *get_mule_by_id(int id) {
int i;
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].id == id) {
return &uwsgi.mules[i];
}
}
return NULL;
}
struct uwsgi_farm *get_farm_by_name(char *name) {
int i;
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (!strcmp(uwsgi.farms[i].name, name)) {
return &uwsgi.farms[i];
}
}
return NULL;
}
struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **umf, struct uwsgi_mule *um) {
struct uwsgi_mule_farm *uwsgi_mf = *umf, *old_umf;
if (!uwsgi_mf) {
*umf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
uwsgi_mf = *umf;
}
else {
while (uwsgi_mf) {
old_umf = uwsgi_mf;
uwsgi_mf = uwsgi_mf->next;
}
uwsgi_mf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
old_umf->next = uwsgi_mf;
}
uwsgi_mf->mule = um;
uwsgi_mf->next = NULL;
return uwsgi_mf;
}
ssize_t uwsgi_mule_get_msg(int manage_signals, int manage_farms, char *message, size_t buffer_size, int timeout) {
ssize_t len = 0;
struct pollfd *mulepoll;
int count = 4;
int farms_count = 0;
uint8_t uwsgi_signal;
int i;
if (uwsgi.muleid == 0)
return -1;
if (manage_signals)
count = 2;
if (!manage_farms)
goto next;
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid))
farms_count++;
}
next:
if (timeout > -1)
timeout = timeout * 1000;
mulepoll = uwsgi_malloc(sizeof(struct pollfd) * (count + farms_count));
mulepoll[0].fd = uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1];
mulepoll[0].events = POLLIN;
mulepoll[1].fd = uwsgi.shared->mule_queue_pipe[1];
mulepoll[1].events = POLLIN;
if (count > 2) {
mulepoll[2].fd = uwsgi.signal_socket;
mulepoll[2].events = POLLIN;
mulepoll[3].fd = uwsgi.my_signal_socket;
mulepoll[3].events = POLLIN;
}
if (farms_count > 0) {
int tmp_cnt = 0;
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
mulepoll[count + tmp_cnt].fd = uwsgi.farms[i].queue_pipe[1];
mulepoll[count + tmp_cnt].events = POLLIN;
tmp_cnt++;
}
}
}
int ret = poll(mulepoll, count + farms_count, timeout);
if (ret <= 0) {
uwsgi_error("poll");
}
else {
if (mulepoll[0].revents & POLLIN) {
len = read(uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1], message, buffer_size);
}
else if (mulepoll[1].revents & POLLIN) {
len = read(uwsgi.shared->mule_queue_pipe[1], message, buffer_size);
}
else {
if (count > 2) {
int interesting_fd = -1;
if (mulepoll[2].revents & POLLIN) {
interesting_fd = mulepoll[2].fd;
}
else if (mulepoll[3].revents & POLLIN) {
interesting_fd = mulepoll[3].fd;
}
if (interesting_fd > -1) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
}
// set the error condition
len = -1;
goto clear;
}
}
// read messages in the farm
for (i = 0; i < farms_count; i++) {
if (mulepoll[count + i].revents & POLLIN) {
len = read(mulepoll[count + i].fd, message, buffer_size);
break;
}
}
}
}
if (len < 0) {
uwsgi_error("read()");
goto clear;
}
clear:
free(mulepoll);
return len;
}
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;
}
}
}
+13 -11
View File
@@ -16,7 +16,7 @@ void uwsgi_systemd_notify(char *message) {
iovec[1].iov_len = strlen(message);
iovec[2].iov_base = "\n";
iovec[2].iov_len = 1;
iovec[2].iov_len = 1;
msghdr->msg_iovlen = 3;
@@ -26,15 +26,15 @@ void uwsgi_systemd_notify(char *message) {
void uwsgi_systemd_notify_ready(void) {
struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
struct iovec *iovec = msghdr->msg_iov;
struct iovec *iovec = msghdr->msg_iov;
iovec[0].iov_base = "STATUS=uWSGI is ready\nREADY=1\n";
iovec[0].iov_len = 30;
iovec[0].iov_base = "STATUS=uWSGI is ready\nREADY=1\n";
iovec[0].iov_len = 30;
msghdr->msg_iovlen = 1;
sendmsg(uwsgi.notification_fd, msghdr, 0);
}
@@ -49,24 +49,26 @@ void uwsgi_systemd_init(char *systemd_socket) {
return;
}
size_t len = strlen(systemd_socket);
sd_sun = uwsgi_malloc(sizeof(struct sockaddr_un));
memset(sd_sun, 0, sizeof(struct sockaddr_un));
sd_sun->sun_family = AF_UNIX;
strncpy(sd_sun->sun_path, systemd_socket, sizeof(sd_sun->sun_path));
if (sd_sun->sun_path[0] == '@') sd_sun->sun_path[0] = 0;
strncpy(sd_sun->sun_path, systemd_socket, UMIN(len, sizeof(sd_sun->sun_path)));
if (sd_sun->sun_path[0] == '@')
sd_sun->sun_path[0] = 0;
msghdr = uwsgi_malloc(sizeof(struct msghdr));
memset(msghdr, 0, sizeof(struct msghdr));
msghdr->msg_iov = uwsgi_malloc(sizeof(struct iovec)*3);
memset(msghdr->msg_iov, 0, sizeof(struct iovec)*3);
msghdr->msg_iov = uwsgi_malloc(sizeof(struct iovec) * 3);
memset(msghdr->msg_iov, 0, sizeof(struct iovec) * 3);
msghdr->msg_name = sd_sun;
msghdr->msg_namelen = sizeof(struct sockaddr_un);
msghdr->msg_namelen = sizeof(struct sockaddr_un) - (sizeof(sd_sun->sun_path) - len);
uwsgi.notification_object = msghdr;
uwsgi.notify = uwsgi_systemd_notify;
uwsgi.notify_ready = uwsgi_systemd_notify_ready;
}
+389
View File
@@ -0,0 +1,389 @@
#include "uwsgi.h"
/*
uWSGI offloading subsystem
*/
extern struct uwsgi_server uwsgi;
#define uwsgi_offload_retry if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) return 0;
#define uwsgi_offload_0r_1w(x, y) if (event_queue_del_fd(ut->queue, x, event_queue_read())) return -1;\
if (event_queue_fd_read_to_write(ut->queue, y)) return -1;
static int uwsgi_offload_net_transfer(struct uwsgi_thread *, struct uwsgi_offload_request *, int);
static int uwsgi_offload_sendfile_transfer(struct uwsgi_thread *, struct uwsgi_offload_request *, int);
static void uwsgi_offload_setup(struct uwsgi_offload_request *uor, struct wsgi_request *wsgi_req,
int (*func)(struct uwsgi_thread *, struct uwsgi_offload_request *, int)) {
wsgi_req->fd_closed = 1;
memset(uor, 0, sizeof(struct uwsgi_offload_request));
uor->s = wsgi_req->poll.fd;
uor->func = func;
// put socket in non-blocking mode
uwsgi_socket_nb(uor->s);
}
static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
struct uwsgi_core *uc = &uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id];
uc->offloaded_requests++;
// round robin
if (uc->offload_rr >= uwsgi.offload_threads) {
uc->offload_rr = 0;
}
struct uwsgi_thread *ut = uwsgi.offload_thread[uc->offload_rr];
uc->offload_rr++;
if (write(ut->pipe[0], uor, sizeof(struct uwsgi_offload_request)) != sizeof(struct uwsgi_offload_request)) {
return -1;
}
return 0;
}
int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socket, struct uwsgi_buffer *ubuf) {
// fill offload request
struct uwsgi_offload_request uor;
uwsgi_offload_setup(&uor, wsgi_req, uwsgi_offload_net_transfer);
uor.fd = uwsgi_connect(socket, 0, 1);
if (uor.fd < 0) {
uwsgi_error("uwsgi_offload_request_net_do() -> connect()");
goto error;
}
uor.ubuf = ubuf;
if (uwsgi_offload_enqueue(wsgi_req, &uor)) {
goto error2;
}
return 0;
error2:
close(uor.fd);
error:
wsgi_req->fd_closed = 0;
return -1;
}
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, char *filename, size_t len) {
// fill offload request
struct uwsgi_offload_request uor;
uwsgi_offload_setup(&uor, wsgi_req, uwsgi_offload_sendfile_transfer);
uor.fd = open(filename, O_RDONLY | O_NONBLOCK);
if (uor.fd < 0) {
uwsgi_error_open(filename);
goto error;
}
// make a fstat to get the file size
if (!len) {
struct stat st;
if (fstat(uor.fd, &st)) {
uwsgi_error("fstat()");
goto error2;
}
len = st.st_size;
}
uor.len = len;
if (uwsgi_offload_enqueue(wsgi_req, &uor)) {
goto error2;
}
return 0;
error2:
close(uor.fd);
error:
wsgi_req->fd_closed = 0;
return -1;
}
static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
// close the socket and the file descriptor
close(uor->s);
close(uor->fd);
// remove the structure from the linked list;
struct uwsgi_offload_request *prev = uor->prev;
struct uwsgi_offload_request *next = uor->next;
if (uor == ut->offload_requests_head) {
ut->offload_requests_head = next;
}
if (uor == ut->offload_requests_tail) {
ut->offload_requests_tail = prev;
}
if (prev) {
prev->next = next;
}
if (next) {
next->prev = prev;
}
if (uor->buf) {
free(uor->buf);
}
if (uor->ubuf) {
uwsgi_buffer_destroy(uor->ubuf);
}
free(uor);
}
static void uwsgi_offload_append(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
if (!ut->offload_requests_head) {
ut->offload_requests_head = uor;
}
if (ut->offload_requests_tail) {
ut->offload_requests_tail->next = uor;
uor->prev = ut->offload_requests_tail;
}
ut->offload_requests_tail = uor;
}
static struct uwsgi_offload_request *uwsgi_offload_get_by_fd(struct uwsgi_thread *ut, int s) {
struct uwsgi_offload_request *uor = ut->offload_requests_head;
while (uor) {
if (uor->s == s || uor->fd == s) {
return uor;
}
uor = uor->next;
}
return NULL;
}
static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
int i;
void *events = event_queue_alloc(uwsgi.offload_threads_events);
for (;;) {
int nevents = event_queue_wait_multi(ut->queue, -1, events, uwsgi.offload_threads_events);
for (i = 0; i < nevents; i++) {
int interesting_fd = event_queue_interesting_fd(events, i);
if (interesting_fd == ut->pipe[1]) {
struct uwsgi_offload_request *uor = uwsgi_malloc(sizeof(struct uwsgi_offload_request));
ssize_t len = read(ut->pipe[1], uor, sizeof(struct uwsgi_offload_request));
if (len != sizeof(struct uwsgi_offload_request)) {
uwsgi_error("read()");
free(uor);
continue;
}
// start monitoring socket for write
if (uor->func(ut, uor, -1)) {
uwsgi_offload_close(ut, uor);
continue;
}
uwsgi_offload_append(ut, uor);
continue;
}
// get the task from the interesting fd
struct uwsgi_offload_request *uor = uwsgi_offload_get_by_fd(ut, interesting_fd);
if (!uor)
continue;
// run the hook
if (uor->func(ut, uor, interesting_fd)) {
uwsgi_offload_close(ut, uor);
}
}
}
}
struct uwsgi_thread *uwsgi_offload_thread_start() {
return uwsgi_thread_new(uwsgi_offload_loop);
}
/*
the offload task starts after having acquired the file fd
uor->len -> the size of the file
uor->pos -> start writing from pos (default 0)
status: none
*/
static int uwsgi_offload_sendfile_transfer(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
if (fd == -1) {
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
return 0;
}
#if defined(__linux__) || defined(__sun__)
ssize_t len = sendfile(uor->s, uor->fd, &uor->pos, 128 * 1024);
if (len > 0) {
uor->written += len;
if (uor->written >= uor->len) {
return -1;
}
return 0;
}
else if (len < 0) {
uwsgi_offload_retry
uwsgi_error("sendfile()");
}
#elif defined(__FreeBSD__) || defined(__DragonFly__)
off_t sbytes = 0;
int ret = sendfile(uor->fd, uor->s, uor->pos, 0, NULL, &sbytes, 0);
// transfer finished
if (ret == -1) {
uor->pos += sbytes;
uwsgi_offload_retry
uwsgi_error("sendfile()");
}
#elif defined(__APPLE__)
off_t len = 0;
int ret = sendfile(uor->fd, uor->s, uor->pos, &len, NULL, 0);
// transfer finished
if (ret == -1) {
uor->pos += len;
uwsgi_offload_retry
uwsgi_error("sendfile()");
}
#endif
return -1;
}
/*
the offload task starts soon after the call to connect()
status:
0 -> waiting for connection on fd
1 -> sending request to fd (write event)
2 -> start waiting for read on s and fd
3 -> write to s
4 -> write to fd
*/
static int uwsgi_offload_net_transfer(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
ssize_t rlen;
// setup
if (fd == -1) {
event_queue_add_fd_write(ut->queue, uor->fd);
return 0;
}
switch(uor->status) {
// waiting for connection
case 0:
if (fd == uor->fd) {
uor->status = 1;
// ok try to send the request right now...
return uwsgi_offload_net_transfer(ut, uor, fd);
}
return -1;
// write event (or just connected)
case 1:
if (fd == uor->fd) {
rlen = write(uor->fd, uor->ubuf->buf + uor->written, uor->ubuf->pos-uor->written);
if (rlen > 0) {
uor->written += rlen;
if (uor->written >= (size_t)uor->ubuf->pos) {
uor->status = 2;
if (event_queue_add_fd_read(ut->queue, uor->s)) return -1;
if (event_queue_fd_write_to_read(ut->queue, uor->fd)) return -1;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("uwsgi_offload_net_transfer() -> write()");
}
}
return -1;
// read event from s or fd
case 2:
if (!uor->buf) {
uor->buf = uwsgi_malloc(4096);
}
if (fd == uor->fd) {
rlen = read(uor->fd, uor->buf, 4096);
if (rlen > 0) {
uor->to_write = rlen;
uor->pos = 0;
uwsgi_offload_0r_1w(uor->fd, uor->s)
uor->status = 3;
return 0;
}
if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("uwsgi_offload_net_transfer() -> read()/fd");
}
}
else if (fd == uor->s) {
rlen = read(uor->s, uor->buf, 4096);
if (rlen > 0) {
uor->to_write = rlen;
uor->pos = 0;
uwsgi_offload_0r_1w(uor->s, uor->fd)
uor->status = 4;
return 0;
}
if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("uwsgi_offload_net_transfer() -> read()/s");
}
}
return -1;
// write event on s
case 3:
rlen = write(uor->s, uor->buf + uor->pos, uor->to_write);
if (rlen > 0) {
uor->to_write -= rlen;
uor->pos += rlen;
if (uor->to_write == 0) {
if (event_queue_fd_write_to_read(ut->queue, uor->s)) return -1;
if (event_queue_add_fd_read(ut->queue, uor->fd)) return -1;
uor->status = 2;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("uwsgi_offload_net_transfer() -> write()/s");
}
return -1;
// write event on fd
case 4:
rlen = write(uor->fd, uor->buf + uor->pos, uor->to_write);
if (rlen > 0) {
uor->to_write -= rlen;
uor->pos += rlen;
if (uor->to_write == 0) {
if (event_queue_fd_write_to_read(ut->queue, uor->fd)) return -1;
if (event_queue_add_fd_read(ut->queue, uor->s)) return -1;
uor->status = 2;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("uwsgi_offload_net_transfer() -> write()/fd");
}
return -1;
default:
break;
}
return -1;
}
+308
View File
@@ -0,0 +1,308 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_ELF
static void uwsgi_plugin_parse_section(char *filename) {
size_t s_len = 0;
char *buf = uwsgi_elf_section(filename, "uwsgi", &s_len);
if (buf) {
char *ctx = NULL;
char *p = strtok_r(buf, "\n", &ctx);
while (p) {
char *equal = strchr(p, '=');
if (equal) {
*equal = 0;
if (!strcmp(p, "requires")) {
uwsgi_load_plugin(-1, equal + 1, NULL);
}
}
p = strtok_r(NULL, "\n", &ctx);
}
free(buf);
}
}
#endif
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, '/')) {
#ifdef UWSGI_ELF
uwsgi_plugin_parse_section(plugin_name);
#endif
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);
#ifdef UWSGI_ELF
uwsgi_plugin_parse_section(plugin_filename);
#endif
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);
#ifdef UWSGI_ELF
uwsgi_plugin_parse_section(plugin_filename);
#endif
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("!!! UNABLE to load uWSGI plugin: %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;
}
File diff suppressed because it is too large Load Diff
+193
View File
@@ -0,0 +1,193 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_init_queue() {
if (!uwsgi.queue_blocksize)
uwsgi.queue_blocksize = 8192;
if ((uwsgi.queue_blocksize * uwsgi.queue_size) % uwsgi.page_size != 0) {
uwsgi_log("invalid queue size/blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.queue_blocksize, uwsgi.page_size);
exit(1);
}
if (uwsgi.queue_store) {
uwsgi.queue_filesize = uwsgi.queue_blocksize * uwsgi.queue_size + 16;
int queue_fd;
struct stat qst;
if (stat(uwsgi.queue_store, &qst)) {
uwsgi_log("creating a new queue store file: %s\n", uwsgi.queue_store);
queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (queue_fd >= 0) {
// fill the queue store
if (ftruncate(queue_fd, uwsgi.queue_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
if ((size_t) qst.st_size != uwsgi.queue_filesize || !S_ISREG(qst.st_mode)) {
uwsgi_log("invalid queue store file. Please remove it or fix queue blocksize/items to match its size\n");
exit(1);
}
queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
uwsgi_log("recovered queue from backing store file: %s\n", uwsgi.queue_store);
}
if (queue_fd < 0) {
uwsgi_error_open(uwsgi.queue_store);
exit(1);
}
uwsgi.queue = mmap(NULL, uwsgi.queue_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0);
// fix header
uwsgi.queue_header = uwsgi.queue;
uwsgi.queue += 16;
}
else {
uwsgi.queue = mmap(NULL, (uwsgi.queue_blocksize * uwsgi.queue_size) + 16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
// fix header
uwsgi.queue_header = uwsgi.queue;
uwsgi.queue += 16;
uwsgi.queue_header->pos = 0;
uwsgi.queue_header->pull_pos = 0;
}
if (!uwsgi.queue) {
uwsgi_error("mmap()");
exit(1);
}
uwsgi.queue_lock = uwsgi_rwlock_init("queue");
uwsgi_log("*** Queue subsystem initialized: %dMB preallocated ***\n", (uwsgi.queue_blocksize * uwsgi.queue_size) / (1024 * 1024));
}
char *uwsgi_queue_get(uint64_t index, uint64_t * size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (index >= uwsgi.queue_size)
return NULL;
ptr = ptr + (uwsgi.queue_blocksize * index);
uqi = (struct uwsgi_queue_item *) ptr;
*size = uqi->size;
return ptr + sizeof(struct uwsgi_queue_item);
}
char *uwsgi_queue_pop(uint64_t * size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (uwsgi.queue_header->pos == 0) {
uwsgi.queue_header->pos = uwsgi.queue_size - 1;
}
else {
uwsgi.queue_header->pos--;
}
ptr = ptr + (uwsgi.queue_blocksize * uwsgi.queue_header->pos);
uqi = (struct uwsgi_queue_item *) ptr;
if (!uqi->size)
return NULL;
*size = uqi->size;
// remove item
uqi->size = 0;
return ptr + sizeof(struct uwsgi_queue_item);
}
char *uwsgi_queue_pull(uint64_t * size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
ptr = ptr + (uwsgi.queue_blocksize * uwsgi.queue_header->pull_pos);
uqi = (struct uwsgi_queue_item *) ptr;
if (!uqi->size)
return NULL;
*size = uqi->size;
uwsgi.queue_header->pull_pos++;
if (uwsgi.queue_header->pull_pos >= uwsgi.queue_size)
uwsgi.queue_header->pull_pos = 0;
// remove item
uqi->size = 0;
return ptr + sizeof(struct uwsgi_queue_item);
}
int uwsgi_queue_push(char *message, uint64_t size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (!size)
return 0;
ptr = ptr + (uwsgi.queue_blocksize * uwsgi.queue_header->pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr += sizeof(struct uwsgi_queue_item);
uqi->size = size;
uqi->ts = uwsgi_now();
memcpy(ptr, message, size);
uwsgi.queue_header->pos++;
if (uwsgi.queue_header->pos >= uwsgi.queue_size)
uwsgi.queue_header->pos = 0;
return 1;
}
int uwsgi_queue_set(uint64_t pos, char *message, uint64_t size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (!size)
return 0;
if (pos >= uwsgi.queue_size)
return 0;
ptr = ptr + (uwsgi.queue_blocksize * pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr += sizeof(struct uwsgi_queue_item);
uqi->size = size;
uqi->ts = uwsgi_now();
memcpy(ptr, message, size);
return 1;
}
+367
View File
@@ -0,0 +1,367 @@
/*
uWSGI rbtree implementation based on nginx
Copyright (C) Igor Sysoev
Copyright (C) Nginx, Inc.
Copyright (C) Unbit S.a.s.
The red-black tree code is based on the algorithm described in
the "Introduction to Algorithms" by Cormen, Leiserson and Rivest.
*/
#include <uwsgi.h>
#define uwsgi_rbt_red(node) ((node)->color = 1)
#define uwsgi_rbt_black(node) ((node)->color = 0)
#define uwsgi_rbt_is_red(node) ((node)->color)
#define uwsgi_rbt_is_black(node) (!uwsgi_rbt_is_red(node))
#define uwsgi_rbt_copy_color(n1, n2) (n1->color = n2->color)
struct uwsgi_rbtree *uwsgi_init_rb_timer() {
struct uwsgi_rbtree *tree = uwsgi_calloc(sizeof(struct uwsgi_rbtree));
struct uwsgi_rb_timer *sentinel = uwsgi_calloc(sizeof(struct uwsgi_rb_timer));
// no need to set it black, calloc already did it
//uwsgi_rbt_black(sentinel);
tree->root = sentinel;
tree->sentinel = sentinel;
return tree;
}
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct uwsgi_rbtree *tree, struct uwsgi_rb_timer *node) {
if (!node)
node = tree->root;
struct uwsgi_rb_timer *sentinel = tree->sentinel;
if (tree->root == sentinel) return NULL;
while (node->left != sentinel) {
node = node->left;
}
return node;
}
static void uwsgi_rbtree_lr(struct uwsgi_rb_timer **root, struct uwsgi_rb_timer *sentinel, struct uwsgi_rb_timer *node) {
struct uwsgi_rb_timer *temp;
temp = node->right;
node->right = temp->left;
if (temp->left != sentinel) {
temp->left->parent = node;
}
temp->parent = node->parent;
if (node == *root) {
*root = temp;
}
else if (node == node->parent->left) {
node->parent->left = temp;
}
else {
node->parent->right = temp;
}
temp->left = node;
node->parent = temp;
}
static void uwsgi_rbtree_rr(struct uwsgi_rb_timer **root, struct uwsgi_rb_timer *sentinel, struct uwsgi_rb_timer *node) {
struct uwsgi_rb_timer *temp;
temp = node->left;
node->left = temp->right;
if (temp->right != sentinel) {
temp->right->parent = node;
}
temp->parent = node->parent;
if (node == *root) {
*root = temp;
}
else if (node == node->parent->right) {
node->parent->right = temp;
}
else {
node->parent->left = temp;
}
temp->right = node;
node->parent = temp;
}
static void uwsgi_rbt_add(struct uwsgi_rb_timer *temp, struct uwsgi_rb_timer *node, struct uwsgi_rb_timer *sentinel) {
struct uwsgi_rb_timer **p;
for (;;) {
p = (node->value < temp->value) ? &temp->left : &temp->right;
if (*p == sentinel)
break;
temp = *p;
}
*p = node;
node->parent = temp;
node->left = sentinel;
node->right = sentinel;
uwsgi_rbt_red(node);
}
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct uwsgi_rbtree *tree, uint64_t value, void *data) {
struct uwsgi_rb_timer *node = uwsgi_malloc(sizeof(struct uwsgi_rb_timer));
struct uwsgi_rb_timer *new_node = node;
node->value = value;
node->data = data;
struct uwsgi_rb_timer *temp = NULL;
/* a binary tree insert */
struct uwsgi_rb_timer **root = &tree->root;
struct uwsgi_rb_timer *sentinel = tree->sentinel;
if (*root == sentinel) {
node->parent = NULL;
node->left = sentinel;
node->right = sentinel;
uwsgi_rbt_black(node);
*root = node;
return new_node;
}
uwsgi_rbt_add(*root, node, sentinel);
/* re-balance tree */
while (node != *root && uwsgi_rbt_is_red(node->parent)) {
if (node->parent == node->parent->parent->left) {
temp = node->parent->parent->right;
if (uwsgi_rbt_is_red(temp)) {
uwsgi_rbt_black(node->parent);
uwsgi_rbt_black(temp);
uwsgi_rbt_red(node->parent->parent);
node = node->parent->parent;
}
else {
if (node == node->parent->right) {
node = node->parent;
uwsgi_rbtree_lr(root, sentinel, node);
}
uwsgi_rbt_black(node->parent);
uwsgi_rbt_red(node->parent->parent);
uwsgi_rbtree_rr(root, sentinel, node->parent->parent);
}
}
else {
temp = node->parent->parent->left;
if (uwsgi_rbt_is_red(temp)) {
uwsgi_rbt_black(node->parent);
uwsgi_rbt_black(temp);
uwsgi_rbt_red(node->parent->parent);
node = node->parent->parent;
}
else {
if (node == node->parent->left) {
node = node->parent;
uwsgi_rbtree_rr(root, sentinel, node);
}
uwsgi_rbt_black(node->parent);
uwsgi_rbt_red(node->parent->parent);
uwsgi_rbtree_lr(root, sentinel, node->parent->parent);
}
}
}
uwsgi_rbt_black(*root);
return new_node;
}
void uwsgi_del_rb_timer(struct uwsgi_rbtree *tree, struct uwsgi_rb_timer *node) {
uint8_t red;
struct uwsgi_rb_timer **root, *sentinel, *subst, *temp, *w;
/* a binary tree delete */
root = &tree->root;
sentinel = tree->sentinel;
if (node->left == sentinel) {
temp = node->right;
subst = node;
}
else if (node->right == sentinel) {
temp = node->left;
subst = node;
}
else {
subst = uwsgi_min_rb_timer(tree, node->right);
if (subst->left != sentinel) {
temp = subst->left;
}
else {
temp = subst->right;
}
}
if (subst == *root) {
*root = temp;
uwsgi_rbt_black(temp);
return;
}
red = uwsgi_rbt_is_red(subst);
if (subst == subst->parent->left) {
subst->parent->left = temp;
}
else {
subst->parent->right = temp;
}
if (subst == node) {
temp->parent = subst->parent;
}
else {
if (subst->parent == node) {
temp->parent = subst;
}
else {
temp->parent = subst->parent;
}
subst->left = node->left;
subst->right = node->right;
subst->parent = node->parent;
uwsgi_rbt_copy_color(subst, node);
if (node == *root) {
*root = subst;
}
else {
if (node == node->parent->left) {
node->parent->left = subst;
}
else {
node->parent->right = subst;
}
}
if (subst->left != sentinel) {
subst->left->parent = subst;
}
if (subst->right != sentinel) {
subst->right->parent = subst;
}
}
if (red) {
return;
}
/* a delete fixup */
while (temp != *root && uwsgi_rbt_is_black(temp)) {
if (temp == temp->parent->left) {
w = temp->parent->right;
if (uwsgi_rbt_is_red(w)) {
uwsgi_rbt_black(w);
uwsgi_rbt_red(temp->parent);
uwsgi_rbtree_lr(root, sentinel, temp->parent);
w = temp->parent->right;
}
if (uwsgi_rbt_is_black(w->left) && uwsgi_rbt_is_black(w->right)) {
uwsgi_rbt_red(w);
temp = temp->parent;
}
else {
if (uwsgi_rbt_is_black(w->right)) {
uwsgi_rbt_black(w->left);
uwsgi_rbt_red(w);
uwsgi_rbtree_rr(root, sentinel, w);
w = temp->parent->right;
}
uwsgi_rbt_copy_color(w, temp->parent);
uwsgi_rbt_black(temp->parent);
uwsgi_rbt_black(w->right);
uwsgi_rbtree_lr(root, sentinel, temp->parent);
temp = *root;
}
}
else {
w = temp->parent->left;
if (uwsgi_rbt_is_red(w)) {
uwsgi_rbt_black(w);
uwsgi_rbt_red(temp->parent);
uwsgi_rbtree_rr(root, sentinel, temp->parent);
w = temp->parent->left;
}
if (uwsgi_rbt_is_black(w->left) && uwsgi_rbt_is_black(w->right)) {
uwsgi_rbt_red(w);
temp = temp->parent;
}
else {
if (uwsgi_rbt_is_black(w->left)) {
uwsgi_rbt_black(w->right);
uwsgi_rbt_red(w);
uwsgi_rbtree_lr(root, sentinel, w);
w = temp->parent->left;
}
uwsgi_rbt_copy_color(w, temp->parent);
uwsgi_rbt_black(temp->parent);
uwsgi_rbt_black(w->left);
uwsgi_rbtree_rr(root, sentinel, temp->parent);
temp = *root;
}
}
}
uwsgi_rbt_black(temp);
}
+110
View File
@@ -0,0 +1,110 @@
#ifdef UWSGI_PCRE
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_opt_pcre_jit(char *opt, char *value, void *foobar) {
#if defined(PCRE_STUDY_JIT_COMPILE) && defined(PCRE_CONFIG_JIT)
int has_jit = 0, ret;
ret = pcre_config(PCRE_CONFIG_JIT, &has_jit);
if (ret != 0 || has_jit != 1)
return;
uwsgi.pcre_jit = PCRE_STUDY_JIT_COMPILE;
#endif
}
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;
}
int opt = uwsgi.pcre_jit;
*pattern_extra = (pcre_extra *) pcre_study((const pcre *) *pattern, opt, &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;
size_t dollars = n;
for(i=0;i<dst_n;i++) {
if (dst[i] == '$') {
dollars++;
}
}
char *res = uwsgi_malloc(dst_n + (src_n * dollars) + 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++ = '$';
*ptr++ = dst[i];
}
dollar = 0;
}
else {
if (dst[i] == '$') {
dollar = 1;
}
else {
*ptr++ = dst[i];
}
}
}
*ptr++ = 0;
return res;
}
#endif
+30 -26
View File
@@ -7,21 +7,23 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
struct uwsgi_route *routes = uwsgi.routes;
if (!routes) return UWSGI_ROUTE_CONTINUE;
if (!routes)
return UWSGI_ROUTE_CONTINUE;
if (uwsgi_parse_vars(wsgi_req)) {
return UWSGI_ROUTE_BREAK;
}
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);
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) {
if (n >= 0) {
int ret = routes->func(wsgi_req, routes);
if (ret == UWSGI_ROUTE_BREAK) uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].routed_requests++;
if (ret != UWSGI_ROUTE_NEXT) {
return ret;
}
@@ -34,23 +36,25 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
int uwsgi_apply_routes_fast(struct wsgi_request *wsgi_req, char *uri, int len) {
struct uwsgi_route *routes = uwsgi.routes;
struct uwsgi_route *routes = uwsgi.routes;
if (!routes) return UWSGI_ROUTE_CONTINUE;
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) {
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_BREAK) uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].routed_requests++;
if (ret != UWSGI_ROUTE_NEXT) {
return ret;
}
}
}
routes = routes->next;
}
routes = routes->next;
}
return UWSGI_ROUTE_CONTINUE;
return UWSGI_ROUTE_CONTINUE;
}
@@ -72,9 +76,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
ur = uwsgi.routes;
}
else {
while(ur) {
while (ur) {
if (!ur->next) {
ur->next = uwsgi_calloc(sizeof(struct uwsgi_route));
ur->next = uwsgi_calloc(sizeof(struct uwsgi_route));
ur = ur->next;
break;
}
@@ -105,10 +109,10 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
ur->ovn = uwsgi_regexp_ovector(ur->pattern, ur->pattern_extra);
if (ur->ovn > 0) {
ur->ovector = uwsgi_calloc(sizeof(int) * (3 * (ur->ovn + 1)) );
ur->ovector = uwsgi_calloc(sizeof(int) * (3 * (ur->ovn + 1)));
}
char *command = space+1;
char *command = space + 1;
char *colon = strchr(command, ':');
if (!colon) {
@@ -119,17 +123,17 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
*colon = 0;
struct uwsgi_router *r = uwsgi.routers;
while(r) {
while (r) {
if (!strcmp(r->name, command)) {
if (r->func(ur, colon+1) == 0) {
if (r->func(ur, colon + 1) == 0) {
// apply is_last
struct uwsgi_route *last_ur = ur;
ur = uwsgi.routes;
while(ur) {
while (ur) {
if (ur->func == last_ur->func) {
ur->is_last = 0;
}
ur = ur->next;
ur = ur->next;
}
last_ur->is_last = 1;
return;
@@ -142,7 +146,7 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
exit(1);
}
struct uwsgi_router *uwsgi_register_router(char *name, int (*func)(struct uwsgi_route *, char *)) {
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
struct uwsgi_router *ur = uwsgi.routers;
if (!ur) {
@@ -152,7 +156,7 @@ struct uwsgi_router *uwsgi_register_router(char *name, int (*func)(struct uwsgi_
return uwsgi.routers;
}
while(ur) {
while (ur) {
if (!ur->next) {
ur->next = uwsgi_calloc(sizeof(struct uwsgi_router));
ur->next->name = name;
+41 -40
View File
@@ -16,7 +16,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
if (uwsgi.shared->rpc_count < MAX_RPC) {
urpc = &uwsgi.shared->rpc_table[uwsgi.shared->rpc_count];
memcpy(urpc->name, name, strlen(name));
urpc->modifier1 = modifier1;
urpc->args = args;
@@ -39,7 +39,7 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
int i;
uint16_t ret = 0;
for(i=0;i<uwsgi.shared->rpc_count;i++) {
for (i = 0; i < uwsgi.shared->rpc_count; i++) {
if (uwsgi.shared->rpc_table[i].name[0] != 0) {
if (!strcmp(uwsgi.shared->rpc_table[i].name, name)) {
urpc = &uwsgi.shared->rpc_table[i];
@@ -58,71 +58,72 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
}
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t *len) {
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
uint8_t i;
uint16_t ulen;
struct uwsgi_header uh;
char *buffer = NULL;
*len = 0;
if (node == NULL || !strcmp(node, "")) {
if (node == NULL || !strcmp(node, "")) {
// allocate the whole buffer
buffer = uwsgi_malloc(65536);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
return buffer;
}
}
// connect to node
int fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
int fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) return NULL;
if (fd < 0)
return NULL;
// prepare a uwsgi array
// prepare a uwsgi array
uint16_t buffer_size = 2 + strlen(func);
for (i = 0; i < argc; i++) {
buffer_size += 2 + argvs[i];
}
for (i = 0; i < argc; i++) {
buffer_size += 2 + argvs[i];
}
// allocate the whole buffer
buffer = uwsgi_malloc(65536);
uh.modifier1 = 173;
uh.pktsize = buffer_size;
uh.modifier2 = 0;
uh.modifier1 = 173;
uh.pktsize = buffer_size;
uh.modifier2 = 0;
// add func to the array
char *bufptr = buffer;
ulen = strlen(func);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, func, ulen);
bufptr += ulen;
char *bufptr = buffer;
ulen = strlen(func);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, func, ulen);
bufptr += ulen;
for (i = 0; i < argc; i++) {
ulen = argvs[i];
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, argv[i], ulen);
bufptr += ulen;
}
for (i = 0; i < argc; i++) {
ulen = argvs[i];
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, argv[i], ulen);
bufptr += ulen;
}
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
close(fd);
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
close(fd);
free(buffer);
return NULL;
}
return NULL;
}
if (write(fd, buffer, buffer_size) != buffer_size) {
uwsgi_error("write()");
close(fd);
if (write(fd, buffer, buffer_size) != buffer_size) {
uwsgi_error("write()");
close(fd);
free(buffer);
return NULL;
}
return NULL;
}
if (uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buffer) < 0) {
close(fd);
@@ -131,7 +132,7 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
}
close(fd);
*len = uh.pktsize;
if (*len == 0) {
free(buffer);
+22 -15
View File
@@ -1,10 +1,8 @@
#ifdef UWSGI_SENDFILE
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
ssize_t uwsgi_sendfile(struct wsgi_request *wsgi_req) {
ssize_t uwsgi_sendfile(struct wsgi_request * wsgi_req) {
int fd = wsgi_req->sendfile_fd;
int sockfd = wsgi_req->poll.fd;
@@ -24,10 +22,11 @@ ssize_t uwsgi_sendfile(struct wsgi_request *wsgi_req) {
if (wsgi_req->sendfile_fd_size) {
if (!wsgi_req->sendfile_fd_chunk) wsgi_req->sendfile_fd_chunk = 4096;
if (!wsgi_req->sendfile_fd_chunk)
wsgi_req->sendfile_fd_chunk = 4096;
if (wsgi_req->socket->proto_sendfile) {
sst = wsgi_req->socket->proto_sendfile(wsgi_req);
sst = wsgi_req->socket->proto_sendfile(wsgi_req);
}
else {
sst = uwsgi_do_sendfile(sockfd, wsgi_req->sendfile_fd, wsgi_req->sendfile_fd_size, wsgi_req->sendfile_fd_chunk, &wsgi_req->sendfile_fd_pos, uwsgi.async);
@@ -39,7 +38,7 @@ end:
return sst;
}
ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk, off_t *pos, int async) {
ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk, off_t * pos, int async) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
@@ -89,20 +88,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;
@@ -163,5 +172,3 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
#endif
}
#endif
+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);
}
}
}
+603
View File
@@ -0,0 +1,603 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
int uwsgi_signal_handler(uint8_t sig) {
struct uwsgi_signal_entry *use = NULL;
use = &uwsgi.shared->signal_table[sig];
if (!use->handler)
return -1;
if (!uwsgi.p[use->modifier1]->signal_handler) {
return -1;
}
// check for COW
if (uwsgi.master_process) {
if (use->wid != 0 && use->wid != uwsgi.mywid) {
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
return -1;
}
}
// in lazy mode (without a master), only the same worker will be able to run handlers
else if (uwsgi.lazy) {
if (use->wid != uwsgi.mywid) {
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
return -1;
}
}
else {
// when master is not active, worker1 is the COW-leader
if (use->wid != 1 && use->wid != uwsgi.mywid) {
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
return -1;
}
}
// set harakiri here (if required and if i am a worker)
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].sig = 1;
uwsgi.workers[uwsgi.mywid].signum = sig;
uwsgi.workers[uwsgi.mywid].signals++;
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
}
else if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid - 1].sig = 1;
uwsgi.mules[uwsgi.muleid - 1].signum = sig;
uwsgi.mules[uwsgi.muleid - 1].signals++;
if (uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.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]);
}
}
#endif
int ret = uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].sig = 0;
if (uwsgi.workers[uwsgi.mywid].harakiri > 0) {
set_harakiri(0);
}
}
else if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid - 1].sig = 0;
if (uwsgi.mules[uwsgi.muleid - 1].harakiri > 0) {
set_mule_harakiri(0);
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
}
#endif
return ret;
}
int uwsgi_signal_registered(uint8_t sig) {
if (uwsgi.shared->signal_table[sig].handler != NULL)
return 1;
return 0;
}
int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t modifier1) {
struct uwsgi_signal_entry *use = NULL;
if (strlen(receiver) > 63)
return -1;
uwsgi_lock(uwsgi.signal_table_lock);
use = &uwsgi.shared->signal_table[sig];
if (use->handler) {
uwsgi_log("[uwsgi-signal] you cannot re-register a signal !!!\n");
uwsgi_unlock(uwsgi.signal_table_lock);
return -1;
}
strncpy(use->receiver, receiver, strlen(receiver) + 1);
use->handler = handler;
use->modifier1 = modifier1;
use->wid = uwsgi.mywid;
if (use->receiver[0] == 0) {
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: default, any worker)\n", sig, uwsgi.mywid, modifier1);
}
else {
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: %s)\n", sig, uwsgi.mywid, modifier1, receiver);
}
uwsgi_unlock(uwsgi.signal_table_lock);
return 0;
}
int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
if (strlen(filename) > (0xff - 1)) {
uwsgi_log("uwsgi_add_file_monitor: invalid filename length\n");
return -1;
}
uwsgi_lock(uwsgi.fmon_table_lock);
if (ushared->files_monitored_cnt < 64) {
// fill the fmon table, the master will use it to add items to the event queue
memcpy(ushared->files_monitored[ushared->files_monitored_cnt].filename, filename, strlen(filename));
ushared->files_monitored[ushared->files_monitored_cnt].registered = 0;
ushared->files_monitored[ushared->files_monitored_cnt].sig = sig;
ushared->files_monitored_cnt++;
}
else {
uwsgi_log("you can register max 64 file monitors !!!\n");
uwsgi_unlock(uwsgi.fmon_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.fmon_table_lock);
return 0;
}
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_up = *up, *old_up;
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while (uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
return uwsgi_up;
}
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
uwsgi_lock(uwsgi.probe_table_lock);
if (ushared->probes_cnt < MAX_PROBES) {
struct uwsgi_probe *up = uwsgi.probes;
while (up) {
if (!strcmp(up->name, kind)) {
break;
}
up = up->next;
}
if (!up) {
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
ushared->probes[ushared->probes_cnt].fd = -1;
ushared->probes[ushared->probes_cnt].state = 0;
ushared->probes[ushared->probes_cnt].last_event = 0;
ushared->probes[ushared->probes_cnt].data = NULL;
ushared->probes[ushared->probes_cnt].cycles = 0;
ushared->probes[ushared->probes_cnt].bad = 0;
if (!timeout) {
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
ushared->probes[ushared->probes_cnt].timeout = timeout;
if (!freq) {
freq = 1;
}
ushared->probes[ushared->probes_cnt].freq = freq;
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.probe_table_lock);
return 0;
}
int uwsgi_add_timer(uint8_t sig, int secs) {
uwsgi_lock(uwsgi.timer_table_lock);
if (ushared->timers_cnt < 64) {
// fill the timer table, the master will use it to add items to the event queue
ushared->timers[ushared->timers_cnt].value = secs;
ushared->timers[ushared->timers_cnt].registered = 0;
ushared->timers[ushared->timers_cnt].sig = sig;
ushared->timers_cnt++;
}
else {
uwsgi_log("you can register max 64 timers !!!\n");
uwsgi_unlock(uwsgi.timer_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.timer_table_lock);
return 0;
}
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) {
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
}
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) {
// fill the timer table, the master will use it to add items to the event queue
ushared->rb_timers[ushared->rb_timers_cnt].value = secs;
ushared->rb_timers[ushared->rb_timers_cnt].registered = 0;
ushared->rb_timers[ushared->rb_timers_cnt].iterations = iterations;
ushared->rb_timers[ushared->rb_timers_cnt].iterations_done = 0;
ushared->rb_timers[ushared->rb_timers_cnt].sig = sig;
ushared->rb_timers_cnt++;
}
else {
uwsgi_log("you can register max 64 rb_timers !!!\n");
uwsgi_unlock(uwsgi.rb_timer_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.rb_timer_table_lock);
return 0;
}
void create_signal_pipe(int *sigpipe) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sigpipe)) {
uwsgi_error("socketpair()\n");
exit(1);
}
uwsgi_socket_nb(sigpipe[0]);
uwsgi_socket_nb(sigpipe[1]);
if (uwsgi.signal_bufsize) {
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
}
}
int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
struct uwsgi_header uh;
uh.modifier1 = 110;
uh.pktsize = 0;
uh.modifier2 = sig;
int fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0)
return -1;
if (write(fd, (char *) &uh, 4) != 4) {
uwsgi_error("uwsgi_remote_signal_send()");
close(fd);
return -1;
}
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL);
close(fd);
return ret;
}
int uwsgi_signal_send(int fd, uint8_t sig) {
socklen_t so_bufsize_len = sizeof(int);
int so_bufsize = 0;
if (write(fd, &sig, 1) != 1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** SIGNAL QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
}
else {
uwsgi_error("uwsgi_signal_send()");
}
return -1;
}
return 0;
}
void uwsgi_route_signal(uint8_t sig) {
struct uwsgi_signal_entry *use = &ushared->signal_table[sig];
int i;
// send to first available worker
if (use->receiver[0] == 0 || !strcmp(use->receiver, "worker") || !strcmp(use->receiver, "worker0")) {
if (uwsgi_signal_send(ushared->worker_signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to workers pool\n", sig);
}
}
// send to all workers
else if (!strcmp(use->receiver, "workers")) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
}
}
// route to specific worker
else if (!strncmp(use->receiver, "worker", 6)) {
i = atoi(use->receiver + 6);
if (i > uwsgi.numproc) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
}
// route to subscribed
else if (!strcmp(use->receiver, "subscribed")) {
}
// route to spooler
#ifdef UWSGI_SPOOLER
else if (!strcmp(use->receiver, "spooler")) {
if (ushared->worker_signal_pipe[0] != -1) {
if (uwsgi_signal_send(ushared->spooler_signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to the spooler\n", sig);
}
}
}
#endif
else if (!strcmp(use->receiver, "mules")) {
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi_signal_send(uwsgi.mules[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i + 1);
}
}
}
else if (!strncmp(use->receiver, "mule", 4)) {
i = atoi(use->receiver + 4);
if (i > uwsgi.mules_cnt) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
else if (i == 0) {
if (uwsgi_signal_send(ushared->mule_signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to a mule\n", sig);
}
}
else {
if (uwsgi_signal_send(uwsgi.mules[i - 1].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i);
}
}
}
else if (!strncmp(use->receiver, "farm_", 5)) {
char *name = use->receiver + 5;
struct uwsgi_farm *uf = get_farm_by_name(name);
if (!uf) {
uwsgi_log("unknown farm: %s\n", name);
return;
}
if (uwsgi_signal_send(uf->signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, uf->id, uf->name);
}
}
else if (!strncmp(use->receiver, "farm", 4)) {
i = atoi(use->receiver + 4);
if (i > uwsgi.farms_cnt || i <= 0) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
else {
if (uwsgi_signal_send(uwsgi.farms[i - 1].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, i, uwsgi.farms[i - 1].name);
}
}
}
else {
// unregistered signal, sending it to all the workers
uwsgi_log("^^^ UNSUPPORTED SIGNAL TARGET: %s ^^^\n", use->receiver);
}
}
int uwsgi_signal_wait(int signum) {
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
int received_signal = -1;
int ret;
struct pollfd pfd[2];
if (signum > -1) {
wait_for_specific_signal = 1;
}
pfd[0].fd = uwsgi.signal_socket;
pfd[0].events = POLLIN;
pfd[1].fd = uwsgi.my_signal_socket;
pfd[1].events = POLLIN;
cycle:
ret = poll(pfd, 2, -1);
if (ret > 0) {
if (pfd[0].revents == POLLIN) {
if (read(uwsgi.signal_socket, &uwsgi_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void) uwsgi_signal_handler(uwsgi_signal);
if (wait_for_specific_signal) {
if (signum != uwsgi_signal)
goto cycle;
}
received_signal = uwsgi_signal;
}
}
if (pfd[1].revents == POLLIN) {
if (read(uwsgi.my_signal_socket, &uwsgi_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void) uwsgi_signal_handler(uwsgi_signal);
if (wait_for_specific_signal) {
if (signum != uwsgi_signal)
goto cycle;
}
}
received_signal = uwsgi_signal;
}
}
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
+102 -58
View File
@@ -249,11 +249,14 @@ static uint64_t get_uwsgi_snmp_value(uint64_t val, uint8_t * oid_t) {
static uint64_t get_uwsgi_custom_snmp_value(uint64_t val, uint8_t * oid_t) {
val--;
uwsgi_wlock(uwsgi.snmp_lock);
if (uwsgi.shared->snmp_value[val].type) {
*oid_t = uwsgi.shared->snmp_value[val].type;
uwsgi_rwunlock(uwsgi.snmp_lock);
return uwsgi.shared->snmp_value[val].val;
}
uwsgi_rwunlock(uwsgi.snmp_lock);
*oid_t = SNMP_NULL;
return 0;
}
@@ -278,91 +281,132 @@ static int get_snmp_integer(uint8_t * ptr, uint64_t * val) {
#ifdef __BIG_ENDIAN__
for (i = 0; i < tlen; i++) {
#else
for (i = tlen - 1; i >= 0; i--) {
for (i = tlen - 1; i >= 0; i--) {
#endif
cval[j] = ptr[1 + i];
j++;
}
return tlen + 1;
cval[j] = ptr[1 + i];
j++;
}
static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * buffer) {
uint8_t tlen;
int i, j;
uint8_t *ptr = (uint8_t *) &snmp_val;
return tlen + 1;
}
// check for counter, counter64 or gauge
static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * buffer) {
uint8_t tlen;
int i, j;
uint8_t *ptr = (uint8_t *) & snmp_val;
if (oid_type == SNMP_COUNTER64) {
tlen = 8;
}
else if (oid_type == SNMP_NULL || oid_type == 0) {
tlen = 0;
}
else {
tlen = 4;
}
// check for counter, counter64 or gauge
buffer[0] = tlen;
if (oid_type == SNMP_COUNTER64) {
tlen = 8;
}
else if (oid_type == SNMP_NULL || oid_type == 0) {
tlen = 0;
}
else {
tlen = 4;
}
j = 1;
buffer[0] = tlen;
j = 1;
#ifdef __BIG_ENDIAN__
for (i = 0; i < tlen; i++) {
for (i = 0; i < tlen; i++) {
#else
for (i = tlen - 1; i >= 0; i--) {
for (i = tlen - 1; i >= 0; i--) {
#endif
buffer[j] = ptr[i];
j++;
}
buffer[j] = ptr[i];
j++;
}
return tlen + 1;
}
return tlen + 1;
}
static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
uint64_t snmp_val;
uint8_t oid_sz;
uint8_t oid_type;
static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
uint64_t snmp_val;
uint8_t oid_sz;
uint8_t oid_type;
if (oid1 == 1) {
snmp_val = get_uwsgi_snmp_value(oid2, &oid_type);
}
else if (oid1 == 2) {
snmp_val = get_uwsgi_custom_snmp_value(oid2, &oid_type);
}
else {
return -1;
}
if (oid1 == 1) {
snmp_val = get_uwsgi_snmp_value(oid2, &oid_type);
}
else if (oid1 == 2) {
snmp_val = get_uwsgi_custom_snmp_value(oid2, &oid_type);
}
else {
return -1;
}
buffer[size - 2] = oid_type;
oid_sz = snmp_int_to_snmp(snmp_val, oid_type, buffer + (size - 1));
buffer[size - 2] = oid_type;
oid_sz = snmp_int_to_snmp(snmp_val, oid_type, buffer + (size - 1));
if (oid_sz < 1)
return -1;
if (oid_sz < 1)
return -1;
oid_sz--;
oid_sz--;
buffer[1] += oid_sz;
*seq1 += oid_sz;
*seq2 += oid_sz;
*seq3 += oid_sz;
buffer[1] += oid_sz;
*seq1 += oid_sz;
*seq2 += oid_sz;
*seq3 += oid_sz;
return size + oid_sz;
return size + oid_sz;
}
}
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
uwsgi.snmp = 1;
if (value) {
uwsgi.snmp_addr = optarg;
uwsgi.master_process = 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;
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 ***"
+755 -237
View File
File diff suppressed because it is too large Load Diff
+151 -110
View File
@@ -13,24 +13,31 @@ static void spooler_manage_task(struct uwsgi_spooler *, char *, char *);
static uint64_t wakeup = 0;
// function to allow waking up the spooler if blocked in event_wait
void spooler_wakeup() { wakeup++; }
void spooler_wakeup() {
wakeup++;
}
void uwsgi_opt_add_spooler(char *opt, char *directory, void *none) {
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 (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++) {
uwsgi_new_spooler(directory);
for (i = 0; i < uwsgi.spooler_numproc; i++) {
us = uwsgi_new_spooler(directory);
if (mode)
us->mode = (long) mode;
}
}
else {
uwsgi_new_spooler(directory);
us = uwsgi_new_spooler(directory);
if (mode)
us->mode = (long) mode;
}
}
@@ -38,31 +45,31 @@ void uwsgi_opt_add_spooler(char *opt, char *directory, void *none) {
struct uwsgi_spooler *uwsgi_new_spooler(char *dir) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
struct uwsgi_spooler *uspool = uwsgi.spoolers;
if (!uspool) {
uwsgi.spoolers = uwsgi_malloc_shared(sizeof(struct uwsgi_spooler));
uspool = uwsgi.spoolers;
}
else {
while(uspool) {
if (uspool->next == NULL) {
uspool->next = uwsgi_malloc_shared(sizeof(struct uwsgi_spooler));
uspool = uspool->next;
break;
}
uspool = uspool->next;
}
}
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);
}
if (!realpath(dir, uspool->dir)) {
uwsgi_error("[spooler] realpath()");
exit(1);
}
uspool->next = NULL;
uspool->next = NULL;
return uspool;
return uspool;
}
@@ -70,18 +77,18 @@ struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while(uspool) {
while (uspool) {
if (!strcmp(uspool->dir, name)) {
return uspool;
}
uspool = uspool->next;
}
return NULL;
}
pid_t spooler_start(struct uwsgi_spooler *uspool) {
pid_t spooler_start(struct uwsgi_spooler * uspool) {
int i;
pid_t pid = uwsgi_fork("uWSGI spooler");
@@ -90,8 +97,18 @@ pid_t spooler_start(struct uwsgi_spooler *uspool) {
exit(1);
}
else if (pid == 0) {
signal(SIGALRM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
signal(SIGTERM, end_me);
// USR1 will be used to wake up the spooler
uwsgi_unix_signal(SIGUSR1, spooler_wakeup);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi.mywid = -1;
uwsgi.mypid = getpid();
uspool->pid = uwsgi.mypid;
@@ -101,25 +118,25 @@ pid_t spooler_start(struct uwsgi_spooler *uspool) {
uwsgi_fixup_fds(0, 0, NULL);
uwsgi_close_all_sockets();
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
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 < 0xFF; i++) {
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
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();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->spooler_init) {
uwsgi.gp[i]->spooler_init();
}
}
spooler(uspool);
}
@@ -134,14 +151,14 @@ 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");
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);
uwsgi_error("unlink()");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
}
@@ -191,7 +208,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
// 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
// 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);
@@ -214,8 +231,8 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
}
if (body && body_len > 0) {
if ((size_t)write(fd, body, body_len) != body_len) {
goto clear;
if ((size_t) write(fd, body, body_len) != body_len) {
goto clear;
}
}
@@ -237,8 +254,9 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
// here the file will be unlocked too
close(fd);
uwsgi_log("[spooler] written %d bytes to file %s\n", size + body_len + 4, filename);
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);
@@ -248,7 +266,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
*/
struct uwsgi_spooler *spoolers = uwsgi.spoolers;
while(spoolers) {
while (spoolers) {
if (!strcmp(spoolers->dir, uspool->dir)) {
if (spoolers->pid > 0 && spoolers->running == 0) {
(void) kill(spoolers->pid, SIGUSR1);
@@ -260,7 +278,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
return 1;
clear:
clear:
uwsgi_unlock(uspool->lock);
uwsgi_error("write()");
if (unlink(filename)) {
@@ -309,6 +327,9 @@ void spooler(struct uwsgi_spooler *uspool) {
event_queue_add_fd_read(spooler_event_queue, uwsgi.shared->spooler_signal_pipe[1]);
}
// reset the tasks counter
uspool->tasks = 0;
for (;;) {
@@ -336,19 +357,7 @@ void spooler(struct uwsgi_spooler *uspool) {
if (event_queue_wait(spooler_event_queue, timeout, &interesting_fd) > 0) {
if (uwsgi.master_process) {
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[1]) {
uint8_t uwsgi_signal;
if (read(interesting_fd, &uwsgi_signal, 1) <= 0) {
uwsgi_log_verbose("uWSGI spooler screams: UAAAAAAH my master died, i will follow him...\n");
end_me(0);
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to the spooler\n", uwsgi_signal);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on the spooler\n", uwsgi_signal);
}
}
uwsgi_receive_signal(interesting_fd, "spooler", (int) getpid());
}
}
}
@@ -369,17 +378,18 @@ static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
struct dirent **tasklist;
int n;
if (!dir) dir = uspool->dir;
if (!dir)
dir = uspool->dir;
n = scandir(dir, &tasklist, 0, versionsort);
if (n < 0) {
uwsgi_error("scandir()");
return;
}
while(n--) {
while (n--) {
spooler_manage_task(uspool, dir, tasklist[n]->d_name);
free(tasklist[n]);
free(tasklist[n]);
}
free(tasklist);
@@ -392,7 +402,8 @@ static void spooler_readdir(struct uwsgi_spooler *uspool, char *dir) {
DIR *sdir;
struct dirent *dp;
if (!dir) dir = uspool->dir;
if (!dir)
dir = uspool->dir;
sdir = opendir(dir);
if (sdir) {
@@ -417,7 +428,8 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
int spool_fd;
if (!dir) dir = uspool->dir;
if (!dir)
dir = uspool->dir;
if (!strncmp("uwsgi_spoolfile_on_", task, 19) || (uwsgi.spooler_ordered && is_a_number(task))) {
struct stat sf_lstat;
@@ -426,7 +438,7 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
}
// a spool request for the future
if (sf_lstat.st_mtime > time(NULL)) {
if (sf_lstat.st_mtime > uwsgi_now()) {
return;
}
@@ -453,20 +465,30 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
spool_fd = open(task, O_RDWR);
if (spool_fd < 0) {
uwsgi_error_open(task);
if (errno != ENOENT)
uwsgi_error_open(task);
return;
}
// check if the file is locked by anther process
// check if the file is locked by another process
if (uwsgi_fcntl_is_locked(spool_fd)) {
close(spool_fd);
uwsgi_protected_close(spool_fd);
return;
}
if (read(spool_fd, &uh, 4) != 4) {
// 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
uwsgi_error("read()");
close(spool_fd);
if (rlen < 0)
uwsgi_error("read()");
uwsgi_protected_close(spool_fd);
return;
}
@@ -474,30 +496,31 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif
if (read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
if (uwsgi_protected_read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
uwsgi_error("read()");
destroy_spool(dir, task);
close(spool_fd);
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);
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)read(spool_fd, body, body_len) != body_len) {
if ((size_t) uwsgi_protected_read(spool_fd, body, body_len) != body_len) {
uwsgi_error("read()");
destroy_spool(dir, task);
close(spool_fd);
uwsgi_protected_close(spool_fd);
free(body);
return;
}
}
// not the task is running and should not be waken
// now the task is running and should not be waken up
uspool->running = 1;
uwsgi_log("[spooler %s pid: %d] managing request %s ...\n", uspool->dir, (int) uwsgi.mypid, task);
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)
@@ -508,24 +531,28 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
}
int callable_found = 0;
for(i=0;i<0xff;i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler) {
time_t now = time(NULL);
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
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;
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) {
uwsgi_log("[spooler %s pid: %d] done with task %s after %d seconds\n", uspool->dir, (int) uwsgi.mypid, task, time(NULL)-now);
destroy_spool(dir, task);
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;
break;
}
}
@@ -533,9 +560,23 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
free(body);
// here we free and unlock the task
close(spool_fd);
uwsgi_protected_close(spool_fd);
uspool->running = 0;
// 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);
}
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");
}
+3 -3
View File
@@ -10,7 +10,7 @@ static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, cha
if (field_count >= 2) {
int value_len = strlen(fields[1]) + 1;
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
add_exported_option( uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
}
return 0;
@@ -20,7 +20,7 @@ static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, cha
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
sqlite3 *db;
char *err = NULL;
char *err = NULL;
char *query = "SELECT * FROM uwsgi";
char *colon = uwsgi_get_last_char(file, ':');
@@ -28,7 +28,7 @@ void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
query = colon+1;
query = colon + 1;
}
}
+522
View File
@@ -0,0 +1,522 @@
#include "uwsgi.h"
/*
utility functions for fast generating json output for the stats subsystem
*/
extern struct uwsgi_server uwsgi;
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->pos = 1;
us->chunk = chunk_size;
us->size = chunk_size;
us->tabs = 1;
us->minified = uwsgi.stats_minified;
if (!us->minified) {
us->base[1] = '\n';
us->pos++;
}
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;
}
if (us->minified)
return 0;
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) {
if (us->minified)
return 0;
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;
if (!us->minified)
us->tabs++;
return uwsgi_stats_symbol_nl(us, '{');
}
int uwsgi_stats_object_close(struct uwsgi_stats *us) {
if (!us->minified) {
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 (!us->minified) {
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);
}
void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
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;
}
if (uwsgi.stats_http) {
if (uwsgi_send_http_stats(client_fd)) {
close(client_fd);
return;
}
}
struct uwsgi_stats *us = func();
if (!us)
goto end;
size_t remains = us->pos;
off_t pos = 0;
while (remains > 0) {
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
goto end0;
}
ssize_t res = write(client_fd, us->base + pos, remains);
if (res <= 0) {
if (res < 0) {
uwsgi_error("write()");
}
goto end0;
}
pos += res;
remains -= res;
}
end0:
free(us->base);
free(us);
end:
close(client_fd);
}
struct uwsgi_stats_pusher *uwsgi_stats_pusher_get(char *name) {
struct uwsgi_stats_pusher *usp = uwsgi.stats_pushers;
while (usp) {
if (!strcmp(usp->name, name)) {
return usp;
}
usp = usp->next;
}
return usp;
}
void uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *pusher, char *arg) {
struct uwsgi_stats_pusher_instance *old_uspi = NULL, *uspi = uwsgi.stats_pusher_instances;
while (uspi) {
old_uspi = uspi;
uspi = uspi->next;
}
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
uspi->pusher = pusher;
uspi->arg = arg;
if (old_uspi) {
old_uspi->next = uspi;
}
else {
uwsgi.stats_pusher_instances = uspi;
}
}
void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
void *events = event_queue_alloc(1);
for (;;) {
int nevents = event_queue_wait_multi(ut->queue, 1, events, 1);
if (nevents > 0) {
int interesting_fd = event_queue_interesting_fd(events, 0);
char buf[4096];
ssize_t len = read(interesting_fd, buf, 4096);
if (len <= 0) {
uwsgi_log("[uwsgi-stats-pusher] goodbye...\n");
return;
}
uwsgi_log("[uwsgi-stats-pusher] message received from master: %.*s\n", (int) len, buf);
continue;
}
time_t now = uwsgi_now();
struct uwsgi_stats_pusher_instance *uspi = uwsgi.stats_pusher_instances;
struct uwsgi_stats *us = NULL;
while (uspi) {
int delta = uspi->freq ? uspi->freq : uwsgi.stats_pusher_default_freq;
if ((uspi->last_run + delta) <= now) {
if (!us) {
us = uwsgi_master_generate_stats();
if (!us)
goto next;
}
uspi->pusher->func(uspi, us->base, us->pos);
uspi->last_run = now;
}
next:
uspi = uspi->next;
}
if (us) {
free(us->base);
free(us);
}
}
}
void uwsgi_stats_pusher_setup() {
struct uwsgi_string_list *usl = uwsgi.requested_stats_pushers;
while (usl) {
char *ssp = uwsgi_str(usl->value);
struct uwsgi_stats_pusher *pusher = NULL;
char *colon = strchr(ssp, ':');
if (colon) {
*colon = 0;
}
pusher = uwsgi_stats_pusher_get(ssp);
if (!pusher) {
uwsgi_log("unable to find \"%s\" stats_pusher\n", ssp);
exit(1);
}
char *arg = NULL;
if (colon) {
arg = colon + 1;
*colon = ':';
}
uwsgi_stats_pusher_add(pusher, arg);
usl = usl->next;
}
}
void uwsgi_register_stats_pusher(char *name, void (*func) (struct uwsgi_stats_pusher_instance *, char *, size_t)) {
struct uwsgi_stats_pusher *pusher = uwsgi.stats_pushers, *old_pusher = NULL;
while (pusher) {
old_pusher = pusher;
pusher = pusher->next;
}
pusher = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher));
pusher->name = name;
pusher->func = func;
if (old_pusher) {
old_pusher->next = pusher;
}
else {
uwsgi.stats_pushers = pusher;
}
}
struct uwsgi_stats_pusher_file_conf {
char *path;
char *freq;
char *separator;
};
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, char *json, size_t json_len) {
struct uwsgi_stats_pusher_file_conf *uspic = (struct uwsgi_stats_pusher_file_conf *) uspi->data;
if (!uspi->configured) {
uspic = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_file_conf));
if (uspi->arg) {
if (uwsgi_kvlist_parse(uspi->arg, strlen(uspi->arg), ',', '=', "path", &uspic->path, "separator", &uspic->separator, "freq", &uspic->freq, NULL)) {
free(uspi);
return;
}
}
if (!uspic->path)
uspic->path = "uwsgi.stats";
if (!uspic->separator)
uspic->separator = "\n\n";
if (uspic->freq)
uspi->freq = atoi(uspic->freq);
uspi->configured = 1;
uspi->data = uspic;
}
int fd = open(uspic->path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uspic->path);
return;
}
ssize_t rlen = write(fd, json, json_len);
if (rlen != (ssize_t) json_len) {
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
}
rlen = write(fd, uspic->separator, strlen(uspic->separator));
if (rlen != (ssize_t) strlen(uspic->separator)) {
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
}
close(fd);
}
+758
View File
@@ -0,0 +1,758 @@
#include "uwsgi.h"
/*
subscription subsystem
each subscription slot is as an hashed item in a dictionary
each slot has a circular linked list containing the nodes names
the structure and system is very similar to uwsgi_dyn_dict already used by the mime type parser
This system is not mean to run on shared memory. If you have multiple processes for the same app, you have to create
a new subscriptions slot list.
To avoid removal of already using nodes, a reference count system has been implemented
*/
extern struct uwsgi_server uwsgi;
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {
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) {
if (!uwsgi_strncmp(key, keylen, current_slot->key, current_slot->keylen)) {
// auto optimization
if (current_slot->prev) {
if (current_slot->hits > current_slot->prev->hits) {
struct uwsgi_subscribe_slot *slot_parent = current_slot->prev->prev, *slot_prev = current_slot->prev;
if (slot_parent) {
slot_parent->next = current_slot;
}
else {
slot[hash_key] = current_slot;
}
if (current_slot->next) {
current_slot->next->prev = slot_prev;
}
slot_prev->prev = current_slot;
slot_prev->next = current_slot->next;
current_slot->next = slot_prev;
current_slot->prev = slot_parent;
}
}
return current_slot;
}
current_slot = current_slot->next;
// check for loopy optimization
if (current_slot == slot[hash_key])
break;
}
return NULL;
}
// least reference count
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_lrc(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node) {
// if node is NULL we are in the second step (in lrc mode we do not use the first step)
if (node)
return NULL;
struct uwsgi_subscribe_node *choosen_node = NULL;
node = current_slot->nodes;
uint64_t min_rc = 0;
while (node) {
if (!node->death_mark) {
if (min_rc == 0 || node->reference < min_rc) {
min_rc = node->reference;
choosen_node = node;
if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->requests <= node->requests))
break;
}
}
node = node->next;
}
if (choosen_node) {
choosen_node->reference++;
}
return choosen_node;
}
// weighted least reference count
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wlrc(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node) {
// if node is NULL we are in the second step (in wlrc mode we do not use the first step)
if (node)
return NULL;
struct uwsgi_subscribe_node *choosen_node = NULL;
node = current_slot->nodes;
double min_rc = 0;
while (node) {
if (!node->death_mark) {
// node->weight is always >= 1, we can safely use it as divider
double ref = (double) node->reference / (double) node->weight;
double next_node_ref = 0;
if (node->next)
next_node_ref = (double) node->next->reference / (double) node->next->weight;
if (min_rc == 0 || ref < min_rc) {
min_rc = ref;
choosen_node = node;
if (min_rc == 0 && !(node->next && next_node_ref <= ref && node->next->requests <= node->requests))
break;
}
}
node = node->next;
}
if (choosen_node) {
choosen_node->reference++;
}
return choosen_node;
}
// weighted round robin algo
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wrr(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node) {
// if node is NULL we are in the second step
if (node) {
if (node->death_mark == 0 && node->wrr > 0) {
node->wrr--;
node->reference++;
return node;
}
return NULL;
}
// 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;
}
// 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;
}
void uwsgi_subscription_set_algo(char *algo) {
if (!algo)
goto wrr;
if (!strcmp(algo, "wrr")) {
uwsgi.subscription_algo = uwsgi_subscription_algo_wrr;
return;
}
if (!strcmp(algo, "lrc")) {
uwsgi.subscription_algo = uwsgi_subscription_algo_lrc;
return;
}
if (!strcmp(algo, "wlrc")) {
uwsgi.subscription_algo = uwsgi_subscription_algo_wlrc;
return;
}
wrr:
uwsgi.subscription_algo = uwsgi_subscription_algo_wrr;
}
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {
if (keylen > 0xff)
return NULL;
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen);
if (!current_slot)
return NULL;
// slot found, move up in the list increasing hits
current_slot->hits++;
time_t now = uwsgi_now();
struct uwsgi_subscribe_node *node = current_slot->nodes;
while (node) {
// is the node alive ?
if (now - node->last_check > uwsgi.subscription_tolerance) {
if (node->death_mark == 0)
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;
}
// do i need to remove the node ?
if (node->death_mark && node->reference == 0) {
// remove the node and move to next
struct uwsgi_subscribe_node *dead_node = node;
node = node->next;
// if the slot has been removed, return NULL;
if (uwsgi_remove_subscribe_node(slot, dead_node) == 1) {
return NULL;
}
continue;
}
struct uwsgi_subscribe_node *choosen_node = uwsgi.subscription_algo(current_slot, node);
if (choosen_node)
return choosen_node;
node = node->next;
}
return uwsgi.subscription_algo(current_slot, node);
}
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, char *val, uint16_t vallen) {
if (keylen > 0xff)
return NULL;
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen);
if (current_slot) {
struct uwsgi_subscribe_node *node = current_slot->nodes;
while (node) {
if (!uwsgi_strncmp(val, vallen, node->name, node->len)) {
return node;
}
node = node->next;
}
}
return NULL;
}
int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_node *node) {
int ret = 0;
struct uwsgi_subscribe_node *a_node;
struct uwsgi_subscribe_slot *node_slot = node->slot;
struct uwsgi_subscribe_slot *prev_slot = node_slot->prev;
struct uwsgi_subscribe_slot *next_slot = node_slot->next;
int hash_key = node_slot->hash;
// over-engineering to avoid race conditions
node->len = 0;
if (node == node_slot->nodes) {
node_slot->nodes = node->next;
}
else {
a_node = node_slot->nodes;
while (a_node) {
if (a_node->next == node) {
a_node->next = node->next;
break;
}
a_node = a_node->next;
}
}
free(node);
// no more nodes, remove the slot too
if (node_slot->nodes == NULL) {
ret = 1;
// first check if i am the only node
if ((!prev_slot && !next_slot) || next_slot == node_slot) {
#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[hash_key] = NULL;
goto end;
}
// if i am the main entry point, set the next value
if (node_slot == slot[hash_key]) {
slot[hash_key] = next_slot;
}
if (prev_slot) {
prev_slot->next = next_slot;
}
if (next_slot) {
next_slot->prev = prev_slot;
}
#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:
return ret;
}
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_req *usr) {
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, usr->key, usr->keylen), *old_slot = NULL, *a_slot;
struct uwsgi_subscribe_node *node, *old_node = 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 = 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;
node->modifier2 = usr->modifier2;
node->requests = 0;
node->transferred = 0;
node->reference = 0;
node->death_mark = 0;
node->failcnt = 0;
node->cores = usr->cores;
node->load = usr->load;
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 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->nodes = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
current_slot->nodes->slot = current_slot;
current_slot->nodes->len = usr->address_len;
current_slot->nodes->reference = 0;
current_slot->nodes->requests = 0;
current_slot->nodes->transferred = 0;
current_slot->nodes->death_mark = 0;
current_slot->nodes->failcnt = 0;
current_slot->nodes->modifier1 = usr->modifier1;
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 = uwsgi_now();
current_slot->nodes->next = NULL;
a_slot = slot[hash_key];
while (a_slot) {
old_slot = a_slot;
a_slot = a_slot->next;
}
if (old_slot) {
old_slot->next = current_slot;
}
current_slot->prev = old_slot;
current_slot->next = NULL;
if (!slot[hash_key] || current_slot->prev == NULL) {
slot[hash_key] = current_slot;
}
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;
}
}
// TODO rewrite it using uwsgi buffers
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_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 (socket_name == NULL && !uwsgi.sockets)
return;
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
char *ssb = subscrbuf + 4;
// key = "domain"
uint16_t ustrlen = 3;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "key", ustrlen);
ssb += ustrlen;
ustrlen = keysize;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, key, ustrlen);
ssb += ustrlen;
// address = "first uwsgi socket"
ustrlen = 7;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "address", ustrlen);
ssb += ustrlen;
ustrlen = strlen(socket_name);
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, socket_name, ustrlen);
ssb += ustrlen;
// modifier1 = "modifier1"
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "modifier1", ustrlen);
ssb += ustrlen;
ustrlen = value_modifier1_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, value_modifier1, value_modifier1_size);
ssb += ustrlen;
// modifier2 = "modifier2"
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "modifier2", ustrlen);
ssb += ustrlen;
ustrlen = value_modifier2_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, value_modifier2, value_modifier2_size);
ssb += ustrlen;
// cores = uwsgi.numproc * uwsgi.cores
ustrlen = 5;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "cores", ustrlen);
ssb += ustrlen;
ustrlen = value_cores_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, value_cores, value_cores_size);
ssb += ustrlen;
// load
ustrlen = 4;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "load", ustrlen);
ssb += ustrlen;
ustrlen = value_load_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*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;
}
struct uwsgi_subscribe_slot **uwsgi_subscription_init_ht() {
if (!uwsgi.subscription_algo) {
uwsgi_subscription_set_algo(NULL);
}
return uwsgi_calloc(sizeof(struct uwsgi_subscription_slot *) * UMAX16);
}
+2138 -1166
View File
File diff suppressed because it is too large Load Diff
+1670 -1640
View File
File diff suppressed because it is too large Load Diff
+279
View File
@@ -0,0 +1,279 @@
#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
+98 -92
View File
@@ -15,7 +15,7 @@ void yaml_rstrip(char *line) {
off_t i;
for(i = strlen(line)-1;i>=0; i--) {
for (i = strlen(line) - 1; i >= 0; i--) {
if (line[i] == ' ' || line[i] == '\t') {
line[i] = 0;
continue;
@@ -26,18 +26,18 @@ void yaml_rstrip(char *line) {
char *yaml_lstrip(char *line) {
off_t i;
char *ptr = line;
off_t i;
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
}
break;
}
for (i = 0; i < (int) strlen(line); i++) {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
}
break;
}
return ptr;
return ptr;
}
@@ -46,13 +46,13 @@ int yaml_get_depth(char *line) {
off_t i;
int depth = 0;
for(i=0;i< (int) strlen(line);i++) {
for (i = 0; i < (int) strlen(line); i++) {
if (line[i] == ' ') {
depth++;
continue;
}
else if (line[i] == '\t' || line[i] == '\r') {
depth+=8;
depth += 8;
continue;
}
break;
@@ -67,11 +67,11 @@ char *yaml_get_line(char *yaml, off_t size) {
char *ptr = yaml;
int comment = 0;
for(i=0;i<size;i++) {
for (i = 0; i < size; i++) {
ptr++;
if (yaml[i] == '#') {
yaml[i] = 0;
comment = 1;
comment = 1;
}
else if (yaml[i] == '\n') {
yaml[i] = 0;
@@ -108,17 +108,17 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
char *colon;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
section_asked = colon+1;
section_asked = colon + 1;
}
}
@@ -128,81 +128,81 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
#ifdef UWSGI_LIBYAML
yaml_parser_t parser;
yaml_token_t token;
yaml_token_t token;
int status = 0;
int parsing = 1;
if(!yaml_parser_initialize(&parser)) {
if (!yaml_parser_initialize(&parser)) {
uwsgi_log("unable to initialize YAML parser (libyaml)\n");
exit(1);
}
yaml_parser_set_input_string(&parser, (const unsigned char *)yaml, (size_t) len-1);
yaml_parser_set_input_string(&parser, (unsigned char *) yaml, (size_t) len - 1);
while(parsing) {
while (parsing) {
if (!yaml_parser_scan(&parser, &token)) {
uwsgi_log("error parsing YAML file: %s (%c)\n", parser.problem, yaml[parser.problem_offset]);
exit(1);
}
switch(token.type) {
case YAML_STREAM_END_TOKEN:
switch (token.type) {
case YAML_STREAM_END_TOKEN:
parsing = 0;
break;
case YAML_KEY_TOKEN:
status = 1;
break;
case YAML_VALUE_TOKEN:
status = 2;
break;
case YAML_FLOW_SEQUENCE_START_TOKEN:
case YAML_BLOCK_SEQUENCE_START_TOKEN:
status = 3;
break;
case YAML_BLOCK_MAPPING_START_TOKEN:
if (!in_uwsgi_section) {
if (key) {
if (!strcmp(section_asked, key)) {
in_uwsgi_section = 1;
}
}
}
break;
case YAML_BLOCK_END_TOKEN:
if (in_uwsgi_section) {
parsing = 0;
break;
case YAML_KEY_TOKEN:
status = 1;
break;
case YAML_VALUE_TOKEN:
status = 2;
break;
case YAML_FLOW_SEQUENCE_START_TOKEN:
case YAML_BLOCK_SEQUENCE_START_TOKEN:
status = 3;
break;
case YAML_BLOCK_MAPPING_START_TOKEN:
if (!in_uwsgi_section) {
if (key) {
if (!strcmp(section_asked, key)) {
in_uwsgi_section = 1;
}
}
}
break;
case YAML_BLOCK_END_TOKEN:
if (in_uwsgi_section) {
parsing = 0;
break;
}
break;
case YAML_SCALAR_TOKEN:
case YAML_FLOW_ENTRY_TOKEN:
case YAML_BLOCK_ENTRY_TOKEN:
if (status == 1) {
key = (char *) token.data.scalar.value;
}
else if (status == 2) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
break;
case YAML_SCALAR_TOKEN:
case YAML_FLOW_ENTRY_TOKEN:
case YAML_BLOCK_ENTRY_TOKEN:
if (status == 1) {
key = (char *) token.data.scalar.value;
}
else if (status == 2) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
status = 0;
}
else if (status == 3) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
}
else {
uwsgi_log("unsupported YAML token in %s block\n", section_asked);
parsing = 0;
break;
}
break;
default:
status = 0;
}
else if (status == 3) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
}
else {
uwsgi_log("unsupported YAML token in %s block\n", section_asked);
parsing = 0;
break;
}
break;
default:
status = 0;
}
}
#else
int depth;
int current_depth = 0;
@@ -211,7 +211,7 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
char *section = "";
while(len) {
while (len) {
yaml_line = yaml_get_line(yaml, len);
if (yaml_line == NULL) {
break;
@@ -219,12 +219,14 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
lines++;
// skip empty line
if (yaml[0] == 0) goto next;
if (yaml[0] == 0)
goto next;
depth = yaml_get_depth(yaml);
if (depth <= current_depth) {
current_depth = depth;
// end the parsing cycle
if (in_uwsgi_section) return;
if (in_uwsgi_section)
return;
}
else if (depth > current_depth && !in_uwsgi_section) {
goto next;
@@ -232,40 +234,44 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
key = yaml_lstrip(yaml);
// skip empty line
if (key[0] == 0) goto next;
if (key[0] == 0)
goto next;
// skip list and {} defined dict
if (key[0] == '-' || key[0] == '[' || key[0] == '{') {
if (in_uwsgi_section) return;
if (in_uwsgi_section)
return;
goto next;
}
if (!in_uwsgi_section) {
section = strchr(key,':');
if (!section) goto next;
section = strchr(key, ':');
if (!section)
goto next;
section[0] = 0;
if (!strcmp(key, section_asked)) {
in_uwsgi_section = 1;
}
}
else {
// get dict value
// get dict value
val = strstr(key, ": ");
if (!val) {
val = strstr(key, ":\t");
}
if (!val) return;
if (!val)
return;
// get the right key
val[0] = 0;
// yeah overengeneering....
yaml_rstrip(key);
val = yaml_lstrip(val+2);
val = yaml_lstrip(val + 2);
yaml_rstrip(val);
//uwsgi_log("YAML: %s = %s\n", key, val);
add_exported_option((char *)key, val, 0);
add_exported_option((char *) key, val, 0);
}
next:
len -= (yaml_line - yaml);
-930
View File
@@ -1,930 +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);
#ifdef UWSGI_DEBUG
uwsgi_log("putenv %s\n", ne);
#endif
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_string_list *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->value;
counter+=2;
uct = uct->next;
}
vassal_argv[counter] = NULL;
// disable stdin
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0)) {
uwsgi_error("dup2()");
exit(1);
}
close(stdin_fd);
}
// close all of the unneded fd
for(i=3;i<(int)uwsgi.max_fd;i++) {
if (n_ui->use_config) {
if (i == n_ui->pipe_config[1])
continue;
}
if (i != n_ui->pipe[1]) {
close(i);
}
}
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];
struct rlimit rl;
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));
if (getrlimit(RLIMIT_NOFILE, &rl)) {
uwsgi_error("getrlimit()");
exit(1);
}
uwsgi.max_fd = rl.rlim_cur;
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 = uwsgi_malloc(PATH_MAX+1);
if (realpath(".", emperor_absolute_dir) == NULL) {
uwsgi_error("realpath()");
exit(1);
}
}
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 && 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
if (!ui_current->config_len) {
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
-883
View File
@@ -1,883 +0,0 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_USE_PORT
#include <port.h>
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int event_queue_init() {
int port = port_create();
if (port < 0) {
uwsgi_error("port_create()");
return -1;
}
return port;
}
int event_queue_del_fd(int eq, int fd, int event) {
if (port_dissociate(eq, PORT_SOURCE_FD, fd)) {
uwsgi_error("port_disassociate");
return -1;
}
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
if (pe[id].portev_events == POLLHUP || pe[id].portev_events == POLLERR) {
return 1;
}
return 0;
}
int event_queue_add_fd_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(port_event_t) * nevents);
}
int event_queue_interesting_fd(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
return (long) pe[id].portev_user;
}
return (int) pe[id].portev_object;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
uint_t nget = 1;
timespec_t ts;
port_event_t *pe;
if (timeout >= 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_getn(eq, events, nevents, &nget, &ts);
}
else {
ret = port_getn(eq, events, nevents, &nget, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
uwsgi_error("port_getn()");
return -1;
}
return 0;
}
pe = (port_event_t *) events;
return nget;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
port_event_t pe;
timespec_t ts;
if (timeout > 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_get(eq, &pe, &ts);
}
else {
ret = port_get(eq, &pe, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
uwsgi_error("port_get()");
return -1;
}
return 0;
}
if (pe.portev_source == PORT_SOURCE_FD) {
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
uwsgi_error("port_associate");
}
}
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
*interesting_fd = (long) pe.portev_user;
}
else {
*interesting_fd = (int) pe.portev_object;
}
return 1;
}
#endif
#ifdef UWSGI_EVENT_USE_EPOLL
#include <sys/epoll.h>
#define UWSGI_EVENT_IN EPOLLIN
#define UWSGI_EVENT_OUT EPOLLOUT
int event_queue_init() {
int epfd;
epfd = epoll_create(256);
if (epfd < 0) {
uwsgi_error("epoll_create()");
return -1;
}
return epfd;
}
int event_queue_add_fd_read(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_MOD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.data.fd = fd;
ee.events = event;
if (epoll_ctl(eq, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLOUT;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(struct epoll_event) * nevents);
}
int event_queue_interesting_fd(void *events, int id) {
struct epoll_event *ee = (struct epoll_event *) events;
return ee[id].data.fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct epoll_event *ee = (struct epoll_event *) events;
if (ee[id].events == EPOLLHUP || ee[id].events == EPOLLERR || (ee[id].events == (EPOLLERR|EPOLLHUP))) {
return 1;
}
return 0;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
if (timeout > 0) {
timeout = timeout*1000;
}
ret = epoll_wait(eq, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
if (errno != EINTR)
uwsgi_error("epoll_wait()");
}
return ret;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
struct epoll_event ee;
if (timeout > 0) {
timeout = timeout*1000;
}
ret = epoll_wait(eq, &ee, 1, timeout);
if (ret < 0) {
if (errno != EINTR)
uwsgi_error("epoll_wait()");
}
if (ret > 0) {
*interesting_fd = ee.data.fd;
}
return ret;
}
#endif
#ifdef UWSGI_EVENT_USE_KQUEUE
#define UWSGI_EVENT_IN EVFILT_READ
#define UWSGI_EVENT_OUT EVFILT_WRITE
int event_queue_init() {
int kfd = kqueue();
if (kfd < 0) {
uwsgi_error("kqueue()");
return -1;
}
return kfd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
struct kevent kev;
#ifndef __FreeBSD__
EV_SET(&kev, fd, EVFILT_WRITE, EV_DISABLE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
#endif
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct kevent kev;
EV_SET(&kev, fd, event, EV_DELETE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_add_fd_read(int eq, int fd) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(struct kevent) * nevents);
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
struct timespec ts;
if (timeout < 0) {
ret = kevent(eq, NULL, 0, events, nevents, NULL);
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout;
ret = kevent(eq, NULL, 0, (struct kevent *)events, nevents, &ts);
}
if (ret < 0) {
if (errno != EINTR)
uwsgi_error("kevent()");
}
return ret;
}
int event_queue_interesting_fd(void *events, int id) {
struct kevent *ev = (struct kevent *) events;
return ev[id].ident;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct kevent *ev = (struct kevent *) events;
if ( ( (ev[id].flags == EV_ERROR) || (ev[id].flags == EV_EOF) || (ev[id].flags == (EV_EOF|EV_ERROR))) ) {
return 1;
}
return 0;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
struct timespec ts;
struct kevent ev;
if (timeout <= 0) {
ret = kevent(eq, NULL, 0, &ev, 1, NULL);
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout;
ret = kevent(eq, NULL, 0, &ev, 1, &ts);
}
if (ret < 0) {
if (errno != EINTR)
uwsgi_error("kevent()");
}
if (ret > 0) {
*interesting_fd = ev.ident;
}
return ret;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_NONE
int event_queue_add_file_monitor(int eq, char *filename, int *id) { return -1;}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {return NULL;}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct file_obj fo;
struct stat st;
static int fmon_id = 0xffffee00;
if (stat(filename, &st)) {
uwsgi_error("stat()");
return -1;
}
fo.fo_name = filename;
fo.fo_atime = st.st_atim;
fo.fo_mtime = st.st_mtim;
fo.fo_ctime = st.st_ctim;
fmon_id++;
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) (long) fmon_id)) {
uwsgi_error("port_associate()");
return -1;
}
*id = fmon_id;
uwsgi_log("added new file to monitor %s [%d]\n", filename, *id);
return *id;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
int i;
struct file_obj fo;
struct stat st;
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id) {
if (stat(ushared->files_monitored[i].filename, &st)) {
uwsgi_error("stat()");
return NULL;
}
fo.fo_name = ushared->files_monitored[i].filename;
fo.fo_atime = st.st_atim;
fo.fo_mtime = st.st_mtim;
fo.fo_ctime = st.st_ctim;
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)(long)id)) {
uwsgi_error("port_associate()");
return NULL;
}
return &ushared->files_monitored[i];
}
}
}
return NULL;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct kevent kev;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(filename);
return -1;
}
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE|NOTE_DELETE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_RENAME|NOTE_REVOKE, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
*id = fd;
uwsgi_log("added new file to monitor %s\n", filename);
return fd;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
int i;
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id) {
return &ushared->files_monitored[i];
}
}
}
return NULL;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifdef OBSOLETE_LINUX_KERNEL
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
return -1;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#else
#include <sys/inotify.h>
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
int ifd = -1;
int i;
int add_to_queue = 0;
for (i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
ifd = ushared->files_monitored[0].fd;
break;
}
}
if (ifd == -1) {
ifd = inotify_init();
if (ifd < 0) {
uwsgi_error("inotify_init()");
return -1;
}
add_to_queue = 1;
}
*id = inotify_add_watch(ifd, filename, IN_ATTRIB|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MODIFY|IN_MOVE_SELF|IN_MOVED_FROM|IN_MOVED_TO);
#ifdef UWSGI_DEBUG
uwsgi_log("added watch %d for filename %s\n", *id, filename);
#endif
if (add_to_queue) {
return event_queue_add_fd_read(eq, ifd);
}
else {
return ifd;
}
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
ssize_t rlen = 0;
struct inotify_event ie, *bie, *iie;
int i,j;
int items = 0;
unsigned int isize = sizeof(struct inotify_event);
struct uwsgi_fmon *uf = NULL;
if (ioctl(id, FIONREAD, &isize) < 0) {
uwsgi_error("ioctl()");
return NULL;
}
if (isize > sizeof(struct inotify_event)) {
bie = uwsgi_malloc(isize);
rlen = read(id, bie, isize);
}
else {
rlen = read(id, &ie, sizeof(struct inotify_event));
bie = &ie;
}
if (rlen < 0) {
uwsgi_error("read()");
}
else {
items = isize/(sizeof(struct inotify_event));
#ifdef UWSGI_DEBUG
uwsgi_log("inotify returned %d items\n", items);
#endif
for(j=0;j<items;j++) {
iie = &bie[j];
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id && ushared->files_monitored[i].id == iie->wd) {
uf = &ushared->files_monitored[i];
}
}
}
}
if (items > 1) {
free(bie);
}
return uf;
}
return NULL;
}
#endif
#endif
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
#ifndef UWSGI_EVENT_TIMER_USE_TIMERFD_NOINC
#include <sys/timerfd.h>
#endif
#ifndef TFD_CLOEXEC
// timerfd support
enum
{
TFD_CLOEXEC = 02000000,
#define TFD_CLOEXEC TFD_CLOEXEC
TFD_NONBLOCK = 04000
#define TFD_NONBLOCK TFD_NONBLOCK
};
/* Bits to be set in the FLAGS parameter of `timerfd_settime'. */
enum
{
TFD_TIMER_ABSTIME = 1 << 0
#define TFD_TIMER_ABSTIME TFD_TIMER_ABSTIME
};
static int timerfd_create (clockid_t __clock_id, int __flags) {
#ifdef __amd64__
return syscall(283, __clock_id, __flags);
#elif defined(__i386__)
return syscall(322, __clock_id, __flags);
#else
return -1;
#endif
}
static int timerfd_settime (int __ufd, int __flags,
__const struct itimerspec *__utmr,
struct itimerspec *__otmr) {
#ifdef __amd64__
return syscall(286, __ufd, __flags, __utmr, __otmr);
#elif defined(__i386__)
return syscall(325, __ufd, __flags, __utmr, __otmr);
#endif
}
#endif
int event_queue_add_timer(int eq, int *id, int sec) {
struct itimerspec it;
int tfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
if (tfd < 0) {
uwsgi_error("timerfd_create()");
return -1;
}
it.it_value.tv_sec = sec;
it.it_value.tv_nsec = 0;
it.it_interval.tv_sec = sec;
it.it_interval.tv_nsec = 0;
if (timerfd_settime(tfd, 0, &it, NULL)) {
uwsgi_error("timerfd_settime()");
close(tfd);
return -1;
}
*id = tfd;
return event_queue_add_fd_read(eq, tfd);
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
ssize_t rlen;
uint64_t counter;
struct uwsgi_timer *ut = NULL;
for(i=0;i<ushared->timers_cnt;i++) {
if (ushared->timers[i].registered) {
if (ushared->timers[i].id == id) {
ut = &ushared->timers[i];
}
}
}
rlen = read(id, &counter, sizeof(uint64_t));
if (rlen < 0) {
uwsgi_error("read()");
}
return ut;
}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_NONE
int event_queue_add_timer(int eq, int *id, int sec) { return -1; }
struct uwsgi_timer *event_queue_ack_timer(int id) { return NULL;}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_PORT
int event_queue_add_timer(int eq, int *id, int sec) {
static int timer_id = 0xffffff00;
port_notify_t pnotif;
struct sigevent sigev;
itimerspec_t it;
timer_t tid;
timer_id++;
pnotif.portnfy_port = eq;
pnotif.portnfy_user = (void *) (long) timer_id;
sigev.sigev_notify = SIGEV_PORT;
sigev.sigev_value.sival_ptr = &pnotif;
if (timer_create(CLOCK_REALTIME, &sigev, &tid) < 0) {
uwsgi_error("timer_create()");
return -1;
}
it.it_value.tv_sec = sec;
it.it_value.tv_nsec = 0;
it.it_interval.tv_sec = sec;
it.it_interval.tv_nsec = 0;
if (timer_settime(tid, 0, &it, NULL) < 0) {
uwsgi_error("timer_settime()");
return -1;
}
*id = timer_id;
return *id;
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
struct uwsgi_timer *ut = NULL;
for(i=0;i<uwsgi.shared->timers_cnt;i++) {
if (uwsgi.shared->timers[i].registered) {
if (uwsgi.shared->timers[i].id == id) {
ut = &uwsgi.shared->timers[i];
}
}
}
return ut;
}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_KQUEUE
int event_queue_add_timer(int eq, int *id, int sec) {
static int timer_id = 0xffffff00;
struct kevent kev;
*id = timer_id ;
timer_id++;
EV_SET(&kev, *id, EVFILT_TIMER, EV_ADD, 0, sec*1000, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return *id;
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
struct uwsgi_timer *ut = NULL;
for(i=0;i<uwsgi.shared->timers_cnt;i++) {
if (uwsgi.shared->timers[i].registered) {
if (uwsgi.shared->timers[i].id == id) {
ut = &uwsgi.shared->timers[i];
}
}
}
return ut;
}
#endif
inline int event_queue_read() {
return UWSGI_EVENT_IN;
}
inline int event_queue_write() {
return UWSGI_EVENT_OUT;
}
View File
View File
View File
View File
View File
View File
View File
View File
+10
View File
@@ -0,0 +1,10 @@
[uwsgi]
;master = true
gevent = 1000
zmq-socket = tcp://192.168.173.2:9999,tcp://192.168.173.2:9998
zmq-socket = tcp://192.168.173.19:9999,tcp://192.168.173.19:9998
http-socket = :8080
;module = tests.ugevent

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