Compare commits

..
335 Commits
Author SHA1 Message Date
Unbit c7d3a27225 backported http-socket-modifier1/2 2013-03-02 16:25:17 +01:00
Unbit 4f50b4aafc completetd gemspec 2013-03-02 14:58:58 +01:00
Unbit d172fb4909 fixed gem generation 2013-03-02 14:49:03 +01:00
Unbit c842bb4917 allows building uwsgi as a gem 2013-03-02 14:37:14 +01:00
Unbit d6da6848be manage https re-handshake and fix gevent timeout management 2013-03-02 09:54:10 +01:00
Unbit b1caf56f49 various minor fixes in gateway initialization 2013-03-02 08:35:56 +01:00
Unbit 00c243bcce backported --for-glob 2013-03-01 15:23:38 +01:00
Unbit 575dd6beee backported add_timer and add_rb_timer for perl/psgi plugin 2013-03-01 15:20:40 +01:00
unbit 645d021d73 Merge pull request #166 from prymitive/carbon_hostname14
backported carbon hostname patch to 1.4.x
2013-03-01 06:18:52 -08:00
Łukasz Mierzwa 0ca320e5fd backported carbon hostname patch to 1.4.x 2013-03-01 15:15:46 +01:00
Unbit 7879a010e8 backported negative --log-alarm 2013-02-27 04:39:55 +01:00
Unbit 43dd1029ad fixed usage of ipcsem on linux 2013-02-27 04:26:59 +01:00
Unbit ce7d84b865 try to avoid the need to sync cache_first_available_item with cache_unused_stack 2013-02-27 01:43:03 +01:00
Unbit 7ab1795075 let's prepare for 1.4.7 2013-02-27 01:27:49 +01:00
Unbit e1ce4e1011 backporetd new carbon plugin and stats pusher subsystem 2013-02-27 01:26:24 +01:00
Unbit 0c02a5104a removed the old/broken/useless mono plugin, a new one will be in 1.9 2013-02-25 08:39:43 +01:00
Unbit 0e244fc59c added support for ruby 2 2013-02-25 07:34:34 +01:00
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
Æ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
160 changed files with 15227 additions and 8221 deletions
+5
View File
@@ -0,0 +1,5 @@
*.o
*.py[co]
/uwsgi
/uwsgibuild.*
+3
View File
@@ -53,3 +53,6 @@ e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
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
+44 -1
View File
@@ -1,5 +1,33 @@
*** 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
@@ -10,12 +38,27 @@
- merged routers codebase (fastrouter, http, rawrouter)
- https support in the http router
- config report at the end of uWSGI build process
- support for keepalive in the http router
- improved subscription system (multicast and unix socket)
- custom options
- graceful reloads on shared sockets
- configurable log-master buffer size
- extreme-optimizations for the stats subsystem
- 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 ***
+3
View File
@@ -3,3 +3,6 @@ all:
clean:
python uwsgiconfig.py --clean
check:
python uwsgiconfig.py --check
+30 -3
View File
@@ -1,3 +1,8 @@
/*
apxs2 -i -c mod_proxy_uwsgi.c
*/
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_strings.h"
@@ -101,10 +106,26 @@ static int uwsgi_send_headers(request_rec *r, proxy_conn_rec *conn)
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) {
apr_table_set(r->subprocess_env, "SCRIPT_NAME", apr_pstrndup(r->pool, script_name, strlen(script_name)-strlen(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);
@@ -135,7 +156,7 @@ static int uwsgi_send_headers(request_rec *r, proxy_conn_rec *conn)
buf[0] = 0;
buf[1] = (uint8_t) (pktsize & 0xff);
buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
buf[0] = 0;
buf[3] = 0;
return uwsgi_send(conn, buf, headerlen, r);
}
@@ -326,7 +347,13 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
}
// ADD PATH_INFO
apr_table_add(r->subprocess_env, "PATH_INFO", url+strlen(worker->name));
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 */
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby
cmd = File.expand_path "#{File.dirname(__FILE__)}/../ext/uwsgi/uwsgi.ruby"
exec(cmd, *ARGV)
+2 -2
View File
@@ -12,12 +12,12 @@ ssl = auto
udp = true
multicast = true
threading = true
sendfile = true
minterpreters = true
async = true
ldap = auto
pcre = auto
routing = auto
alarm = auto
ipv6 = false
debug = false
unbit = false
@@ -29,7 +29,7 @@ plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, router_rewrite, router_http
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
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
main_plugin = python
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
-30
View File
@@ -1,30 +0,0 @@
[uwsgi]
xml = true
ini = true
snmp = true
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
-29
View File
@@ -1,29 +0,0 @@
[uwsgi]
xml = true
ini = true
yaml = true
snmp = true
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 =
+1 -1
View File
@@ -11,12 +11,12 @@ embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
ldap = true
pcre = true
routing = true
alarm = true
debug = false
unbit = true
xml_implementation = expat
-44
View File
@@ -1,44 +0,0 @@
[uwsgi]
xml = false
ini = true
yaml = false
json = false
sqlite3 = false
zeromq = false
snmp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = false
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins =
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+275
View File
@@ -0,0 +1,275 @@
#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, int negate) {
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;
}
ual->negate = negate;
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, usl->custom)) {
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) {
if (!ual->negate) {
uwsgi_alarm_log_run(ual, msg, len);
}
else {
break;
}
}
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;
}
}
+128 -133
View File
@@ -7,21 +7,21 @@ void uwsgi_async_init() {
uwsgi.async_queue = event_queue_init();
if (uwsgi.async_queue < 0) {
exit(1);
}
if (uwsgi.async_queue < 0) {
exit(1);
}
uwsgi_add_sockets_to_queue(uwsgi.async_queue, -1);
uwsgi_add_sockets_to_queue(uwsgi.async_queue, -1);
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
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;
}
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;
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
}
@@ -37,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--;
}
@@ -63,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++;
@@ -99,27 +99,28 @@ struct wsgi_request *find_first_available_wsgi_req() {
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
time_t current_time = uwsgi_now();
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;
@@ -129,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;
}
}
@@ -141,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;
}
@@ -167,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, uwsgi_now()+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);
}
@@ -216,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;
@@ -241,7 +249,8 @@ void *async_loop(void *arg1) {
}
// 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) {
@@ -249,38 +258,38 @@ 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 - uwsgi_now();
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);
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
continue;
}
}
is_a_new_connection = 0;
@@ -288,11 +297,11 @@ void *async_loop(void *arg1) {
// 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) {
@@ -304,30 +313,23 @@ void *async_loop(void *arg1) {
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__
/* 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;
}
/* re-set blocking socket */
int arg = uwsgi_sock->arg;
arg &= (~O_NONBLOCK);
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, arg) < 0) {
uwsgi_error("fcntl()");
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
#endif
if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
@@ -352,16 +354,14 @@ 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;
@@ -387,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;
}
}
@@ -426,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
@@ -453,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);
}
@@ -464,6 +461,4 @@ void *async_loop(void *arg1) {
}
return NULL;
}
+61 -6
View File
@@ -10,18 +10,62 @@ struct uwsgi_buffer *uwsgi_buffer_new(size_t 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("realloc()");
uwsgi_error("uwsgi_buffer_append()");
return -1;
}
ub->buf = new_buf;
@@ -34,7 +78,8 @@ int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
}
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
if (ub->buf) free(ub->buf);
if (ub->buf)
free(ub->buf);
free(ub);
}
@@ -42,19 +87,19 @@ int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
size_t remains = ub->pos;
char *ptr = ub->buf;
while(remains > 0) {
while (remains > 0) {
int ret = uwsgi_waitfd_write(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret > 0) {
ssize_t len = write(fd, ptr, remains);
if (len > 0) {
ptr += len;
remains -= len;
}
}
else if (len == 0) {
return -1;
}
else {
uwsgi_error("write()");
uwsgi_error("uwsgi_buffer_send()");
return -1;
}
}
@@ -69,3 +114,13 @@ int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
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);
}
+166 -141
View File
@@ -3,90 +3,89 @@
extern struct uwsgi_server uwsgi;
void uwsgi_init_cache() {
int i;
if (!uwsgi.cache_blocksize)
uwsgi.cache_blocksize = UMAX16;
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);
}
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);
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);
}
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);
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;
// 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;
//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 (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();
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);
}
}
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 = 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 = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
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);
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) {
@@ -94,7 +93,7 @@ uint32_t djb33x_hash(char *key, int keylen) {
register uint32_t hash = 5381;
int i;
for(i=0;i<keylen;i++) {
for (i = 0; i < keylen; i++) {
hash = ((hash << 5) + hash) ^ key[i];
}
@@ -102,11 +101,11 @@ uint32_t djb33x_hash(char *key, int keylen) {
}
inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
static inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
uint32_t hash_key = hash % 0xffff;
uint64_t slot = uwsgi.cache_hashtable[hash_key];
@@ -118,19 +117,23 @@ inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uci = &uwsgi.cache_items[slot];
// first round
if (uci->djbhash != hash) return 0;
if (uci->keysize != keylen) goto cycle;
if (memcmp(uci->key, key, keylen)) goto cycle;
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) {
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);
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) {
@@ -141,9 +144,12 @@ cycle:
exit(1);
}
}
if (uci->djbhash != hash) return 0;
if (uci->keysize != keylen) continue;
if (!memcmp(uci->key, key, keylen)) return slot;
if (uci->djbhash != hash)
continue;
if (uci->keysize != keylen)
continue;
if (!memcmp(uci->key, key, keylen))
return slot;
}
return 0;
@@ -154,15 +160,16 @@ 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) {
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;
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 uwsgi.cache + (index * uwsgi.cache_blocksize);
}
return NULL;
@@ -177,20 +184,15 @@ int uwsgi_cache_del(char *key, uint16_t keylen, uint64_t index) {
index = uwsgi_cache_get_index(key, keylen);
if (index) {
uci = &uwsgi.cache_items[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;
uwsgi.cache_items[uci->prev].next = uci->next;
}
else {
// set next as the new entry point (could be 0)
@@ -198,7 +200,7 @@ int uwsgi_cache_del(char *key, uint16_t keylen, uint64_t index) {
}
if (uci->next) {
uwsgi.cache_items[uci->next].prev = uci->prev;
uwsgi.cache_items[uci->next].prev = uci->prev;
}
if (!uci->prev && !uci->next) {
@@ -219,12 +221,12 @@ void uwsgi_cache_fix() {
uint64_t i;
for(i=0;i< uwsgi.cache_max_items;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;
uwsgi.cache_hashtable[uwsgi.cache_items[i].djbhash % 0xffff] = i;
}
}
else {
@@ -238,16 +240,17 @@ void uwsgi_cache_fix() {
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 ;
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 || !vallen)
return -1;
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) 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");
@@ -263,27 +266,28 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
uwsgi.shared->cache_unused_stack_ptr--;
}
else {
index = uwsgi.shared->cache_first_available_item;
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 = &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);
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;
uci->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
slot = uci->djbhash % 0xffff;
int slot = uci->djbhash % 0xffff;
// reset values
uci->prev = 0;
uci->next = 0;
@@ -295,29 +299,29 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
//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) {
ucii = &uwsgi.cache_items[last_index];
while (ucii->next) {
last_index = ucii->next;
ucii = &uwsgi.cache_items[ last_index ];
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] ;
uci = &uwsgi.cache_items[index];
if (expires) {
expires += uwsgi_now();
uci->expires = expires;
}
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
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 !!! */
@@ -328,7 +332,7 @@ void *cache_thread_loop(void *fd_ptr) {
int fd = *fd_tmp;
int i;
ssize_t len;
char uwsgi_packet[UMAX16+4];
char uwsgi_packet[UMAX16 + 4];
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi_packet;
char *val;
uint64_t vallen;
@@ -341,7 +345,7 @@ void *cache_thread_loop(void *fd_ptr) {
ctl_poll.events = POLLIN;
for(;;) {
for (;;) {
ctl_sun_len = sizeof(struct sockaddr_un);
pthread_mutex_lock(&uwsgi.cache_server_lock);
@@ -354,55 +358,58 @@ void *cache_thread_loop(void *fd_ptr) {
continue;
}
i = 0;
while(i < 4) {
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);
len = read(ctl_poll.fd, uwsgi_packet + i, 4 - i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i+=len;
i += len;
}
if (uh->pktsize == 0) goto clear;
if (uh->pktsize == 0)
goto clear;
while(i < 4+uh->pktsize) {
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);
len = read(ctl_poll.fd, uwsgi_packet + i, (4 + uh->pktsize) - i);
if (len < 0) {
uwsgi_error("cache read()");
goto clear;
}
i+=len;
i += len;
}
watermark = uwsgi_packet+4+uh->pktsize;
watermark = uwsgi_packet + 4 + uh->pktsize;
// get first parameter
memcpy(&keylen, uwsgi_packet+4, 2);
memcpy(&keylen, uwsgi_packet + 4, 2);
#ifdef __BIG_ENDIAN__
keylen = uwsgi_swap16(keylen);
keylen = uwsgi_swap16(keylen);
#endif
if (uwsgi_packet+6+keylen > watermark) goto clear;
key = uwsgi_packet+6+keylen+2;
memcpy(&keylen, key-2, 2);
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);
keylen = uwsgi_swap16(keylen);
#endif
if (key+keylen > watermark) goto clear;
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) {
if (val && vallen > 0) {
if (write(ctl_poll.fd, val, vallen) < 0) {
uwsgi_error("cache write()");
}
}
@@ -417,27 +424,45 @@ clear:
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);
}
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);
pthread_mutex_init(&uwsgi.cache_server_lock, NULL);
if (threads < 1) threads = 1;
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++) {
for (i = 0; i < threads; i++) {
pthread_create(&thread_id, NULL, cache_thread_loop, (void *) fd);
}
return *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);
}
+4 -4
View File
@@ -4,11 +4,11 @@ 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();
return uwsgi.clock->seconds();
}
uint64_t uwsgi_micros() {
return uwsgi.clock->microseconds();
return uwsgi.clock->microseconds();
}
@@ -22,7 +22,7 @@ void uwsgi_register_clock(struct uwsgi_clock *clock) {
return;
}
while(clocks) {
while (clocks) {
if (!clocks->next) {
clocks->next = clock;
return;
@@ -33,7 +33,7 @@ void uwsgi_register_clock(struct uwsgi_clock *clock) {
void uwsgi_set_clock(char *name) {
struct uwsgi_clock *clocks = uwsgi.clocks;
while(clocks) {
while (clocks) {
if (!strcmp(name, clocks->name)) {
uwsgi.clock = clocks;
return;
+317 -317
View File
@@ -7,7 +7,7 @@ extern struct uwsgi_server uwsgi;
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);
add_exported_option(uwsgi_concat2n(key, keylen, "", 0), uwsgi_concat2n(value, vallen, "", 0), 0);
}
@@ -15,45 +15,45 @@ void cluster_setup() {
int rlen;
// get cluster configuration
if (uwsgi.cluster != NULL) {
// get multicast socket
if (uwsgi.cluster != NULL) {
// get multicast socket
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
uwsgi_log("JOINED CLUSTER: %s\n", 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:
// 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();
}
if (!uwsgi.cluster_nodes)
uwsgi_cluster_add_me();
}
}
@@ -61,404 +61,404 @@ void cluster_setup() {
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
int i;
struct uwsgi_cluster_node *ucn;
char *tcp_port;
int i;
struct uwsgi_cluster_node *ucn;
char *tcp_port;
#ifdef UWSGI_DEBUG
uwsgi_log("adding node\n");
uwsgi_log("adding node\n");
#endif
tcp_port = strchr(nucn->name, ':');
tcp_port = strchr(nucn->name, ':');
#ifndef UWSGI_ZEROMQ
if (tcp_port == NULL) {
if (tcp_port == NULL) {
#else
char *zmq_dash = strchr(nucn->name, '-');
if (tcp_port == NULL && zmq_dash == NULL) {
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;
}
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;
}
}
}
// 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];
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 {
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);
uwsgi_log("%s\n", nucn->name);
#endif
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
}
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;
}
}
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);
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";
const char *key1 = "hostname";
const char *key2 = "address";
const char *key3 = "workers";
const char *key4 = "requests";
char *ptrbuf;
uint16_t ustrlen;
char numproc[6];
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) {
char uuid_zmq_str[37];
uuid_t uuid_zmq;
if (!uwsgi.sockets && !uwsgi.zeromq) {
#else
if (!uwsgi.sockets) {
if (!uwsgi.sockets) {
#endif
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
exit(1);
}
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
exit(1);
}
snprintf(numproc, 6, "%d", uwsgi.numproc);
snprintf(numproc, 6, "%d", uwsgi.numproc);
size_t len;
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;
}
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;
}
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);
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;
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(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);
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);
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);
}
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);
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);
}
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);
*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(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 = 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;
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);
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
free(buf);
free(buf);
#ifdef UWSGI_DEBUG
uwsgi_log("add_me() successfull\n");
uwsgi_log("add_me() successfull\n");
#endif
return 0;
return 0;
}
int uwsgi_cluster_join(char *name) {
int fd;
char *cp;
int broadcast = 0;
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 (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] = ':';
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);
}
// 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;
return fd;
}
char *uwsgi_cluster_best_node() {
int i;
int best_node = -1;
struct uwsgi_cluster_node *ucn;
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;
}
}
}
}
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;
}
if (best_node == -1) {
return NULL;
}
uwsgi.shared->nodes[best_node].last_choosen = uwsgi_now();
return uwsgi.shared->nodes[best_node].name;
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;
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
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("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("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("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);
}
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;
struct uwsgi_cluster_node nucn;
switch (uwsgi.workers[0].cores[0].req.uh.modifier1) {
case 95:
memset(&nucn, 0, sizeof(struct uwsgi_cluster_node));
switch (uwsgi.workers[0].cores[0].req.uh.modifier1) {
case 95:
memset(&nucn, 0, sizeof(struct uwsgi_cluster_node));
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.wsgi_requests[0]->uh.pktsize);
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:
uwsgi_hooked_parse(uwsgi.workers[0].cores[0].req.buffer, uwsgi.workers[0].cores[0].req.uh.pktsize, manage_cluster_announce, &nucn);
if (nucn.name[0] != 0) {
uwsgi_cluster_add_node(&nucn, CLUSTER_NODE_DYNAMIC);
}
break;
case 96:
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.wsgi_requests[0]->uh.pktsize);
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:
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);
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;
}
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) {
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("%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);
//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;
struct uwsgi_header *uh = (struct uwsgi_header *) cluster_opt_buf;
uh->modifier1 = 99;
uh->pktsize = cluster_opt_size - 4;
uh->modifier2 = 1;
uh->modifier1 = 99;
uh->pktsize = cluster_opt_size - 4;
uh->modifier2 = 1;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(uh->pktsize);
uh->pktsize = uwsgi_swap16(uh->pktsize);
#endif
char *cptrbuf = cluster_opt_buf + 4;
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;
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;
}
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;
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++;
}
+191 -127
View File
@@ -6,7 +6,6 @@ a supervisor for multiple uWSGI instances
*/
#include "uwsgi.h"
#include <glob.h>
extern struct uwsgi_server uwsgi;
@@ -125,17 +124,12 @@ struct uwsgi_emperor_scanner *emperor_scanners;
int uwsgi_emperor_is_valid(char *name) {
if (uwsgi_endswith(name, ".xml") ||
uwsgi_endswith(name, ".ini") ||
uwsgi_endswith(name, ".yml") ||
uwsgi_endswith(name, ".yaml") ||
uwsgi_endswith(name, ".js") ||
uwsgi_endswith(name, ".json")) {
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json")) {
if (strlen(name) < 0xff) {
return 1;
}
if (strlen(name) < 0xff) {
return 1;
}
}
return 0;
@@ -155,48 +149,48 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
DIR *dir = opendir(".");
while ((de = readdir(dir)) != NULL) {
if (!uwsgi_emperor_is_valid(de->d_name))
continue;
if (!uwsgi_emperor_is_valid(de->d_name))
continue;
if (stat(de->d_name, &st))
continue;
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (!S_ISREG(st.st_mode))
continue;
ui_current = emperor_get(de->d_name);
ui_current = emperor_get(de->d_name);
if (ui_current) {
// check if uid or gid are changed, in such case, stop 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", de->d_name);
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);
if (ui_current) {
// check if uid or gid are changed, in such case, stop 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", de->d_name);
emperor_stop(ui_current);
continue;
}
}
else {
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
// 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(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
closedir(dir);
// now check for removed instances
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
while (c_ui) {
if (c_ui->scanner == ues) {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
c_ui = c_ui->ui_next;
}
c_ui = c_ui->ui_next;
}
}
// this is the monitor for glob patterns
@@ -213,50 +207,50 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
}
for (i = 0; i < (int) g.gl_pathc; i++) {
if (!uwsgi_emperor_is_valid(g.gl_pathv[i]))
continue;
if (stat(g.gl_pathv[i], &st))
continue;
if (!uwsgi_emperor_is_valid(g.gl_pathv[i]))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (stat(g.gl_pathv[i], &st))
continue;
ui_current = emperor_get(g.gl_pathv[i]);
if (!S_ISREG(st.st_mode))
continue;
if (ui_current) {
// check if uid or gid are changed, in such case, stop 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", g.gl_pathv[i]);
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);
ui_current = emperor_get(g.gl_pathv[i]);
if (ui_current) {
// check if uid or gid are changed, in such case, stop 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", g.gl_pathv[i]);
emperor_stop(ui_current);
continue;
}
}
else {
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
// 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(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
globfree(&g);
// now check for removed instances
struct uwsgi_instance *c_ui = ui->ui_next;
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
if (c_ui->scanner == ues) {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
c_ui = c_ui->ui_next;
}
while (c_ui) {
if (c_ui->scanner == ues) {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
c_ui = c_ui->ui_next;
}
}
@@ -308,7 +302,7 @@ static void royal_death(int signum) {
}
}
uwsgi_log("[emperor] *** RAGNAROK EVOKED ***\n");
uwsgi_log("[emperor] *** RAGNAROK EVOKED ***\n");
uwsgi_notify("The Emperor is buried.");
exit(0);
}
@@ -498,7 +492,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
if (uwsgi.emperor_tyrant) {
if (uid == 0 || gid == 0) {
uwsgi_log("[emperor-tyrant] invalid permissions for file %s\n", name);
uwsgi_log("[emperor-tyrant] invalid permissions for vassal %s\n", name);
return;
}
}
@@ -714,7 +708,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
exit(1);
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0)) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
@@ -768,14 +762,14 @@ void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
uwsgi.emperor_absolute_dir = uwsgi.cwd;
if (!uwsgi_startswith(ues->arg, "glob://", 7)) {
ues->arg+=7;
ues->arg += 7;
}
}
void uwsgi_imperial_monitor_directory_init(struct uwsgi_emperor_scanner *ues) {
if (!uwsgi_startswith(ues->arg, "dir://", 6)) {
ues->arg+=6;
ues->arg += 6;
}
if (chdir(ues->arg)) {
@@ -789,6 +783,8 @@ void uwsgi_imperial_monitor_directory_init(struct uwsgi_emperor_scanner *ues) {
exit(1);
}
ues->arg = uwsgi.emperor_absolute_dir;
}
struct uwsgi_imperial_monitor *imperial_monitor_get_by_id(char *scheme) {
@@ -881,13 +877,13 @@ next:
int uwsgi_emperor_scanner_event(int fd) {
struct uwsgi_emperor_scanner *ues = emperor_scanners;
while (ues) {
while (ues) {
if (ues->fd > -1 && ues->fd == fd) {
ues->event_func(ues);
return 1;
}
ues = ues->next;
}
ues = ues->next;
}
return 0;
@@ -993,9 +989,10 @@ void emperor_loop() {
}
// check if a monitor is mapped to that file descriptor
if (uwsgi_emperor_scanner_event(interesting_fd)) continue;
if (uwsgi_emperor_scanner_event(interesting_fd))
continue;
ui_current = emperor_get_by_fd(interesting_fd);
if (ui_current) {
char byte;
@@ -1025,7 +1022,7 @@ void emperor_loop() {
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(NULL, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
free(zerg_name);
}
}
@@ -1041,9 +1038,9 @@ void emperor_loop() {
// check for heartbeat (if required)
ui_current = ui->ui_next;
while(ui_current) {
while (ui_current) {
if (ui_current->last_heartbeat > 0) {
if ( (ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) {
if ((ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) {
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
// set last_heartbeat to 0 avoiding races
ui_current->last_heartbeat = 0;
@@ -1076,7 +1073,20 @@ void emperor_loop() {
diedpid = 0;
}
if (diedpid < 0) {
uwsgi_error("waitpid()");
// it looks like it happens when OOM is triggered to Linux cgroup, but it could be a uWSGI bug :P
// by the way, fallback to a clean situation...
if (errno == ECHILD) {
uwsgi_log("--- MUTINY DETECTED !!! IMPALING VASSALS... ---\n");
ui_current = ui->ui_next;
while (ui_current) {
struct uwsgi_instance *rebel_vassal = ui_current;
ui_current = ui_current->ui_next;
emperor_del(rebel_vassal);
}
}
else {
uwsgi_error("waitpid()");
}
}
ui_current = ui;
while (ui_current->ui_next) {
@@ -1129,6 +1139,13 @@ void emperor_send_stats(int fd) {
return;
}
if (uwsgi.stats_http) {
if (uwsgi_send_http_stats(client_fd)) {
close(client_fd);
return;
}
}
struct uwsgi_stats *us = uwsgi_stats_new(8192);
if (uwsgi_stats_keyval_comma(us, "version", UWSGI_VERSION))
@@ -1208,6 +1225,9 @@ void emperor_send_stats(int fd) {
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) c_ui->gid))
goto end0;
if (uwsgi_stats_keyval_comma(us, "monitor", c_ui->scanner->arg))
goto end0;
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) c_ui->respawns))
goto end0;
@@ -1227,49 +1247,49 @@ void emperor_send_stats(int fd) {
goto end0;
if (uwsgi_stats_comma(us))
goto end0;
goto end0;
if (uwsgi_stats_key(us, "blacklist"))
goto end0;
if (uwsgi_stats_list_open(us))
goto end0;
goto end0;
if (uwsgi_stats_list_open(us))
goto end0;
struct uwsgi_emperor_blacklist_item *uebi = emperor_blacklist;
while (uebi) {
while (uebi) {
if (uwsgi_stats_object_open(us))
goto end0;
goto end0;
if (uwsgi_stats_keyval_comma(us, "id", uebi->id))
goto end0;
if (uwsgi_stats_keyval_comma(us, "id", uebi->id))
goto end0;
if (uwsgi_stats_keylong_comma(us, "throttle_level", uebi->throttle_level/1000))
goto end0;
if (uwsgi_stats_keylong_comma(us, "throttle_level", uebi->throttle_level / 1000))
goto end0;
if (uwsgi_stats_keylong_comma(us, "attempt", (unsigned long long) uebi->attempt))
goto end0;
if (uwsgi_stats_keylong_comma(us, "attempt", (unsigned long long) uebi->attempt))
goto end0;
if (uwsgi_stats_keylong_comma(us, "first_attempt", (unsigned long long) uebi->first_attempt.tv_sec))
goto end0;
if (uwsgi_stats_keylong_comma(us, "first_attempt", (unsigned long long) uebi->first_attempt.tv_sec))
goto end0;
if (uwsgi_stats_keylong(us, "last_attempt", (unsigned long long) uebi->last_attempt.tv_sec))
goto end0;
if (uwsgi_stats_keylong(us, "last_attempt", (unsigned long long) uebi->last_attempt.tv_sec))
goto end0;
if (uwsgi_stats_object_close(us))
goto end0;
goto end0;
uebi = uebi->next;
uebi = uebi->next;
if (uebi) {
if (uwsgi_stats_comma(us))
goto end0;
}
}
}
if (uwsgi_stats_list_close(us))
goto end0;
goto end0;
if (uwsgi_stats_object_close(us))
goto end0;
@@ -1277,6 +1297,10 @@ void emperor_send_stats(int fd) {
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) {
@@ -1299,42 +1323,82 @@ end:
void uwsgi_emperor_start() {
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.master_process) {
uwsgi_notify_ready();
emperor_loop();
// never here
exit(1);
}
if (uwsgi.emperor_procname) {
uwsgi_set_processname(uwsgi.emperor_procname);
}
uwsgi_notify_ready();
emperor_loop();
// never here
exit(1);
}
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
}
else if (uwsgi.emperor_pid == 0) {
if (uwsgi.emperor_procname) {
uwsgi.emperor_pid = uwsgi_fork(uwsgi.emperor_procname);
}
else {
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
}
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
}
else if (uwsgi.emperor_pid == 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
emperor_loop();
// never here
exit(1);
}
emperor_loop();
// never here
exit(1);
}
}
void uwsgi_check_emperor() {
char *emperor_env = getenv("UWSGI_EMPEROR_FD");
if (emperor_env) {
uwsgi.has_emperor = 1;
uwsgi.emperor_fd = atoi(emperor_env);
uwsgi.master_process = 1;
uwsgi.no_orphans = 1;
uwsgi_log("*** has_emperor mode detected (fd: %d) ***\n", uwsgi.emperor_fd);
if (emperor_env) {
uwsgi.has_emperor = 1;
uwsgi.emperor_fd = atoi(emperor_env);
uwsgi.master_process = 1;
uwsgi.no_orphans = 1;
uwsgi_log("*** has_emperor mode detected (fd: %d) ***\n", uwsgi.emperor_fd);
if (getenv("UWSGI_EMPEROR_FD_CONFIG")) {
uwsgi.emperor_fd_config = atoi(getenv("UWSGI_EMPEROR_FD_CONFIG"));
}
}
if (getenv("UWSGI_EMPEROR_FD_CONFIG")) {
uwsgi.emperor_fd_config = atoi(getenv("UWSGI_EMPEROR_FD_CONFIG"));
}
}
}
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
if (!uwsgi_emperor_is_valid(name))
return;
struct uwsgi_instance *ui_current = emperor_get(name);
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (uid != ui_current->uid || gid != ui_current->gid) {
uwsgi_log("[emperor-tyrant] !!! permissions of vassal %s changed. stopping the instance... !!!\n", name);
emperor_stop(ui_current);
return;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (ts > ui_current->last_mod) {
// make a new config (free the old one)
free(ui_current->config);
ui_current->config = config;
ui_current->config_len = strlen(config);
// always respawn (no need for amqp-style rules)
emperor_respawn(ui_current, ts);
}
}
else {
// make a copy of the config as it will be freed
emperor_add(ues, name, ts, uwsgi_str(config), strlen((const char *) config), uid, gid);
}
}
+532 -313
View File
File diff suppressed because it is too large Load Diff
+85 -80
View File
@@ -2,29 +2,29 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(int, void *), void *data) {
struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), void *data) {
struct uwsgi_gateway *ug;
int num=1,i;
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;
}
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++;
}
}
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 = &ushared->gateways[ushared->gateways_cnt];
ug->pid = 0;
ug->name = name;
ug->loop = loop;
ug->num = num;
ug->fullname = fullname;
ug->data = data;
@@ -35,10 +35,14 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(int, void *), vo
if (!uwsgi.master_process)
gateway_respawn(ushared->gateways_cnt);
ushared->gateways_cnt++;
ushared->gateways_cnt++;
return ug;
return ug;
}
static void gateway_brutal_end() {
_exit(UWSGI_END_CODE);
}
void gateway_respawn(int id) {
@@ -48,114 +52,115 @@ void gateway_respawn(int id) {
if (uwsgi.master_process)
uwsgi.shared->gateways_harakiri[id] = 0;
gw_pid = uwsgi_fork(ug->fullname);
if (gw_pid < 0) {
uwsgi_error("fork()");
uwsgi_error("fork()");
return;
}
if (gw_pid == 0) {
uwsgi_fixup_fds(0, 0, ug);
if (uwsgi.master_as_root) uwsgi_as_root();
if (uwsgi.master_as_root)
uwsgi_as_root();
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
uwsgi.mypid = getpid();
atexit(gateway_brutal_end);
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);
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);
_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);
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);
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;
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;
}
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;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
uwsgi_sock->fd = -1;
uwsgi_sock->shared = 0;
uwsgi_sock->name = name;
uwsgi_sock->name = name;
uwsgi_sock->name_len = strlen(name);
uwsgi_sock->owner = owner;
return uwsgi_sock;
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;
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;
}
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;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
uwsgi_sock->fd = fd;
uwsgi_sock->name = uwsgi_getsockname(fd);
uwsgi_sock->name = uwsgi_getsockname(fd);
uwsgi_sock->name_len = strlen(uwsgi_sock->name);
uwsgi_sock->owner = owner;
uwsgi_sock->owner = owner;
return uwsgi_sock;
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;
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);
}
}
}
+209 -168
View File
@@ -7,99 +7,112 @@ void uwsgi_init_default() {
uwsgi.cpus = 1;
uwsgi.backtrace_depth = 64;
uwsgi.max_apps = 64;
uwsgi.max_apps = 64;
uwsgi.master_queue = -1;
uwsgi.master_queue = -1;
uwsgi.signal_socket = -1;
uwsgi.my_signal_socket = -1;
uwsgi.cache_server_fd = -1;
uwsgi.stats_fd = -1;
uwsgi.signal_socket = -1;
uwsgi.my_signal_socket = -1;
uwsgi.cache_server_fd = -1;
uwsgi.stats_fd = -1;
uwsgi.original_log_fd = -1;
uwsgi.stats_pusher_default_freq = 3;
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.original_log_fd = -1;
uwsgi.subscribe_freq = 10;
uwsgi.subscription_tolerance = 17;
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.cluster_fd = -1;
uwsgi.cores = 1;
uwsgi.threads = 1;
uwsgi.subscribe_freq = 10;
uwsgi.subscription_tolerance = 17;
uwsgi.default_app = -1;
uwsgi.cluster_fd = -1;
uwsgi.cores = 1;
uwsgi.threads = 1;
uwsgi.buffer_size = 4096;
uwsgi.numproc = 1;
uwsgi.offload_threads_events = 64;
uwsgi.forkbomb_delay = 2;
uwsgi.default_app = -1;
uwsgi.async = 1;
uwsgi.listen_queue = 100;
uwsgi.buffer_size = 4096;
uwsgi.numproc = 1;
uwsgi.cheaper_overload = 3;
uwsgi.forkbomb_delay = 2;
uwsgi.log_master_bufsize = 8192;
uwsgi.async = 1;
uwsgi.listen_queue = 100;
uwsgi.max_vars = MAX_VARS;
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
uwsgi.cheaper_overload = 3;
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
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_frequency = 30;
uwsgi.shared->spooler_signal_pipe[0] = -1;
uwsgi.shared->spooler_signal_pipe[1] = -1;
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_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->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;
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;
// 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_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()");
}
}
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()");
}
}
}
@@ -108,33 +121,33 @@ 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, "_");
}
}
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, ",");
}
}
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, ",");
}
}
}
@@ -143,112 +156,140 @@ void uwsgi_commandline_config() {
uwsgi.option_index = -1;
char *optname;
while ((i = getopt_long(uwsgi.argc, uwsgi.argv, uwsgi.short_options, uwsgi.long_options, &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 (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);
}
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);
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;
}
}
}
}
}
}
}
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;
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));
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);
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);
// 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 *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);
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);
}
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);
}
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);
// 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);
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 {
+215 -139
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,6 +45,10 @@ 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;
@@ -60,36 +64,50 @@ int uwsgi_pthread_robust_mutexes_enabled = 1;
#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_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_NP)) {
uwsgi_log("unable to make the mutex 'robust'\n");
exit(1);
}
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)) {
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");
@@ -99,9 +117,9 @@ retry:
goto retry;
}
#endif
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
pthread_mutexattr_destroy(&attr);
@@ -116,25 +134,25 @@ retry:
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
}
@@ -149,7 +167,7 @@ void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
#else
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
#endif
uli->pid = uwsgi.mypid;
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
@@ -164,7 +182,7 @@ void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
#else
pthread_rwlock_rdlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
uli->pid = uwsgi.mypid;
#endif
}
@@ -173,7 +191,7 @@ void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
#else
pthread_rwlock_wrlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
uli->pid = uwsgi.mypid;
#endif
}
@@ -182,7 +200,7 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
#else
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = 0;
uli->pid = 0;
#endif
}
@@ -196,20 +214,20 @@ struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
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);
@@ -235,36 +253,46 @@ 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)
@@ -275,36 +303,46 @@ pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_f
#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);
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;
return uli;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
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;
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;
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;
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); }
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)
@@ -342,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
@@ -384,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;
@@ -400,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) {
@@ -418,7 +464,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
uwsgi_error("semctl()");
exit(1);
}
return uli;
}
@@ -434,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) {
@@ -449,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) {
@@ -467,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;
@@ -482,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)) {
@@ -493,7 +551,9 @@ 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() {
@@ -514,8 +574,10 @@ void uwsgi_setup_locking() {
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_ipcsem;
uwsgi.lock_size = 8;
uwsgi.rwlock_size = 8;
return;
goto ready;
}
uwsgi_log("unable to find lock engine \"%s\"\n", uwsgi.lock_engine);
exit(1);
}
uwsgi_log_initial("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
@@ -536,37 +598,43 @@ void uwsgi_setup_locking() {
// 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)));
}
ready:
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.threads > 1) {
pthread_mutex_init(&uwsgi.thunder_mutex, NULL);
}
if (uwsgi.master_process) {
// signal table lock
uwsgi.signal_table_lock = uwsgi_lock_init("signal");
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");
// fmon table lock
uwsgi.fmon_table_lock = uwsgi_lock_init("filemon");
// timer table lock
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
// timer table lock
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
// probe table lock
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
// probe table lock
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
// rb_timer table lock
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
// rb_timer table lock
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
// cron table lock
uwsgi.cron_table_lock = uwsgi_lock_init("cron");
}
// cron table lock
uwsgi.cron_table_lock = uwsgi_lock_init("cron");
}
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
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");
}
@@ -589,43 +657,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_SET;
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);
}
}
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;
}
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]);
}
+625 -376
View File
File diff suppressed because it is too large Load Diff
+93 -44
View File
@@ -10,70 +10,119 @@ struct wsgi_request *simple_current_wsgi_req() {
}
void uwsgi_register_loop(char *name, void *loop) {
void uwsgi_register_loop(char *name, void (*func) (void)) {
if (uwsgi.loops_cnt >= MAX_LOOPS) {
uwsgi_log("you can define %d loops at max\n", MAX_LOOPS);
exit(1);
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;
}
uwsgi.loops[uwsgi.loops_cnt].name = name;
uwsgi.loops[uwsgi.loops_cnt].loop = loop;
uwsgi.loops_cnt++;
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) {
int i;
struct uwsgi_loop *loop = uwsgi.loops;
for (i = 0; i < uwsgi.loops_cnt; i++) {
if (!strcmp(name, uwsgi.loops[i].name)) {
return uwsgi.loops[i].loop;
while (loop) {
if (!strcmp(name, loop->name)) {
return loop->loop;
}
loop = loop->next;
}
return NULL;
}
void *simple_loop(void *arg1) {
/*
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
int i;
sigset_t smask;
if (uwsgi.threads > 1) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
#ifdef UWSGI_DEBUG
sigdelset(&smask, SIGSEGV);
#endif
pthread_sigmask(SIG_BLOCK, &smask, NULL);
// run per-thread socket hook
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (uwsgi_sock->proto_thread_fixup) {
uwsgi_sock->proto_thread_fixup(uwsgi_sock, core_id);
}
uwsgi_sock = uwsgi_sock->next;
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
}
uwsgi_setup_thread_req(core_id, wsgi_req);
}
#endif
+113 -66
View File
@@ -15,8 +15,8 @@ void uwsgi_restore_auto_snapshot(int signum) {
void uwsgi_block_signal(int signum) {
sigset_t smask;
sigemptyset(&smask);
sigaddset(&smask, signum);
sigemptyset(&smask);
sigaddset(&smask, signum);
if (sigprocmask(SIG_BLOCK, &smask, NULL)) {
uwsgi_error("sigprocmask()");
}
@@ -24,8 +24,8 @@ void uwsgi_block_signal(int signum) {
void uwsgi_unblock_signal(int signum) {
sigset_t smask;
sigemptyset(&smask);
sigaddset(&smask, signum);
sigemptyset(&smask);
sigaddset(&smask, signum);
if (sigprocmask(SIG_UNBLOCK, &smask, NULL)) {
uwsgi_error("sigprocmask()");
}
@@ -231,28 +231,28 @@ int uwsgi_master_check_mercy() {
}
void expire_rb_timeouts(struct rb_root *root) {
void expire_rb_timeouts(struct uwsgi_rbtree *tree) {
time_t current = uwsgi_now();
uint64_t current = (uint64_t) uwsgi_now();
struct uwsgi_rb_timer *urbt;
struct uwsgi_signal_rb_timer *usrbt;
for (;;) {
urbt = uwsgi_min_rb_timer(root);
urbt = uwsgi_min_rb_timer(tree, NULL);
if (urbt == NULL)
return;
if (urbt->key <= current) {
if (urbt->value <= current) {
// remove the timeout and add another
usrbt = (struct uwsgi_signal_rb_timer *) urbt->data;
rb_erase(&usrbt->uwsgi_rb_timer->rbt, root);
free(usrbt->uwsgi_rb_timer);
uwsgi_del_rb_timer(tree, urbt);
free(urbt);
usrbt->iterations_done++;
uwsgi_route_signal(usrbt->sig);
if (!usrbt->iterations || usrbt->iterations_done < usrbt->iterations) {
usrbt->uwsgi_rb_timer = uwsgi_add_rb_timer(root, uwsgi_now() + usrbt->value, usrbt);
usrbt->uwsgi_rb_timer = uwsgi_add_rb_timer(tree, uwsgi_now() + usrbt->value, usrbt);
}
continue;
}
@@ -265,23 +265,62 @@ int uwsgi_master_log(void) {
ssize_t rlen = read(uwsgi.shared->worker_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
if (rlen > 0) {
#ifdef UWSGI_ALARM
uwsgi_alarm_log_check(uwsgi.log_master_buf, rlen);
#endif
#ifdef UWSGI_PCRE
struct uwsgi_regexp_list *url = uwsgi.log_drain_rules;
while(url) {
while (url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
return 0;
}
url = url->next;
}
#endif
if (uwsgi.choosen_logger) {
struct uwsgi_logger *ul = uwsgi.choosen_logger;
while(ul) {
ul->func(ul, uwsgi.log_master_buf, rlen);
ul = ul->next;
if (uwsgi.log_filter_rules) {
int show = 0;
url = uwsgi.log_filter_rules;
while (url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
show = 1;
break;
}
url = url->next;
}
if (!show)
return 0;
}
else {
url = uwsgi.log_route;
int finish = 0;
while (url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
if (ul_route) {
ul_route->func(ul_route, uwsgi.log_master_buf, rlen);
finish = 1;
}
}
url = url->next;
}
if (finish)
return 0;
#endif
int raw_log = 1;
struct uwsgi_logger *ul = uwsgi.choosen_logger;
while (ul) {
// check for named logger
if (ul->id) {
goto next;
}
ul->func(ul, uwsgi.log_master_buf, rlen);
raw_log = 0;
next:
ul = ul->next;
}
if (raw_log) {
rlen = write(uwsgi.original_log_fd, uwsgi.log_master_buf, rlen);
}
return 0;
@@ -481,13 +520,13 @@ clear:
}
#ifdef __linux__
void get_linux_tcp_info(int fd) {
int get_linux_tcp_info(int fd) {
socklen_t tis = sizeof(struct tcp_info);
if (!getsockopt(fd, IPPROTO_TCP, TCP_INFO, &uwsgi.shared->ti, &tis)) {
// a check for older linux kernels
if (!uwsgi.shared->ti.tcpi_sacked) {
return;
return -1;
}
uwsgi.shared->load = uwsgi.shared->ti.tcpi_unacked;
@@ -509,7 +548,11 @@ void get_linux_tcp_info(int fd) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%d/%d) ***\n", fd, uwsgi.shared->ti.tcpi_unacked, uwsgi.shared->ti.tcpi_sacked);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
return uwsgi.shared->ti.tcpi_unacked;
}
return -1;
}
#include <linux/sockios.h>
@@ -520,7 +563,7 @@ void get_linux_tcp_info(int fd) {
#ifdef SIOBKLGQ
void get_linux_unbit_SIOBKLGQ(int fd) {
int get_linux_unbit_SIOBKLGQ(int fd) {
int queue = 0;
if (ioctl(fd, SIOBKLGQ, &queue) >= 0) {
@@ -530,8 +573,11 @@ void get_linux_unbit_SIOBKLGQ(int fd) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%d/%d) ***\n", fd, queue, uwsgi.listen_queue);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
return queue;
}
return -1;
}
#endif
#endif
@@ -576,7 +622,7 @@ int master_loop(char **argv, char **environ) {
int check_interval = 1;
struct uwsgi_rb_timer *min_timeout;
struct rb_root *rb_timers = uwsgi_init_rb_timer();
struct uwsgi_rbtree *rb_timers = uwsgi_init_rb_timer();
if (uwsgi.procname_master) {
@@ -644,6 +690,11 @@ int master_loop(char **argv, char **environ) {
uwsgi.threaded_logger = 0;
}
}
#ifdef UWSGI_ALARM
// initialize the alarm subsystem
uwsgi_alarms_init();
#endif
}
if (uwsgi.cache_max_items > 0 && !uwsgi.cache_no_expire) {
@@ -685,6 +736,15 @@ int master_loop(char **argv, char **environ) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.stats_fd);
uwsgi_log("*** Stats server enabled on %s fd: %d ***\n", uwsgi.stats, uwsgi.stats_fd);
}
if (uwsgi.stats_pusher_instances) {
if (!uwsgi_thread_new(uwsgi_stats_pusher_loop)) {
uwsgi_log("!!! unable to spawn stats pusher thread !!!\n");
exit(1);
}
}
#ifdef UWSGI_UDP
if (uwsgi.udp_socket) {
udp_fd = bind_to_udp(uwsgi.udp_socket, 0, 0);
@@ -733,15 +793,7 @@ int master_loop(char **argv, char **environ) {
}
// spawn daemons
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (!ud->registered) {
spawn_daemon(ud);
ud->registered = 1;
}
ud = ud->next;
}
uwsgi_daemons_spawn_all();
// first subscription
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
@@ -805,9 +857,11 @@ int master_loop(char **argv, char **environ) {
}
}
uwsgi_daemons_smart_check();
if (uwsgi.to_outworld) {
//uwsgi_log("%d/%d\n", uwsgi.lazy_respawned, uwsgi.numproc);
if (uwsgi.lazy_respawned >= uwsgi.numproc || (uwsgi.cheaper && uwsgi.lazy_respawned == uwsgi.cheaper_count)) {
if (uwsgi.lazy_respawned >= uwsgi.marked_workers || uwsgi.lazy_respawned >= uwsgi.numproc) {
uwsgi.to_outworld = 0;
uwsgi.master_mercy = 0;
uwsgi.lazy_respawned = 0;
@@ -838,8 +892,7 @@ int master_loop(char **argv, char **environ) {
return 0;
}
if ((uwsgi.cheap || uwsgi.ready_to_die >= uwsgi.numproc) && uwsgi.to_hell) {
if ((uwsgi.cheap || uwsgi.ready_to_die >= uwsgi.marked_workers || uwsgi.ready_to_die >= uwsgi.numproc) && uwsgi.to_hell) {
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
@@ -849,7 +902,7 @@ int master_loop(char **argv, char **environ) {
exit(0);
}
if ((uwsgi.cheap || uwsgi.ready_to_reload >= uwsgi.numproc) && uwsgi.to_heaven) {
if ((uwsgi.cheap || uwsgi.ready_to_reload >= uwsgi.marked_workers || uwsgi.ready_to_reload >= uwsgi.numproc) && uwsgi.to_heaven) {
uwsgi_reload(argv);
// never here (unless in shared library mode)
return -1;
@@ -922,12 +975,12 @@ int master_loop(char **argv, char **environ) {
int interesting_fd = -1;
if (ushared->rb_timers_cnt > 0) {
min_timeout = uwsgi_min_rb_timer(rb_timers);
min_timeout = uwsgi_min_rb_timer(rb_timers, NULL);
if (min_timeout == NULL) {
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
}
else {
check_interval = min_timeout->key - uwsgi_now();
check_interval = min_timeout->value - uwsgi_now();
if (check_interval <= 0) {
expire_rb_timeouts(rb_timers);
check_interval = 0;
@@ -981,7 +1034,7 @@ int master_loop(char **argv, char **environ) {
if (uwsgi.stats && uwsgi.stats_fd > -1) {
if (interesting_fd == uwsgi.stats_fd) {
uwsgi_send_stats(uwsgi.stats_fd);
uwsgi_send_stats(uwsgi.stats_fd, uwsgi_master_generate_stats);
goto health_cycle;
}
}
@@ -1192,12 +1245,12 @@ health_cycle:
int busy_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
if (uwsgi.workers[i].busy == 1) {
busy_workers = 1;
break;
}
}
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
if (uwsgi.workers[i].busy == 1) {
busy_workers = 1;
break;
}
}
}
if (last_request_count != uwsgi.workers[0].requests) {
@@ -1248,11 +1301,11 @@ health_cycle:
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_INET) {
get_linux_tcp_info(uwsgi_sock->fd);
uwsgi_sock->queue = get_linux_tcp_info(uwsgi_sock->fd);
}
#ifdef SIOBKLGQ
else if (uwsgi_sock->family == AF_UNIX) {
get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd);
uwsgi_sock->queue = get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd);
}
#endif
uwsgi_sock = uwsgi_sock->next;
@@ -1408,6 +1461,12 @@ health_cycle:
continue;
#endif
if (uwsgi.emperor_pid >= 0 && diedpid == uwsgi.emperor_pid) {
uwsgi_log_verbose("!!! Emperor died !!!\n");
uwsgi_emperor_start();
continue;
}
pid_found = 0;
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].pid == diedpid) {
@@ -1436,17 +1495,7 @@ health_cycle:
continue;
/* reload the daemons */
// TODO reload_daemons(diedpid);
pid_found = 0;
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid == diedpid) {
spawn_daemon(ud);
pid_found = 1;
break;
}
ud = ud->next;
}
pid_found = uwsgi_daemon_check_pid_reload(diedpid);
if (pid_found)
continue;
@@ -1492,14 +1541,8 @@ health_cycle:
}
}
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid == diedpid) {
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
goto next;
}
ud = ud->next;
}
if (uwsgi_daemon_check_pid_death(diedpid))
goto next;
if (WIFEXITED(waitpid_status)) {
uwsgi_log("subprocess %d exited with code %d\n", (int) diedpid, WEXITSTATUS(waitpid_status));
@@ -1558,6 +1601,10 @@ next:
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
}
}
// manage_next_request is zero, but killed by signal...
else if (WIFSIGNALED(waitpid_status)) {
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
}
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
uwsgi.workers[uwsgi.mywid].pid = 0;
+354 -230
View File
@@ -7,24 +7,25 @@ void worker_wakeup() {
void uwsgi_master_cleanup_hooks(void) {
int j;
int j;
// could be an inherited atexit hook
if (uwsgi.mywid > 0) return ;
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 < 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();
}
}
for (j = 0; j < 256; j++) {
if (uwsgi.p[j]->master_cleanup) {
uwsgi.p[j]->master_cleanup();
}
}
}
@@ -492,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) {
@@ -505,29 +528,39 @@ 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].user_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];
@@ -548,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);
}
@@ -736,18 +772,9 @@ void uwsgi_manage_command_cron(time_t now) {
}
void uwsgi_send_stats(int fd) {
struct uwsgi_stats *uwsgi_master_generate_stats() {
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;
}
int i;
struct uwsgi_stats *us = uwsgi_stats_new(8192);
@@ -761,6 +788,14 @@ void uwsgi_send_stats(int fd) {
goto end;
#endif
int signal_queue = 0;
if (ioctl(uwsgi.shared->worker_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_stats_keylong_comma(us, "load", (unsigned long long) uwsgi.shared->load))
goto end;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) getpid()))
@@ -771,248 +806,335 @@ void uwsgi_send_stats(int fd) {
goto end;
char *cwd = uwsgi_get_cwd();
if (uwsgi_stats_keyval_comma(us, "cwd", cwd))
goto end0;
if (uwsgi_stats_keyval_comma(us, "cwd", cwd)) {
free(cwd);
goto end;
}
free(cwd);
if (uwsgi.daemons) {
if (uwsgi_stats_key(us, "daemons"))
goto end0;
goto end;
if (uwsgi_stats_list_open(us))
goto end0;
goto end;
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (uwsgi_stats_object_open(us))
goto end0;
goto end;
if (uwsgi_stats_keyval_comma(us, "cmd", ud->command))
goto end0;
goto end;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) ud->pid))
goto end0;
goto end;
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) (ud->respawns - 1)))
goto end0;
goto end;
if (uwsgi_stats_object_close(us))
goto end0;
goto end;
if (ud->next) {
if (uwsgi_stats_comma(us))
goto end0;
goto end;
}
ud = ud->next;
}
if (uwsgi_stats_list_close(us))
goto end0;
goto end;
if (uwsgi_stats_comma(us))
goto end0;
goto end;
}
if (uwsgi_stats_key(us, "locks"))
goto end0;
goto end;
if (uwsgi_stats_list_open(us))
goto end0;
goto end;
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
while (uli) {
if (uwsgi_stats_object_open(us))
goto end0;
goto end;
if (uwsgi_stats_keylong(us, uli->id, (unsigned long long) uli->pid))
goto end0;
goto end;
if (uwsgi_stats_object_close(us))
goto end0;
goto end;
if (uli->next) {
if (uwsgi_stats_comma(us))
goto end0;
goto end;
}
uli = uli->next;
}
if (uwsgi_stats_list_close(us))
goto end0;
goto end;
if (uwsgi_stats_comma(us))
goto end0;
goto end;
if (uwsgi_stats_key(us, "sockets"))
goto end;
if (uwsgi_stats_key(us, "workers"))
goto end0;
if (uwsgi_stats_list_open(us))
goto end0;
goto end;
for (i = 0; i < uwsgi.numproc; i++) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_stats_object_open(us))
goto end0;
goto end;
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) uwsgi.workers[i + 1].id))
goto end0;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
goto end0;
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
goto end0;
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
goto end0;
if (uwsgi_stats_keylong_comma(us, "exceptions", (unsigned long long) uwsgi.workers[i + 1].exceptions))
goto end0;
if (uwsgi_stats_keylong_comma(us, "harakiri_count", (unsigned long long) uwsgi.workers[i + 1].harakiri_count))
goto end0;
if (uwsgi_stats_keylong_comma(us, "signals", (unsigned long long) uwsgi.workers[i + 1].signals))
goto end0;
if (uwsgi_stats_keylong_comma(us, "static_offload_threads", (unsigned long long) uwsgi.workers[i + 1].static_offload_threads))
goto end0;
if (uwsgi_stats_keyval_comma(us, "name", uwsgi_sock->name))
goto end;
if (uwsgi.workers[i + 1].cheaped) {
if (uwsgi_stats_keyval_comma(us, "status", "cheap"))
goto end0;
}
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
if (uwsgi_stats_keyval_comma(us, "status", "pause"))
goto end0;
}
else {
if (uwsgi.workers[i + 1].sig) {
if (uwsgi_stats_keyvalnum_comma(us, "status", "sig", (unsigned long long) uwsgi.workers[i + 1].signum))
goto end0;
}
else if (uwsgi.workers[i + 1].busy) {
if (uwsgi_stats_keyval_comma(us, "status", "busy"))
goto end0;
}
else {
if (uwsgi_stats_keyval_comma(us, "status", "idle"))
goto end0;
}
}
if (uwsgi_stats_keyval_comma(us, "proto", uwsgi_sock->proto_name ? uwsgi_sock->proto_name : "uwsgi"))
goto end;
if (uwsgi_stats_keylong_comma(us, "rss", (unsigned long long) uwsgi.workers[i + 1].rss_size))
goto end0;
if (uwsgi_stats_keylong_comma(us, "vsz", (unsigned long long) uwsgi.workers[i + 1].vsz_size))
goto end0;
if (uwsgi_stats_keylong_comma(us, "queue", (unsigned long long) uwsgi_sock->queue))
goto end;
if (uwsgi_stats_keylong_comma(us, "running_time", (unsigned long long) uwsgi.workers[i + 1].running_time))
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_spawn", (unsigned long long) uwsgi.workers[i + 1].last_spawn))
goto end0;
if (uwsgi_stats_keylong_comma(us, "respawn_count", (unsigned long long) uwsgi.workers[i + 1].respawn_count))
goto end0;
if (uwsgi_stats_keylong_comma(us, "shared", (unsigned long long) uwsgi_sock->shared))
goto end;
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) uwsgi.workers[i + 1].tx))
goto end0;
if (uwsgi_stats_keylong_comma(us, "avg_rt", (unsigned long long) uwsgi.workers[i + 1].avg_response_time))
goto end0;
// applications list
if (uwsgi_stats_key(us, "apps"))
goto end0;
if (uwsgi_stats_list_open(us))
goto end0;
for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
ua = &uwsgi.workers[i + 1].apps[j];
if (uwsgi_stats_object_open(us))
goto end0;
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j))
goto end0;
if (uwsgi_stats_keylong_comma(us, "modifier1", (unsigned long long) ua->modifier1))
goto end0;
if (uwsgi_stats_keyvaln_comma(us, "mountpoint", ua->mountpoint, ua->mountpoint_len))
goto end0;
if (uwsgi_stats_keylong_comma(us, "startup_time", ua->startup_time))
goto end0;
if (uwsgi_stats_keylong_comma(us, "requests", ua->requests))
goto end0;
if (uwsgi_stats_keylong_comma(us, "exceptions", ua->exceptions))
goto end0;
if (ua->chdir) {
if (uwsgi_stats_keyval(us, "chdir", ua->chdir))
goto end0;
}
else {
if (uwsgi_stats_keyval(us, "chdir", ""))
goto end0;
}
if (uwsgi_stats_object_close(us))
goto end0;
if (j < uwsgi.workers[i + 1].apps_cnt - 1) {
if (uwsgi_stats_comma(us))
goto end0;
}
}
if (uwsgi_stats_list_close(us))
goto end0;
if (uwsgi_stats_comma(us))
goto end0;
// cores list
if (uwsgi_stats_key(us, "cores"))
goto end0;
if (uwsgi_stats_list_open(us))
goto end0;
for (j = 0; j < uwsgi.cores; j++) {
struct uwsgi_core *uc = &uwsgi.workers[i + 1].cores[j];
if (uwsgi_stats_object_open(us))
goto end0;
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j))
goto end0;
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uc->requests))
goto end0;
if (uwsgi_stats_keylong(us, "in_request", (unsigned long long) uc->in_request))
goto end0;
if (uwsgi_stats_object_close(us))
goto end0;
if (j < uwsgi.cores-1) {
if (uwsgi_stats_comma(us))
goto end0;
}
}
if (uwsgi_stats_list_close(us))
goto end0;
if (uwsgi_stats_keylong(us, "can_offload", (unsigned long long) uwsgi_sock->can_offload))
goto end;
if (uwsgi_stats_object_close(us))
goto end0;
goto end;
if (i < uwsgi.numproc - 1) {
uwsgi_sock = uwsgi_sock->next;
if (uwsgi_sock) {
if (uwsgi_stats_comma(us))
goto end0;
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end0;
if (uwsgi_stats_object_close(us))
goto end0;
goto end;
size_t remains = us->pos;
off_t pos = 0;
while (remains > 0) {
ssize_t res = write(client_fd, us->base + pos, remains);
if (res <= 0) {
if (res < 0) {
uwsgi_error("write()");
}
goto end0;
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;
}
pos += res;
remains -= res;
}
end0:
free(cwd);
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);
close(client_fd);
return NULL;
}
void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
@@ -1046,7 +1168,7 @@ void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
void trigger_harakiri(int i) {
int j;
uwsgi_log("*** HARAKIRI ON WORKER %d (pid: %d) ***\n", i, uwsgi.workers[i].pid);
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;
@@ -1083,22 +1205,24 @@ void trigger_harakiri(int i) {
}
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);
}
}
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);
uwsgi.workers[i].harakiri_count++;
if (!uwsgi.workers[i].pending_harakiri)
uwsgi.workers[i].harakiri_count++;
uwsgi.workers[i].pending_harakiri++;
}
// to avoid races
+225 -209
View File
@@ -19,14 +19,14 @@ void mule_send_msg(int fd, char *message, size_t len) {
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()");
}
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()");
}
}
}
@@ -34,54 +34,65 @@ void uwsgi_mule(int id) {
int i;
pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
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()");
}
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.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.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);
}
}
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.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
if (uwsgi.mules[id-1].patch) {
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) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
// never here
break;
end_me(1);
}
}
}
}
}
uwsgi_mule_handler();
}
else if (pid > 0) {
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = pid;
uwsgi.mules[id - 1].id = id;
uwsgi.mules[id - 1].pid = pid;
uwsgi_log("spawned uWSGI mule %d (pid: %d)\n", id, (int) pid);
}
}
@@ -90,7 +101,7 @@ int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
struct uwsgi_mule_farm *umf = farm->mules;
while(umf) {
while (umf) {
if (umf->mule->id == muleid) {
return 1;
}
@@ -103,54 +114,54 @@ int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
int farm_has_signaled(int fd) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
for (i = 0; i < uwsgi.farms_cnt; i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while(umf) {
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;
}
}
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;
return 0;
}
void uwsgi_mule_add_farm_to_queue(int queue) {
int i;
for(i=0;i<uwsgi.farms_cnt;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]);
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];
@@ -158,12 +169,12 @@ void uwsgi_mule_handler() {
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.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(;;) {
for (;;) {
rlen = event_queue_wait(mule_queue, -1, &interesting_fd);
if (rlen <= 0) {
continue;
@@ -172,31 +183,31 @@ void uwsgi_mule_handler() {
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);
}
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);
}
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)) {
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)) {
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);
}
@@ -209,7 +220,7 @@ struct uwsgi_mule *get_mule_by_id(int id) {
int i;
for(i=0;i<uwsgi.mules_cnt;i++) {
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].id == id) {
return &uwsgi.mules[i];
}
@@ -220,229 +231,234 @@ struct uwsgi_mule *get_mule_by_id(int id) {
struct uwsgi_farm *get_farm_by_name(char *name) {
int i;
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (!strcmp(uwsgi.farms[i].name, name)) {
return &uwsgi.farms[i];
}
}
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (!strcmp(uwsgi.farms[i].name, name)) {
return &uwsgi.farms[i];
}
}
return NULL;
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;
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;
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 = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
old_umf->next = uwsgi_mf;
}
uwsgi_mf->mule = um;
uwsgi_mf->next = NULL;
uwsgi_mf->mule = um;
uwsgi_mf->next = NULL;
return uwsgi_mf;
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;
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 (uwsgi.muleid == 0)
return -1;
if (manage_signals) count = 2;
if (manage_signals)
count = 2;
if (!manage_farms) goto next;
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++;
}
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;
if (timeout > -1)
timeout = timeout * 1000;
mulepoll = uwsgi_malloc(sizeof(struct pollfd) * (count+farms_count));
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;
}
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++) {
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;
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;
}
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);
}
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);
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);
}
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;
}
}
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;
}
}
}
}
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;
}
if (len < 0) {
uwsgi_error("read()");
goto clear;
}
clear:
free(mulepoll);
return len;
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);
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);
}
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);
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);
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);
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);
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;
uwsgi.mules[i].id = i + 1;
snprintf(uwsgi.mules[i].name, 0xff, "uWSGI mule %d", 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);
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++) {
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 *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);
}
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++;
mules_list[0] = 0;
mules_list++;
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
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);
// 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);
}
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);
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);
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;
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;
}
+89 -58
View File
@@ -2,6 +2,28 @@
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;
@@ -12,7 +34,7 @@ static int plugin_already_loaded(const char *plugin) {
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
}
if (uwsgi.p[i]->alias) {
if (!strcmp(plugin, uwsgi.p[i]->alias)) {
@@ -20,29 +42,29 @@ static int plugin_already_loaded(const char *plugin) {
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
}
}
for(i=0;i<uwsgi.gp_cnt;i++) {
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->name) {
if (!strcmp(plugin, uwsgi.gp[i]->name)) {
if (!strcmp(plugin, uwsgi.gp[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
if (uwsgi.gp[i]->alias) {
if (!strcmp(plugin, uwsgi.gp[i]->alias)) {
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);
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
}
return 1;
}
}
}
return 0;
}
@@ -57,7 +79,6 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
char *plugin_name = plugin;
char *plugin_symbol_name_start = plugin;
struct uwsgi_plugin *up;
char linkpath_buf[1024], linkpath[1024];
int linkpath_size;
@@ -66,7 +87,7 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
if (colon) {
colon[0] = 0;
modifier = atoi(plugin_name);
plugin_name = colon+1;
plugin_name = colon + 1;
colon[0] = ':';
}
@@ -79,10 +100,13 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
// 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());
uwsgi_log("%s\n", dlerror());
goto end;
}
plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/');
@@ -93,8 +117,11 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
// step dir, check for user-supplied plugins directory
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
while(pdir) {
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;
@@ -109,19 +136,22 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
// 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 (!plugin_handle) {
if (!has_option)
uwsgi_log( "%s\n", dlerror());
}
else {
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start)-3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
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);
@@ -129,7 +159,7 @@ success:
if ((linkpath_size = readlink(plugin_abs_path, linkpath_buf, 1023)) > 0) {
do {
linkpath_buf[linkpath_size] = '\0';
strncpy(linkpath, linkpath_buf, linkpath_size+1);
strncpy(linkpath, linkpath_buf, linkpath_size + 1);
} while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0);
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", linkpath);
@@ -143,16 +173,16 @@ success:
else {
slash++;
}
plugin_entry_symbol = uwsgi_concat2n(slash, strlen(slash)-3, "",0);
plugin_entry_symbol = uwsgi_concat2n(slash, strlen(slash) - 3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
}
}
if (up) {
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()");
}
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
if (plugin_filename)
@@ -162,8 +192,8 @@ success:
}
if (plugin_already_loaded(up->name)) {
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
if (plugin_filename)
@@ -178,8 +208,8 @@ success:
if (!strcmp(has_option, op->name)) {
found = 1;
break;
}
op++;
}
op++;
}
if (!found) {
if (dlclose(plugin_handle)) {
@@ -192,14 +222,14 @@ success:
free(plugin_entry_symbol);
return NULL;
}
}
if (modifier != -1) {
fill_plugin_table(modifier, up);
fill_plugin_table(modifier, up);
up->modifier1 = modifier;
}
else {
fill_plugin_table(up->modifier1, up);
fill_plugin_table(up->modifier1, up);
}
if (need_free)
free(plugin_name);
@@ -210,10 +240,10 @@ success:
if (up->on_load)
up->on_load();
return plugin_handle;
}
}
if (!has_option)
uwsgi_log( "%s\n", dlerror());
}
uwsgi_log("%s\n", dlerror());
}
end:
if (need_free)
@@ -228,14 +258,14 @@ 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) {
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)) {
if (uwsgi_load_plugin(-1, filename, option)) {
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
free(filename);
closedir(d);
@@ -248,27 +278,28 @@ int uwsgi_try_autoload(char *option) {
}
closedir(d);
}
pdir = pdir->next;
}
pdir = pdir->next;
}
// last step: search in compile-time plugin_dir
// last step: search in compile-time plugin_dir
d = opendir(UWSGI_PLUGIN_DIR);
if (!d) return 0;
if (!d)
return 0;
while((dp = readdir(d)) != NULL) {
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;
}
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);
+702 -685
View File
File diff suppressed because it is too large Load Diff
+96 -89
View File
@@ -4,132 +4,136 @@ extern struct uwsgi_server uwsgi;
void uwsgi_init_queue() {
if (!uwsgi.queue_blocksize)
uwsgi.queue_blocksize = 8192;
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_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 (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 (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);
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);
}
// 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.queue_lock = uwsgi_rwlock_init("queue");
uwsgi_log("*** Queue subsystem initialized: %dMB preallocated ***\n", (uwsgi.queue_blocksize * uwsgi.queue_size) / (1024 * 1024));
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) {
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;
if (index >= uwsgi.queue_size)
return NULL;
ptr = ptr + (uwsgi.queue_blocksize*index);
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) {
char *uwsgi_queue_pop(uint64_t * size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (uwsgi.queue_header->pos == 0) {
uwsgi.queue_header->pos = uwsgi.queue_size-1;
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;
ptr = ptr + (uwsgi.queue_blocksize * uwsgi.queue_header->pos);
uqi = (struct uwsgi_queue_item *) ptr;
if (!uqi->size) return NULL;
if (!uqi->size)
return NULL;
*size = uqi->size;
*size = uqi->size;
// remove item
uqi->size = 0;
return ptr + sizeof(struct uwsgi_queue_item);
return ptr + sizeof(struct uwsgi_queue_item);
}
char *uwsgi_queue_pull(uint64_t *size) {
char *uwsgi_queue_pull(uint64_t * size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
char *ptr = (char *) uwsgi.queue;
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pull_pos);
ptr = ptr + (uwsgi.queue_blocksize * uwsgi.queue_header->pull_pos);
uqi = (struct uwsgi_queue_item *) ptr;
if (!uqi->size) return NULL;
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;
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);
}
@@ -142,9 +146,10 @@ int uwsgi_queue_push(char *message, uint64_t size) {
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (!size) return 0;
if (!size)
return 0;
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pos);
ptr = ptr + (uwsgi.queue_blocksize * uwsgi.queue_header->pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr += sizeof(struct uwsgi_queue_item);
@@ -154,33 +159,35 @@ int uwsgi_queue_push(char *message, uint64_t size) {
memcpy(ptr, message, size);
uwsgi.queue_header->pos++;
if (uwsgi.queue_header->pos >= uwsgi.queue_size) uwsgi.queue_header->pos = 0;
if (uwsgi.queue_header->pos >= uwsgi.queue_size)
uwsgi.queue_header->pos = 0;
return 1;
}
int uwsgi_queue_set(uint64_t pos, char *message, uint64_t size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (!size) return 0;
if (!size)
return 0;
if (pos >= uwsgi.queue_size) return 0;
if (pos >= uwsgi.queue_size)
return 0;
ptr = ptr + (uwsgi.queue_blocksize*pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr = ptr + (uwsgi.queue_blocksize * pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr += sizeof(struct uwsgi_queue_item);
ptr += sizeof(struct uwsgi_queue_item);
uqi->size = size;
uqi->ts = uwsgi_now();
memcpy(ptr, message, size);
uqi->size = size;
uqi->ts = uwsgi_now();
memcpy(ptr, message, size);
return 1;
return 1;
}
+334 -31
View File
@@ -1,64 +1,367 @@
/*
uWSGI timers implementation
uWSGI rbtree implementation based on nginx
based on Linux hrtimers and nginx timeout management.
rbtree with allowed duplicate keys is used
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"
#include <uwsgi.h>
struct rb_root *uwsgi_init_rb_timer() {
#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 rb_root *u_rb_root = uwsgi_malloc(sizeof(struct rb_root));
u_rb_root->rb_node = NULL;
struct uwsgi_rbtree *uwsgi_init_rb_timer() {
return u_rb_root;
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 rb_root *root) {
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct uwsgi_rbtree *tree, struct uwsgi_rb_timer *node) {
struct rb_node *node = root->rb_node;
if (!node)
node = tree->root;
struct uwsgi_rb_timer *sentinel = tree->sentinel;
if (node == NULL) return NULL;
if (tree->root == sentinel) return NULL;
while(node->rb_left != NULL) {
node = node->rb_left;
while (node->left != sentinel) {
node = node->left;
}
return ((struct uwsgi_rb_timer *) node);
return node;
}
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct rb_root *root, time_t key, void *data) {
static void uwsgi_rbtree_lr(struct uwsgi_rb_timer **root, struct uwsgi_rb_timer *sentinel, struct uwsgi_rb_timer *node) {
struct uwsgi_rb_timer *urbt = uwsgi_malloc(sizeof(struct uwsgi_rb_timer));
struct rb_node **p = &root->rb_node, *parent = NULL;
struct uwsgi_rb_timer *current_rb_timer;
struct uwsgi_rb_timer *temp;
memset(urbt, 0, sizeof(struct uwsgi_rb_timer));
temp = node->right;
node->right = temp->left;
urbt->key = key;
urbt->data = data;
if (temp->left != sentinel) {
temp->left->parent = node;
}
while(*p) {
parent = *p;
temp->parent = node->parent;
current_rb_timer = (struct uwsgi_rb_timer *) 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);
}
if (key <= current_rb_timer->key) {
p = &(*p)->rb_left;
}
else {
p = &(*p)->rb_right;
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);
}
}
}
rb_link_node((struct rb_node *) urbt, parent, p);
uwsgi_rbt_black(*root);
rb_insert_color((struct rb_node *) urbt, root);
return new_node;
}
return urbt;
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);
}
+66 -43
View File
@@ -1,46 +1,60 @@
#ifdef UWSGI_PCRE
#include "uwsgi.h"
int uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra) {
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) {
*pattern = pcre_compile((const char *) re, 0, &errstr, &erroff, NULL);
if (!*pattern) {
uwsgi_log("pcre error: %s at offset %d\n", errstr, erroff);
return -1;
}
*pattern_extra = (pcre_extra *) pcre_study((const pcre*)*pattern, 0, &errstr);
if (*pattern_extra == NULL && errstr != NULL) {
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) {
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 );
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 ) {
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, ovec, (n + 1) * 3);
}
return pcre_exec((const pcre*)pattern, (const pcre_extra *)pattern_extra, subject, length, 0, 0, NULL, 0 );
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 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))
if (pcre_fullinfo((const pcre *) pattern, (const pcre_extra *) pattern_extra, PCRE_INFO_CAPTURECOUNT, &n))
return 0;
return n;
@@ -48,40 +62,49 @@ int uwsgi_regexp_ovector(pcre *pattern, pcre_extra *pattern_extra) {
char *uwsgi_regexp_apply_ovec(char *src, int src_n, char *dst, int dst_n, int *ovector, int n) {
int i;
int dollar = 0;
int i;
int dollar = 0;
char *res = uwsgi_malloc( dst_n + (src_n * n) + 1);
char *ptr = res;
size_t dollars = n;
for(i=0;i<dst_n;i++) {
if (dollar) {
if (isdigit((int)dst[i])) {
int pos = (dst[i] - 48);
if (pos <= n) {
pos = pos * 2;
memcpy(ptr, src + ovector[pos], ovector[pos+1]-ovector[pos]);
ptr+=ovector[pos+1]-ovector[pos];
}
}
else {
*ptr++= dst[i];
}
dollar = 0;
}
else {
if (dst[i] == '$') {
dollar = 1;
}
else {
*ptr++= dst[i];
}
}
}
for(i=0;i<dst_n;i++) {
if (dst[i] == '$') {
dollars++;
}
}
*ptr++= 0;
char *res = uwsgi_malloc(dst_n + (src_n * dollars) + 1);
char *ptr = res;
return 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);
+8 -11
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__)
@@ -100,8 +99,8 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
return sf_ret;
}
while(written < filesize) {
sf_ret = sendfile(sockfd, filefd, pos, filesize-written);
while (written < filesize) {
sf_ret = sendfile(sockfd, filefd, pos, filesize - written);
if (sf_ret < 0) {
uwsgi_error("sendfile()");
return 0;
@@ -109,7 +108,7 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
else if (sf_ret == 0) {
return 0;
}
written+= sf_ret;
written += sf_ret;
}
return written;
@@ -173,5 +172,3 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
#endif
}
#endif
+228 -216
View File
@@ -4,13 +4,16 @@ extern struct uwsgi_server uwsgi;
int uwsgi_signal_handler(uint8_t sig) {
struct uwsgi_signal_entry *use = NULL;
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) {
@@ -34,52 +37,52 @@ int uwsgi_signal_handler(uint8_t sig) {
}
}
// set harakiri here (if required and if i am a worker)
// 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].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]);
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]);
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]);
}
}
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);
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);
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);
}
}
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
}
#endif
return ret;
@@ -97,7 +100,8 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
struct uwsgi_signal_entry *use = NULL;
if (strlen(receiver) > 63) return -1;
if (strlen(receiver) > 63)
return -1;
uwsgi_lock(uwsgi.signal_table_lock);
@@ -109,7 +113,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
return -1;
}
strncpy(use->receiver, receiver, strlen(receiver)+1);
strncpy(use->receiver, receiver, strlen(receiver) + 1);
use->handler = handler;
use->modifier1 = modifier1;
use->wid = uwsgi.mywid;
@@ -129,7 +133,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
if (strlen(filename) > (0xff-1)) {
if (strlen(filename) > (0xff - 1)) {
uwsgi_log("uwsgi_add_file_monitor: invalid filename length\n");
return -1;
}
@@ -140,9 +144,9 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
// 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].registered = 0;
ushared->files_monitored[ushared->files_monitored_cnt].sig = sig;
ushared->files_monitored_cnt++;
}
else {
@@ -157,31 +161,31 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
}
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func)(int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_up = *up, *old_up;
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;
}
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 = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
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;
return uwsgi_up;
}
@@ -189,10 +193,10 @@ 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) {
if (ushared->probes_cnt < MAX_PROBES) {
struct uwsgi_probe *up = uwsgi.probes;
while(up) {
while (up) {
if (!strcmp(up->name, kind)) {
break;
}
@@ -201,15 +205,15 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq)
if (!up) {
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
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;
// 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;
@@ -225,15 +229,15 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int 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;
}
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);
uwsgi_unlock(uwsgi.probe_table_lock);
return 0;
}
@@ -267,107 +271,109 @@ 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;
}
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;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
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;
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;
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
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;
}
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);
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
return 0;
}
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
if (!uwsgi.master_process) return -1;
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.rb_timer_table_lock);
uwsgi_lock(uwsgi.rb_timer_table_lock);
if (ushared->rb_timers_cnt < 64) {
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;
}
// 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);
uwsgi_unlock(uwsgi.rb_timer_table_lock);
return 0;
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]);
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_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[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_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()");
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
}
}
@@ -379,9 +385,10 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
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 (fd < 0)
return -1;
if (write(fd, (char *) &uh, 4) != 4) {
uwsgi_error("uwsgi_remote_signal_send()");
@@ -403,16 +410,16 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
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);
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;
}
@@ -430,7 +437,7 @@ void uwsgi_route_signal(uint8_t sig) {
}
// send to all workers
else if (!strcmp(use->receiver, "workers")) {
for(i=1;i<=uwsgi.numproc;i++) {
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);
}
@@ -438,13 +445,13 @@ void uwsgi_route_signal(uint8_t sig) {
}
// route to specific worker
else if (!strncmp(use->receiver, "worker", 6)) {
i = atoi(use->receiver+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);
}
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
}
// route to subscribed
else if (!strcmp(use->receiver, "subscribed")) {
@@ -454,54 +461,54 @@ void uwsgi_route_signal(uint8_t sig) {
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);
}
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++) {
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);
}
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);
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);
}
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);
}
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;
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);
}
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);
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);
}
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);
}
}
}
@@ -512,51 +519,56 @@ void uwsgi_route_signal(uint8_t sig) {
}
uint8_t uwsgi_signal_wait(int signum) {
int uwsgi_signal_wait(int signum) {
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
uint8_t received_signal;
int ret;
struct pollfd pfd[2];
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;
}
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;
pfd[0].fd = uwsgi.signal_socket;
pfd[0].events = POLLIN;
pfd[1].fd = uwsgi.my_signal_socket;
pfd[1].events = POLLIN;
cycle:
ret = poll(pfd, 2, -1);
if (ret > 0) {
if (pfd[0].revents == POLLIN) {
if (read(uwsgi.signal_socket, &received_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void)uwsgi_signal_handler(received_signal);
if (wait_for_specific_signal) {
if (received_signal != uwsgi_signal) goto cycle;
}
}
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;
}
if (pfd[1].revents == POLLIN) {
if (read(uwsgi.my_signal_socket, &received_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void)uwsgi_signal_handler(received_signal);
if (wait_for_specific_signal) {
if (received_signal != uwsgi_signal) goto cycle;
}
}
}
}
}
return received_signal;
return received_signal;
}
void uwsgi_receive_signal(int fd, char *name, int id) {
@@ -565,27 +577,27 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
ssize_t ret = read(fd, &uwsgi_signal, 1);
if (ret == 0) {
if (ret == 0) {
goto destroy;
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
uwsgi_error("[uwsgi-signal] read()");
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
uwsgi_error("[uwsgi-signal] read()");
goto destroy;
}
else if (ret > 0) {
}
else if (ret > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
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);
}
}
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);
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
end_me(0);
}
+90 -87
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,130 +281,130 @@ 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 = value;
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);
}
}
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;
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;
}
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");
}
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;
}
+341 -284
View File
@@ -174,6 +174,7 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
struct sockaddr_in uws_addr;
char *udp_port;
int bcast = 1;
int reuse = 1;
#ifdef UWSGI_MULTICAST
struct ip_mreq mc;
@@ -231,6 +232,10 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
return -1;
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
}
#ifdef UWSGI_MULTICAST
if (multicast) {
// if multicast is enabled remember to bind to INADDR_ANY
@@ -265,6 +270,10 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
uwsgi_error("setsockopt()");
}
if (setsockopt(serverfd, IPPROTO_IP, IP_MULTICAST_TTL, &uwsgi.multicast_ttl, sizeof(uwsgi.multicast_ttl))) {
uwsgi_error("setsockopt()");
}
}
#endif
@@ -325,7 +334,11 @@ int connect_to_unix(char *socket_name, int timeout, int async) {
memcpy(uws_addr.sun_path, socket_name, UMIN(strlen(socket_name), 102));
}
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
uwsgi_poll.fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
#else
uwsgi_poll.fd = socket(AF_UNIX, SOCK_STREAM, 0);
#endif
if (uwsgi_poll.fd < 0) {
uwsgi_error("socket()");
return -1;
@@ -363,7 +376,11 @@ int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
socket_name[strlen(socket_name)] = ':';
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
#else
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
#endif
if (uwsgi_poll.fd < 0) {
uwsgi_error("socket()");
return -1;
@@ -542,25 +559,26 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
uwsgi_error("SO_REUSEADDR setsockopt()");
uwsgi_nuclear_blast();
}
#ifdef __linux__
#ifdef IP_FREEBIND
#ifndef IP_FREEBIND
#define IP_FREEBIND 15
#endif
if (uwsgi.freebind) {
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
uwsgi_error("IP_FREEBIND setsockopt()");
uwsgi_nuclear_blast();
}
}
#endif
#endif
if (uwsgi.reuse_port) {
#ifdef SO_REUSEPORT
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
uwsgi_error("SO_REUSEPORT setsockopt()");
uwsgi_nuclear_blast();
}
#else
@@ -568,11 +586,21 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
#endif
}
if (uwsgi.so_send_timeout) {
struct timeval tv;
tv.tv_sec = uwsgi.so_send_timeout;
tv.tv_usec = 0;
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDTIMEO, (const void *) &tv, sizeof(struct timeval)) < 0) {
uwsgi_error("SO_SNDTIMEO setsockopt()");
uwsgi_nuclear_blast();
}
}
if (!uwsgi.no_defer_accept) {
#ifdef __linux__
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
uwsgi_error("setsockopt()");
uwsgi_error("TCP_DEFER_ACCEPT setsockopt()");
}
// OSX has no SO_ACCEPTFILTER !!!
#elif defined(__freebsd__)
@@ -580,7 +608,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
strcpy(afa.af_name, "dataready");
afa.af_arg[0] = 0;
if (setsockopt(serverfd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(struct accept_filter_arg))) {
uwsgi_error("setsockopt()");
uwsgi_error("SO_ACCEPTFILTER setsockopt()");
}
#endif
@@ -588,19 +616,27 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (uwsgi.so_keepalive) {
if (setsockopt(serverfd, SOL_SOCKET, SO_KEEPALIVE, &uwsgi.so_keepalive, sizeof(int))) {
uwsgi_error("setsockopt()");
uwsgi_error("SO_KEEPALIVE setsockopt()");
}
}
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
if (errno == EADDRINUSE) {
uwsgi_log("probably another instance of uWSGI is running on the same address.\n");
uwsgi_log("probably another instance of uWSGI is running on the same address (%s).\n", socket_name);
}
uwsgi_error("bind()");
uwsgi_nuclear_blast();
}
#ifdef __linux__
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%i).\n", somaxconn);
uwsgi_nuclear_blast();
}
#endif
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
uwsgi_nuclear_blast();
@@ -650,13 +686,16 @@ void uwsgi_socket_b(int fd) {
int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_size, int timeout, int async) {
int arg, ret;
int ret;
int soopt = 0;
socklen_t solen = sizeof(int);
int cnt;
/* set non-blocking socket */
arg = fcntl(fdpoll->fd, F_GETFL, NULL);
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
// hmm, nothing to do, as we are already non-blocking
#else
int arg = fcntl(fdpoll->fd, F_GETFL, NULL);
if (arg < 0) {
uwsgi_error("fcntl()");
return -1;
@@ -666,6 +705,7 @@ int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_s
uwsgi_error("fcntl()");
return -1;
}
#endif
ret = connect(fdpoll->fd, addr, addr_size);
@@ -673,17 +713,20 @@ int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_s
if (ret < 0 && errno != EINPROGRESS) {
return -1;
}
return 0;
}
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
uwsgi_socket_b(fdpoll->fd);
#else
/* re-set blocking socket */
arg &= (~O_NONBLOCK);
if (fcntl(fdpoll->fd, F_SETFL, arg) < 0) {
uwsgi_error("fcntl()");
return -1;
}
if (async)
return 0;
#endif
if (ret < 0) {
/* check what happened */
@@ -1438,342 +1481,356 @@ socklen_t socket_to_in_addr6(char *socket_name, char *port, int portn, struct so
void uwsgi_setup_shared_sockets() {
int i;
struct uwsgi_socket *shared_sock = uwsgi.shared_sockets;
while (shared_sock) {
if (!uwsgi.is_a_reload) {
char *tcp_port = strrchr(shared_sock->name, ':');
if (tcp_port == NULL) {
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
shared_sock->family = AF_UNIX;
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
while (shared_sock) {
if (!uwsgi.is_a_reload) {
char *tcp_port = strrchr(shared_sock->name, ':');
int current_defer_accept = uwsgi.no_defer_accept;
if (shared_sock->no_defer) {
uwsgi.no_defer_accept = 1;
}
else {
if (tcp_port == NULL) {
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
shared_sock->family = AF_UNIX;
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
}
else {
#ifdef UWSGI_IPV6
if (shared_sock->name[0] == '[' && tcp_port[-1] == ']') {
shared_sock->fd = bind_to_tcp6(shared_sock->name, uwsgi.listen_queue, tcp_port);
shared_sock->family = AF_INET6;
// fix socket name
shared_sock->name = uwsgi_getsockname(shared_sock->fd);
uwsgi_log("uwsgi shared socket %d bound to TCP6 address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
}
else {
if (shared_sock->name[0] == '[' && tcp_port[-1] == ']') {
shared_sock->fd = bind_to_tcp6(shared_sock->name, uwsgi.listen_queue, tcp_port);
shared_sock->family = AF_INET6;
// fix socket name
shared_sock->name = uwsgi_getsockname(shared_sock->fd);
uwsgi_log("uwsgi shared socket %d bound to TCP6 address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
}
else {
#endif
shared_sock->fd = bind_to_tcp(shared_sock->name, uwsgi.listen_queue, tcp_port);
shared_sock->family = AF_INET;
// fix socket name
shared_sock->name = uwsgi_getsockname(shared_sock->fd);
uwsgi_log("uwsgi shared socket %d bound to TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
shared_sock->fd = bind_to_tcp(shared_sock->name, uwsgi.listen_queue, tcp_port);
shared_sock->family = AF_INET;
// fix socket name
shared_sock->name = uwsgi_getsockname(shared_sock->fd);
uwsgi_log("uwsgi shared socket %d bound to TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
#ifdef UWSGI_IPV6
}
}
#endif
}
if (shared_sock->fd < 0) {
uwsgi_log("unable to create shared socket on: %s\n", shared_sock->name);
exit(1);
}
if (shared_sock->no_defer) {
uwsgi.no_defer_accept = current_defer_accept;
}
if (shared_sock->fd < 0) {
uwsgi_log("unable to create shared socket on: %s\n", shared_sock->name);
exit(1);
}
}
else {
for (i = 3; i < (int) uwsgi.max_fd; i++) {
char *sock = uwsgi_getsockname(i);
if (sock) {
if (!strcmp(sock, shared_sock->name)) {
if (strchr(sock, ':')) {
uwsgi_log("uwsgi shared socket %d inherited TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
shared_sock->family = AF_INET;
}
else {
uwsgi_log("uwsgi shared socket %d inherited UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
shared_sock->family = AF_UNIX;
}
shared_sock->fd = i;
}
else {
free(sock);
}
}
}
}
shared_sock->bound = 1;
shared_sock = shared_sock->next;
}
}
else {
for (i = 3; i < (int) uwsgi.max_fd; i++) {
char *sock = uwsgi_getsockname(i);
if (sock) {
if (!strcmp(sock, shared_sock->name)) {
if (strchr(sock, ':')) {
uwsgi_log("uwsgi shared socket %d inherited TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
shared_sock->family = AF_INET;
}
else {
uwsgi_log("uwsgi shared socket %d inherited UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
shared_sock->family = AF_UNIX;
}
shared_sock->fd = i;
}
else {
free(sock);
}
}
}
}
shared_sock->bound = 1;
shared_sock = shared_sock->next;
}
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
while (uwsgi_sock) {
if (uwsgi_sock->shared) {
shared_sock = uwsgi_get_shared_socket_by_num(uwsgi_sock->from_shared);
if (!shared_sock) {
uwsgi_log("unable to find shared socket %d\n", uwsgi_sock->from_shared);
exit(1);
}
uwsgi_sock->fd = shared_sock->fd;
uwsgi_sock->family = shared_sock->family;
uwsgi_sock->name = shared_sock->name;
uwsgi_log("uwsgi socket %d mapped to shared socket %d (%s) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, uwsgi_sock->fd);
}
if (uwsgi_sock->shared) {
shared_sock = uwsgi_get_shared_socket_by_num(uwsgi_sock->from_shared);
if (!shared_sock) {
uwsgi_log("unable to find shared socket %d\n", uwsgi_sock->from_shared);
exit(1);
}
uwsgi_sock->fd = shared_sock->fd;
uwsgi_sock->family = shared_sock->family;
uwsgi_sock->name = shared_sock->name;
uwsgi_log("uwsgi socket %d mapped to shared socket %d (%s) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, uwsgi_sock->fd);
}
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_sock->next;
}
}
void uwsgi_map_sockets() {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
struct uwsgi_string_list *usl = uwsgi.map_socket;
int enabled = 1;
while (usl) {
while (uwsgi_sock) {
struct uwsgi_string_list *usl = uwsgi.map_socket;
int enabled = 1;
while (usl) {
char *colon = strchr(usl->value, ':');
char *colon = strchr(usl->value, ':');
if (!colon) {
uwsgi_log("invalid socket mapping, must be socket:worker[,worker...]\n");
exit(1);
}
if ((int) uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
enabled = 0;
char *p = strtok(colon + 1, ",");
while (p != NULL) {
int w = atoi(p);
if (w < 1 || w > uwsgi.numproc) {
uwsgi_log("invalid worker num: %d\n", w);
exit(1);
}
if (w == uwsgi.mywid) {
enabled = 1;
uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
break;
}
p = strtok(NULL, ",");
}
}
if ((int) uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
enabled = 0;
char *p = strtok(colon + 1, ",");
while (p != NULL) {
int w = atoi(p);
if (w < 1 || w > uwsgi.numproc) {
uwsgi_log("invalid worker num: %d\n", w);
exit(1);
}
if (w == uwsgi.mywid) {
enabled = 1;
uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
break;
}
p = strtok(NULL, ",");
}
}
usl = usl->next;
}
usl = usl->next;
}
if (!enabled) {
close(uwsgi_sock->fd);
int fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != uwsgi_sock->fd) {
if (dup2(fd, uwsgi_sock->fd)) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
uwsgi_sock->disabled = 1;
}
if (!enabled) {
close(uwsgi_sock->fd);
int fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != uwsgi_sock->fd) {
if (dup2(fd, uwsgi_sock->fd) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
uwsgi_sock->disabled = 1;
}
uwsgi_sock = uwsgi_sock->next;
uwsgi_sock = uwsgi_sock->next;
}
}
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->disabled) {
uwsgi_sock = uwsgi_del_socket(uwsgi_sock);
}
else {
uwsgi_sock = uwsgi_sock->next;
}
}
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->disabled) {
uwsgi_sock = uwsgi_del_socket(uwsgi_sock);
}
else {
uwsgi_sock = uwsgi_sock->next;
}
}
}
void uwsgi_bind_sockets() {
socklen_t socket_type_len;
union uwsgi_sockaddr usa;
union uwsgi_sockaddr_ptr gsa;
union uwsgi_sockaddr_ptr gsa;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
char *tcp_port = strrchr(uwsgi_sock->name, ':');
if (tcp_port == NULL) {
uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
uwsgi_sock->family = AF_UNIX;
if (uwsgi.chown_socket) {
uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
}
uwsgi_log("uwsgi socket %d bound to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
}
else {
while (uwsgi_sock) {
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
char *tcp_port = strrchr(uwsgi_sock->name, ':');
if (tcp_port == NULL) {
uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
uwsgi_sock->family = AF_UNIX;
if (uwsgi.chown_socket) {
uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
}
uwsgi_log("uwsgi socket %d bound to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
}
else {
#ifdef UWSGI_IPV6
if (uwsgi_sock->name[0] == '[' && tcp_port[-1] == ']') {
uwsgi_sock->fd = bind_to_tcp6(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
uwsgi_log("uwsgi socket %d bound to TCP6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
uwsgi_sock->family = AF_INET6;
}
else {
if (uwsgi_sock->name[0] == '[' && tcp_port[-1] == ']') {
uwsgi_sock->fd = bind_to_tcp6(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
uwsgi_log("uwsgi socket %d bound to TCP6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
uwsgi_sock->family = AF_INET6;
}
else {
#endif
uwsgi_sock->fd = bind_to_tcp(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
uwsgi_log("uwsgi socket %d bound to TCP address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
uwsgi_sock->family = AF_INET;
uwsgi_sock->fd = bind_to_tcp(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
uwsgi_log("uwsgi socket %d bound to TCP address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
uwsgi_sock->family = AF_INET;
#ifdef UWSGI_IPV6
}
}
#endif
}
}
if (uwsgi_sock->fd < 0 && !uwsgi_sock->per_core) {
uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
exit(1);
}
}
uwsgi_sock->bound = 1;
uwsgi_sock = uwsgi_sock->next;
}
if (uwsgi_sock->fd < 0 && !uwsgi_sock->per_core) {
uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
exit(1);
}
}
uwsgi_sock->bound = 1;
uwsgi_sock = uwsgi_sock->next;
}
if (uwsgi.chown_socket) {
if (!uwsgi.master_as_root) {
uwsgi_as_root();
}
}
if (uwsgi.chown_socket) {
if (!uwsgi.master_as_root) {
uwsgi_as_root();
}
}
int zero_used = 0;
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->bound && uwsgi_sock->fd == 0) {
zero_used = 1;
break;
}
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->bound && uwsgi_sock->fd == 0) {
zero_used = 1;
break;
}
uwsgi_sock = uwsgi_sock->next;
}
if (!zero_used) {
socket_type_len = sizeof(struct sockaddr_un);
gsa.sa = (struct sockaddr *) &usa;
if (!uwsgi.skip_zero && !getsockname(0, gsa.sa, &socket_type_len)) {
if (gsa.sa->sa_family == AF_UNIX) {
uwsgi_sock = uwsgi_new_socket(usa.sa_un.sun_path);
uwsgi_sock->family = AF_UNIX;
uwsgi_sock->fd = 0;
uwsgi_sock->bound = 1;
uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
else {
uwsgi_sock = uwsgi_new_socket(uwsgi_concat2("::", ""));
uwsgi_sock->family = AF_INET;
uwsgi_sock->fd = 0;
uwsgi_sock->bound = 1;
uwsgi_log("uwsgi socket %d inherited INET address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
}
else if (!uwsgi.honour_stdin) {
int fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != 0) {
if (dup2(fd, 0)) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
}
else if (uwsgi.honour_stdin) {
if (!tcgetattr(0, &uwsgi.termios)) {
uwsgi.restore_tc = 1;
}
}
if (!zero_used) {
socket_type_len = sizeof(struct sockaddr_un);
gsa.sa = (struct sockaddr *) &usa;
if (!uwsgi.skip_zero && !getsockname(0, gsa.sa, &socket_type_len)) {
if (gsa.sa->sa_family == AF_UNIX) {
uwsgi_sock = uwsgi_new_socket(uwsgi_getsockname(0));
uwsgi_sock->family = AF_UNIX;
uwsgi_sock->fd = 0;
uwsgi_sock->bound = 1;
uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
else {
uwsgi_sock = uwsgi_new_socket(uwsgi_getsockname(0));
uwsgi_sock->family = AF_INET;
uwsgi_sock->fd = 0;
uwsgi_sock->bound = 1;
uwsgi_log("uwsgi socket %d inherited INET address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
}
else if (!uwsgi.honour_stdin) {
int fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != 0) {
if (dup2(fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
}
else if (uwsgi.honour_stdin) {
if (!tcgetattr(0, &uwsgi.termios)) {
uwsgi.restore_tc = 1;
}
}
}
}
// check for auto_port socket
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->auto_port) {
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->auto_port) {
#ifdef UWSGI_IPV6
if (uwsgi_sock->family == AF_INET6) {
uwsgi_log("uwsgi socket %d bound to TCP6 address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
}
else {
if (uwsgi_sock->family == AF_INET6) {
uwsgi_log("uwsgi socket %d bound to TCP6 address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
}
else {
#endif
uwsgi_log("uwsgi socket %d bound to TCP address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
uwsgi_log("uwsgi socket %d bound to TCP address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
#ifdef UWSGI_IPV6
}
}
#endif
}
uwsgi_sock = uwsgi_sock->next;
}
}
uwsgi_sock = uwsgi_sock->next;
}
}
void uwsgi_set_sockets_protocols() {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
char *requested_protocol = uwsgi_sock->proto_name;
while (uwsgi_sock) {
char *requested_protocol = uwsgi_sock->proto_name;
if (uwsgi_sock->lazy) goto setup_proto;
if (!uwsgi_sock->bound || uwsgi_sock->fd == -1)
goto nextsock;
if (!uwsgi_sock->per_core) {
uwsgi_sock->arg = fcntl(uwsgi_sock->fd, F_GETFL, NULL);
if (uwsgi_sock->arg < 0) {
uwsgi_error("fcntl()");
exit(1);
}
uwsgi_sock->arg |= O_NONBLOCK;
if (fcntl(uwsgi_sock->fd, F_SETFL, uwsgi_sock->arg) < 0) {
uwsgi_error("fcntl()");
exit(1);
}
}
if (uwsgi_sock->lazy)
goto setup_proto;
if (!uwsgi_sock->bound || uwsgi_sock->fd == -1)
goto nextsock;
if (!uwsgi_sock->per_core) {
uwsgi_sock->arg = fcntl(uwsgi_sock->fd, F_GETFL, NULL);
if (uwsgi_sock->arg < 0) {
uwsgi_error("fcntl()");
exit(1);
}
uwsgi_sock->arg |= O_NONBLOCK;
if (fcntl(uwsgi_sock->fd, F_SETFL, uwsgi_sock->arg) < 0) {
uwsgi_error("fcntl()");
exit(1);
}
}
setup_proto:
if (!requested_protocol) {
requested_protocol = uwsgi.protocol;
}
if (!requested_protocol) {
requested_protocol = uwsgi.protocol;
}
if (requested_protocol && !strcmp("http", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_http_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
uwsgi_sock->proto_sendfile = NULL;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
if (!strcmp(uwsgi.protocol, "fastcgi") || !strcmp(uwsgi.protocol, "fcgi")) {
uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1;
}
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_fastcgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_fastcgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_fastcgi_writev_header;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
if (requested_protocol && !strcmp("http", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_http_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
uwsgi_sock->proto_sendfile = NULL;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
if (uwsgi.protocol && (!strcmp(uwsgi.protocol, "fastcgi") || !strcmp(uwsgi.protocol, "fcgi"))) {
uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1;
}
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_fastcgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_fastcgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_fastcgi_writev_header;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
#ifdef UWSGI_ZEROMQ
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
uwsgi.zeromq = 1;
}
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
uwsgi.zeromq = 1;
}
#endif
else {
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
uwsgi_sock->proto_sendfile = NULL;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
else {
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
uwsgi_sock->proto_sendfile = NULL;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
nextsock:
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_sock->next;
}
}
+108 -88
View File
@@ -13,27 +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 *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++) {
for (i = 0; i < uwsgi.spooler_numproc; i++) {
us = uwsgi_new_spooler(directory);
if (mode) us->mode = (long) mode;
if (mode)
us->mode = (long) mode;
}
}
else {
us = uwsgi_new_spooler(directory);
if (mode) us->mode = (long) mode;
us = uwsgi_new_spooler(directory);
if (mode)
us->mode = (long) mode;
}
}
@@ -41,31 +45,31 @@ void uwsgi_opt_add_spooler(char *opt, char *directory, void *mode) {
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_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 (!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;
}
@@ -73,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");
@@ -93,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;
@@ -105,24 +119,24 @@ pid_t spooler_start(struct uwsgi_spooler *uspool) {
uwsgi_close_all_sockets();
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
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);
}
@@ -137,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);
}
}
@@ -194,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);
@@ -217,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;
}
}
@@ -242,7 +256,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
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);
@@ -252,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);
@@ -264,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)) {
@@ -355,12 +369,6 @@ void spooler(struct uwsgi_spooler *uspool) {
}
wakeup = tmp_wakeup;
// need to recycle ?
if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t)uwsgi.spooler_max_tasks) {
uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
end_me(0);
}
}
}
@@ -370,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);
@@ -393,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) {
@@ -418,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;
@@ -487,16 +498,16 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
if (uwsgi_protected_read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
uwsgi_error("read()");
destroy_spool(dir, task);
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)uwsgi_protected_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);
uwsgi_protected_close(spool_fd);
@@ -520,27 +531,28 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
}
int callable_found = 0;
for(i=0;i<256;i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler) {
time_t now = uwsgi_now();
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
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) {
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);
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;
}
}
@@ -551,9 +563,17 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
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");
uwsgi_error("chdir()");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
+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;
}
}
+379 -115
View File
@@ -3,15 +3,21 @@
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->base[1] = '\n';
us->pos = 2;
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;
}
@@ -19,9 +25,10 @@ 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) {
if (ptr + 1 > watermark) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
@@ -36,6 +43,8 @@ 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');
}
@@ -45,24 +54,33 @@ int uwsgi_stats_comma(struct uwsgi_stats *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;
for (i = 0; i < us->tabs; i++) {
if (uwsgi_stats_symbol(us, '\t'))
return -1;
};
return 0;
}
int uwsgi_stats_object_open(struct uwsgi_stats *us) {
if (uwsgi_stats_apply_tabs(us)) return -1;
us->tabs++;
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 (uwsgi_stats_symbol(us, '\n')) return -1;
us->tabs--;
if (uwsgi_stats_apply_tabs(us)) return -1;
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, '}');
}
@@ -72,161 +90,187 @@ int uwsgi_stats_list_open(struct uwsgi_stats *us) {
}
int uwsgi_stats_list_close(struct uwsgi_stats *us) {
if (uwsgi_stats_symbol(us, '\n')) return -1;
us->tabs--;
if (uwsgi_stats_apply_tabs(us)) return -1;
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;
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 ;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
if (ret < 0) return -1;
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
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 ;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
if (ret < 0) return -1;
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;
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;
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 ;
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;
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;
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;
}
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;
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 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;
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 ;
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;
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;
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;
}
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;
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 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;
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 ;
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;
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;
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;
}
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":", key);
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
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 ;
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;
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;
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;
}
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\"", str);
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
us->pos += ret;
return 0;
}
@@ -234,33 +278,253 @@ int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long num) {
if (uwsgi_stats_apply_tabs(us)) return -1;
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 ;
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;
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;
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;
}
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;
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;
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;
}
struct uwsgi_stats_pusher_instance * 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;
}
return 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 (uspi->raw) {
uspi->pusher->func(uspi, now, NULL, 0);
}
else {
if (!us) {
us = uwsgi_master_generate_stats();
if (!us) goto next;
}
uspi->pusher->func(uspi, now, 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;
}
}
struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func) (struct uwsgi_stats_pusher_instance *, time_t, 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;
}
return pusher;
}
struct uwsgi_stats_pusher_file_conf {
char *path;
char *freq;
char *separator;
};
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, time_t now, 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);
}
+398 -363
View File
File diff suppressed because it is too large Load Diff
+762 -339
View File
File diff suppressed because it is too large Load Diff
+410 -210
View File
File diff suppressed because it is too large Load Diff
+115 -107
View File
@@ -36,22 +36,22 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
uwsgi_log("invalid xml id\n");
exit(1);
}
uwsgi_log( "[uWSGI] using xml uwsgi id: %s\n", colon);
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);
uwsgi_log("[uWSGI] could not parse file %s.\n", filename);
exit(1);
}
uwsgi_log( "[uWSGI] parsing config file %s\n", filename);
uwsgi_log("[uWSGI] parsing config file %s\n", filename);
element = xmlDocGetRootElement(doc);
if (element == NULL) {
uwsgi_log( "[uWSGI] invalid xml config file.\n");
uwsgi_log("[uWSGI] invalid xml config file.\n");
exit(1);
}
if (strcmp((char *) element->name, "uwsgi")) {
@@ -62,7 +62,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
xml_id = (char *) xmlGetProp(node, (const xmlChar *) "id");
if (colon && xml_id) {
if ( strcmp(colon, xml_id) ) {
if (strcmp(colon, xml_id)) {
continue;
}
}
@@ -73,82 +73,82 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
}
if (!element) {
uwsgi_log( "[uWSGI] invalid xml root element, <uwsgi> expected.\n");
uwsgi_log("[uWSGI] invalid xml root element, <uwsgi> expected.\n");
exit(1);
}
}
// first check for options
for (node = element->children; node; node = node->next) {
// 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);
}
}
}
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);
@@ -166,17 +166,22 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
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) {
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 (!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;
if (!strcmp("uwsgi", name))
uwsgi_xml_found_stanza = 1;
}
else {
uwsgi_xml_found_opt_key = (char *) name;
@@ -186,23 +191,26 @@ static void startElement(void *xml_id, const XML_Char *name, const XML_Char **at
static void textElement(void *xml_id, const char *s, int len) {
if (!uwsgi_xml_found_stanza) return ;
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);
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) {
static void endElement(void *xml_id, const XML_Char * name) {
if (!uwsgi_xml_found_stanza) return ;
if (!uwsgi_xml_found_stanza)
return;
if (!strcmp(name, "uwsgi")) {
uwsgi_xml_found_stanza = 0;
return;
}
if (!uwsgi_xml_found_opt_key) 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;
@@ -212,30 +220,30 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
char *colon;
char *xml_content;
int xml_size = 0;
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);
}
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);
xml_content = uwsgi_open_and_read(filename, &xml_size, 0, magic_table);
uwsgi_log( "[uWSGI] parsing config file %s\n", filename);
uwsgi_log("[uWSGI] parsing config file %s\n", filename);
XML_Parser parser = XML_ParserCreate(NULL);
XML_SetUserData(parser, NULL);
@@ -257,9 +265,9 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
}
}
} while(!done);
} while (!done);
// we can safely free, as we have a copy of datas
XML_ParserFree(parser);
}
+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);
+15
View File
@@ -0,0 +1,15 @@
require 'net/http'
Net::HTTP.start("uwsgi.it") do |http|
resp = http.get("/install")
open("install.sh", "wb") do |file|
file.write(resp.body)
end
end
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
open("Makefile", "w") do |file|
file.write("all:\n")
file.write("\t\n")
end
-9
View File
@@ -1,9 +0,0 @@
// http:3:GET / HTTP/1.1:192.168.173.10:80,192.168.173.11:80,192.168.173.12:80,192.168.173.13:80
/*
write(arg1);
wait_for_fd()
get_data() == 200
*/
View File
View File
View File
View File
-1
View File
@@ -1 +0,0 @@
// uwsgi:3::192.168.173.1:3031,192.168.173.2:3031,192.168.173.3:3031,192.168.173.4:3031
+30
View File
@@ -2,6 +2,36 @@ import uwsgi
if uwsgi.loop == 'gevent':
import gevent
from threading import Thread
import time
from uwsgidecorators import postfork
def foobar():
while True:
time.sleep(3)
print "threee second elapsed in worker %d" % uwsgi.worker_id()
@postfork
def spawn_thread():
t = Thread(target=foobar)
t.daemon = True
t.start()
@postfork
def spawn_thread2():
t = Thread(target=foobar)
t.daemon = True
t.start()
def gl_func():
while True:
gevent.sleep(2)
print "i am a greenltet running in worker %d" % uwsgi.worker_id()
@postfork
def spawn_greenlet():
gevent.spawn(gl_func)
print uwsgi.version
print uwsgi.workers()
try:
-309
View File
@@ -1,309 +0,0 @@
/*
*** uWSGI, stripped down version of Linux rbtree ***
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
(C) 2002 David Woodhouse <dwmw2@infradead.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../uwsgi.h"
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
struct rb_node *right = node->rb_right;
struct rb_node *parent = rb_parent(node);
if ((node->rb_right = right->rb_left))
rb_set_parent(right->rb_left, node);
right->rb_left = node;
rb_set_parent(right, parent);
if (parent)
{
if (node == parent->rb_left)
parent->rb_left = right;
else
parent->rb_right = right;
}
else
root->rb_node = right;
rb_set_parent(node, right);
}
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{
struct rb_node *left = node->rb_left;
struct rb_node *parent = rb_parent(node);
if ((node->rb_left = left->rb_right))
rb_set_parent(left->rb_right, node);
left->rb_right = node;
rb_set_parent(left, parent);
if (parent)
{
if (node == parent->rb_right)
parent->rb_right = left;
else
parent->rb_left = left;
}
else
root->rb_node = left;
rb_set_parent(node, left);
}
void rb_insert_color(struct rb_node *node, struct rb_root *root)
{
struct rb_node *parent, *gparent;
while ((parent = rb_parent(node)) && rb_is_red(parent))
{
gparent = rb_parent(parent);
if (parent == gparent->rb_left)
{
{
register struct rb_node *uncle = gparent->rb_right;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_right == node)
{
register struct rb_node *tmp;
__rb_rotate_left(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_right(gparent, root);
} else {
{
register struct rb_node *uncle = gparent->rb_left;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_left == node)
{
register struct rb_node *tmp;
__rb_rotate_right(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_left(gparent, root);
}
}
rb_set_black(root->rb_node);
}
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
struct rb_root *root)
{
struct rb_node *other;
while ((!node || rb_is_black(node)) && node != root->rb_node)
{
if (parent->rb_left == node)
{
other = parent->rb_right;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_left(parent, root);
other = parent->rb_right;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_right || rb_is_black(other->rb_right))
{
rb_set_black(other->rb_left);
rb_set_red(other);
__rb_rotate_right(other, root);
other = parent->rb_right;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_right);
__rb_rotate_left(parent, root);
node = root->rb_node;
break;
}
}
else
{
other = parent->rb_left;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_right(parent, root);
other = parent->rb_left;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_left || rb_is_black(other->rb_left))
{
rb_set_black(other->rb_right);
rb_set_red(other);
__rb_rotate_left(other, root);
other = parent->rb_left;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_left);
__rb_rotate_right(parent, root);
node = root->rb_node;
break;
}
}
}
if (node)
rb_set_black(node);
}
void rb_erase(struct rb_node *node, struct rb_root *root)
{
struct rb_node *child, *parent;
int color;
if (!node->rb_left)
child = node->rb_right;
else if (!node->rb_right)
child = node->rb_left;
else
{
struct rb_node *old = node, *left;
node = node->rb_right;
while ((left = node->rb_left) != NULL)
node = left;
if (rb_parent(old)) {
if (rb_parent(old)->rb_left == old)
rb_parent(old)->rb_left = node;
else
rb_parent(old)->rb_right = node;
} else
root->rb_node = node;
child = node->rb_right;
parent = rb_parent(node);
color = rb_color(node);
if (parent == old) {
parent = node;
} else {
if (child)
rb_set_parent(child, parent);
parent->rb_left = child;
node->rb_right = old->rb_right;
rb_set_parent(old->rb_right, node);
}
node->rb_parent_color = old->rb_parent_color;
node->rb_left = old->rb_left;
rb_set_parent(old->rb_left, node);
goto color;
}
parent = rb_parent(node);
color = rb_color(node);
if (child)
rb_set_parent(child, parent);
if (parent)
{
if (parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
}
else
root->rb_node = child;
color:
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
#ifdef __clang__
void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#else
inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#endif
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
+1
View File
@@ -11,5 +11,6 @@ uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_ADDR $server_addr;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
+203
View File
@@ -0,0 +1,203 @@
#include "../../uwsgi.h"
#include <curl/curl.h>
extern struct uwsgi_server uwsgi;
struct uwsgi_alarm_curl_config {
int first;
char *arg;
char *subject;
char *to;
};
struct uwsgi_alarm_curl_opt {
char *name;
CURLoption option;
void (*func)(CURL *, CURLoption, char *, struct uwsgi_alarm_curl_config*);
};
static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
uacc->to = arg;
struct curl_slist *list = NULL;
char *items = uwsgi_str(arg);
char *ctx = NULL;
char *p = strtok_r(items, ",", &ctx);
while(p) {
list = curl_slist_append(list, p);
p = strtok_r(NULL, ",", &ctx);
}
curl_easy_setopt(curl, option, list);
}
static void uwsgi_alarm_curl_ssl(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
curl_easy_setopt(curl, option, (long)CURLUSESSL_ALL);
}
static void uwsgi_alarm_curl_int(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
curl_easy_setopt(curl, option, atoi(arg));
}
static void uwsgi_alarm_curl_set_subject(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
uacc->subject = arg;
}
static struct uwsgi_alarm_curl_opt uaco[] = {
{"url", CURLOPT_URL, NULL},
{"mail_to", CURLOPT_MAIL_RCPT, uwsgi_alarm_curl_to },
{"mail_from", CURLOPT_MAIL_FROM, NULL},
{"subject", 0, uwsgi_alarm_curl_set_subject},
{"ssl", CURLOPT_USE_SSL, uwsgi_alarm_curl_ssl},
{"auth_user", CURLOPT_USERNAME, NULL},
{"auth_pass", CURLOPT_PASSWORD, NULL},
{"method", CURLOPT_CUSTOMREQUEST, NULL},
{"timeout", CURLOPT_TIMEOUT, uwsgi_alarm_curl_int},
{"conn_timeout", CURLOPT_CONNECTTIMEOUT, uwsgi_alarm_curl_int},
{NULL, 0, NULL},
};
static void uwsgi_alarm_curl_setopt(CURL *curl, char *opt, struct uwsgi_alarm_curl_config *uacc) {
struct uwsgi_alarm_curl_opt *o = uaco;
char *equal = strchr(opt,'=');
if (!equal) {
if (!uacc->first) {
curl_easy_setopt(curl, CURLOPT_URL, opt);
uacc->first = 1;
}
return;
}
uacc->first = 1;
*equal = 0;
while(o->name) {
if (!strcmp(o->name, opt)) {
if (o->func) {
o->func(curl, o->option, equal+1, uacc);
}
else {
curl_easy_setopt(curl, o->option, equal+1);
}
goto end;
}
o++;
}
end:
*equal = '=';
}
static size_t uwsgi_alarm_curl_read_callback(void *ptr, size_t size, size_t nmemb, void *userp) {
struct uwsgi_thread *ut = (struct uwsgi_thread *) userp;
size_t full_size = size * nmemb;
size_t remains = ut->len - ut->pos;
struct uwsgi_alarm_curl_config *uacc = ut->data;
if (remains == 0) return 0;
if (ut->custom0 == 0) {
size_t newline = 0;
size_t required = 1;
char *addr = ptr;
if (uacc->to) required += 4 + strlen(uacc->to) + 1;
if (uacc->subject) required += 9 + strlen(uacc->subject) + 1;
if (required > full_size) goto skip;
if (uacc->to) {
memcpy(addr, "To: ", 4); addr+=4;
memcpy(addr, uacc->to, strlen(uacc->to)); addr += strlen(uacc->to);
*addr ++= '\n';
newline = 1;
}
if (uacc->subject) {
memcpy(addr, "Subject: ", 9); addr+=9;
memcpy(addr, uacc->subject, strlen(uacc->subject)); addr += strlen(uacc->subject);
*addr ++= '\n';
newline = 1;
}
skip:
if (newline > 0) {
*addr = '\n';
}
ut->custom0 = 1;
return required;
}
if (full_size < remains) {
remains = full_size;
}
memcpy(ptr, ut->buf + ut->pos, remains);
ut->pos += remains;
return remains;
}
static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
int interesting_fd;
ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);
CURL *curl = curl_easy_init();
// ARGH !!!
if (!curl) return;
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, uwsgi_alarm_curl_read_callback);
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
char *opts = uwsgi_str(uacc->arg);
// fill curl options
char *ctx = NULL;
char *p = strtok_r(opts, ";", &ctx);
while(p) {
uwsgi_alarm_curl_setopt(curl, uwsgi_str(p), uacc);
p = strtok_r(NULL, ";", &ctx);
}
for(;;) {
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
if (ret <= 0) continue;
if (interesting_fd != ut->pipe[1]) continue;
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
if (rlen <= 0) continue;
ut->pos = 0;
ut->len = (size_t) rlen;
ut->custom0 = 0;
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) ut->len);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
}
}
static void uwsgi_alarm_curl_init(struct uwsgi_alarm_instance *uai) {
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_curl_loop);
if (!ut) return;
uai->data_ptr = ut;
struct uwsgi_alarm_curl_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_alarm_curl_config));
uacc->arg = uai->arg;
ut->data = uacc;
}
// pipe the message into the thread;
static void uwsgi_alarm_curl_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
struct uwsgi_thread *ut = (struct uwsgi_thread *) uai->data_ptr;
ut->rlen = write(ut->pipe[0], msg, len);
}
static void uwsgi_alarm_curl_load(void) {
uwsgi_register_alarm("curl", uwsgi_alarm_curl_init, uwsgi_alarm_curl_func);
}
struct uwsgi_plugin alarm_curl_plugin = {
.name = "alarm_curl",
.on_load = uwsgi_alarm_curl_load,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='alarm_curl'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lcurl']
GCC_LIST = ['alarm_curl_plugin']
+52
View File
@@ -0,0 +1,52 @@
#include "../../uwsgi.h"
#import "Foundation/NSString.h"
#import "AppKit/NSSpeechSynthesizer.h"
@interface uWSGIAlarmSpeaker : NSObject {
NSSpeechSynthesizer *synth;
}
-(void)speak: (NSString *)phrase;
@end
@implementation uWSGIAlarmSpeaker
- (uWSGIAlarmSpeaker *) init {
self = [super init];
synth = [[NSSpeechSynthesizer alloc] initWithVoice:nil];
return self;
}
- (void)speak:(NSString *)phrase {
[synth startSpeakingString:phrase];
}
@end
// generate a uwsgi signal on alarm
void uwsgi_alarm_speech_init(struct uwsgi_alarm_instance *uai) {
uai->data_ptr = [[uWSGIAlarmSpeaker alloc] init];
}
void uwsgi_alarm_speech_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
uWSGIAlarmSpeaker *say = (uWSGIAlarmSpeaker *) uai->data_ptr;
NSString *phrase = [[NSString alloc] initWithBytes:msg
length:len
encoding:NSUTF8StringEncoding];
[say speak:phrase];
[phrase release];
}
static void uwsgi_alarm_speech_load(void) {
uwsgi_register_alarm("speech", uwsgi_alarm_speech_init, uwsgi_alarm_speech_func);
}
struct uwsgi_plugin alarm_speech_plugin = {
.name = "alarm_speech",
.on_load = uwsgi_alarm_speech_load,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='alarm_speech'
CFLAGS = []
LDFLAGS = []
LIBS = ['-framework appkit']
GCC_LIST = ['alarm_speech.m']
+26
View File
@@ -0,0 +1,26 @@
#include "../../uwsgi.h"
void uwsgi_alarm_xmpp_loop(struct uwsgi_thread *);
static void uwsgi_alarm_xmpp_init(struct uwsgi_alarm_instance *uai) {
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_xmpp_loop);
if (!ut) return;
uai->data_ptr = ut;
ut->data = uai->arg;
}
// pipe the message into the thread;
static void uwsgi_alarm_xmpp_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
struct uwsgi_thread *ut = (struct uwsgi_thread *) uai->data_ptr;
ut->rlen = write(ut->pipe[0], msg, len);
}
static void uwsgi_alarm_xmpp_load(void) {
uwsgi_register_alarm("xmpp", uwsgi_alarm_xmpp_init, uwsgi_alarm_xmpp_func);
}
struct uwsgi_plugin alarm_xmpp_plugin = {
.name = "alarm_xmpp",
.on_load = uwsgi_alarm_xmpp_load,
};
+158
View File
@@ -0,0 +1,158 @@
#include "../../uwsgi.h"
#include <gloox/client.h>
#include <gloox/error.h>
#include <gloox/message.h>
#include <gloox/connectionlistener.h>
#include <gloox/connectiontcpclient.h>
extern struct uwsgi_server uwsgi;
using namespace gloox;
class Jabbo : public ConnectionListener{
public:
Jabbo(struct uwsgi_thread *ut, char *jab_username, char *jab_password, char *dests) {
u_thread = ut;
dest = NULL;
char *ctx = NULL;
char *p = strtok_r(dests, ",", &ctx);
while(p) {
uwsgi_string_new_list(&dest, p);
p = strtok_r(NULL, ",", &ctx);
}
JID jid(jab_username);
client = new Client( jid, jab_password );
client->registerConnectionListener(this);
u_connected = 0;
client->connect(false);
fd = static_cast<ConnectionTCPClient*>( client->connectionImpl() )->socket();
}
~Jabbo() {
delete client;
}
void send(char *buf, size_t len) {
struct uwsgi_string_list *usl = dest;
while(usl) {
JID jid(usl->value);
std::string text(buf, len);
Message msg(Message::Chat, jid, text);
client->send(msg);
usl = usl->next;
}
}
virtual void onConnect() {
event_queue_add_fd_read(u_thread->queue, fd);
event_queue_add_fd_read(u_thread->queue, u_thread->pipe[1]);
u_connected = 1;
uwsgi_log("[uwsgi-xmpp] connected to the XMPP server\n");
}
virtual void onDisconnect(ConnectionError e) {
uwsgi_log("[uwsgi-xmpp] trying reconnect to the XMPP server...\n");
if (u_connected) {
// no need to remove it as it is already closed...
//event_queue_del_fd(u_thread->queue, fd, event_queue_read());
event_queue_del_fd(u_thread->queue, u_thread->pipe[1], event_queue_read());
}
sleep(1);
u_connected = 0;
client->connect(false);
fd = static_cast<ConnectionTCPClient*>( client->connectionImpl() )->socket();
}
virtual void onResourceBindError(const Error *error) {
uwsgi_log("[uwsgi-xmpp] onResourceBindError(): %s\n", error->text().c_str());
client->disconnect();
}
virtual void onSessionCreateError(const Error *error) {
uwsgi_log("[uwsgi-xmpp] onSessionCreateError(): %s\n", error->text().c_str());
client->disconnect();
}
virtual bool onTLSConnect(const CertInfo& info) {
return true;
}
Client* client;
int fd;
int u_connected;
struct uwsgi_thread *u_thread;
struct uwsgi_string_list *dest;
};
extern "C" void uwsgi_alarm_xmpp_loop(struct uwsgi_thread *ut) {
int interesting_fd;
ut->buf = (char *) uwsgi_malloc(uwsgi.log_master_bufsize);
char *xmpp_username = (char *) "";
char *xmpp_password = (char *) "";
char *xmpp_dests = (char *) "";
// 0 -> username, 1 -> password, 2-> dest list
int opt_state = 0;
// fill xmpp options
char *ctx = NULL;
char *opts = uwsgi_str((char *)ut->data);
char *p = strtok_r(opts, ";", &ctx);
while(p) {
switch(opt_state) {
case 0:
xmpp_username = p;
opt_state = 1;
break;
case 1:
xmpp_password = p;
opt_state = 2;
break;
case 2:
xmpp_dests = p;
opt_state = 3;
break;
default:
break;
}
p = strtok_r(NULL, ";", &ctx);
}
// do not process loglines til the jabber account is connected
event_queue_del_fd(ut->queue, ut->pipe[1], event_queue_read());
Jabbo j(ut, xmpp_username, xmpp_password, xmpp_dests);
int timeout = 0;
for(;;) {
if (j.u_connected) {
timeout = -1;
}
else {
timeout = 0;
}
int ret = event_queue_wait(ut->queue, timeout, &interesting_fd);
if (ret < 0) continue;
if (ret > 0 && interesting_fd == ut->pipe[1]) {
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
if (rlen <= 0) continue;
if (j.u_connected) {
j.send(ut->buf, rlen);
}
}
else if (ret == 0 || (ret > 0 && j.fd > -1 && interesting_fd == j.fd)) {
j.client->recv();
}
}
}
+6
View File
@@ -0,0 +1,6 @@
NAME='alarm_xmpp'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lgloox']
GCC_LIST = ['alarm_xmpp_plugin', 'gloox.cc']
+250 -125
View File
@@ -1,29 +1,56 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
/*
Author: Łukasz Mierzwa
*/
extern struct uwsgi_server uwsgi;
struct carbon_server_list {
char *value; // server address
int healthy;
int errors;
struct carbon_server_list *next;
};
struct uwsgi_carbon {
struct uwsgi_string_list *servers;
struct carbon_server_list *servers_data;
int freq;
int timeout;
char *id;
int no_workers;
unsigned long long *last_busyness_values;
unsigned long long *current_busyness_values;
int *was_busy;
int need_retry;
time_t last_update;
time_t next_retry;
int max_retries;
int retry_delay;
char *root_node;
char *hostname_dot_replacement;
char *hostname;
struct uwsgi_stats_pusher *pusher;
} u_carbon;
struct uwsgi_option carbon_options[] = {
static struct uwsgi_option carbon_options[] = {
{"carbon", required_argument, 0, "push statistics to the specified carbon server", uwsgi_opt_add_string_list, &u_carbon.servers, UWSGI_OPT_MASTER},
{"carbon-timeout", required_argument, 0, "set carbon connection timeout", uwsgi_opt_set_int, &u_carbon.timeout, 0},
{"carbon-freq", required_argument, 0, "set carbon push frequency", uwsgi_opt_set_int, &u_carbon.freq, 0},
{"carbon-timeout", required_argument, 0, "set carbon connection timeout in seconds (default 3)", uwsgi_opt_set_int, &u_carbon.timeout, 0},
{"carbon-freq", required_argument, 0, "set carbon push frequency in seconds (default 60)", uwsgi_opt_set_int, &u_carbon.freq, 0},
{"carbon-id", required_argument, 0, "set carbon id", uwsgi_opt_set_str, &u_carbon.id, 0},
{"carbon-no-workers", no_argument, 0, "disable generation of single worker metrics", uwsgi_opt_true, &u_carbon.no_workers, 0},
{"carbon-max-retry", required_argument, 0, "set maximum number of retries in case of connection errors (default 1)", uwsgi_opt_set_int, &u_carbon.max_retries, 0},
{"carbon-retry-delay", required_argument, 0, "set connection retry delay in seconds (default 7)", uwsgi_opt_set_int, &u_carbon.retry_delay, 0},
{"carbon-root", required_argument, 0, "set carbon metrics root node (default 'uwsgi')", uwsgi_opt_set_str, &u_carbon.root_node, 0},
{"carbon-hostname-dots", required_argument, 0, "set char to use as a replacement for dots in hostname (dots are not replaced by default)", uwsgi_opt_set_str, &u_carbon.hostname_dot_replacement, 0},
{0, 0, 0, 0, 0, 0, 0},
};
void carbon_post_init() {
static void carbon_post_init() {
int i;
struct uwsgi_string_list *usl = u_carbon.servers;
@@ -31,12 +58,28 @@ void carbon_post_init() {
if (!u_carbon.servers) return;
while(usl) {
uwsgi_log("added carbon server %s\n", usl->value);
struct carbon_server_list *u_server = uwsgi_calloc(sizeof(struct carbon_server_list));
u_server->value = usl->value;
u_server->healthy = 1;
u_server->errors = 0;
if (u_carbon.servers_data) {
u_server->next = u_carbon.servers_data;
}
u_carbon.servers_data = u_server;
uwsgi_log("[carbon] added server %s\n", usl->value);
usl = usl->next;
}
if (!u_carbon.root_node) u_carbon.root_node = "uwsgi.";
if (strlen(u_carbon.root_node) && !uwsgi_endswith(u_carbon.root_node, ".")) {
u_carbon.root_node = uwsgi_concat2(u_carbon.root_node, ".");
}
if (u_carbon.freq < 1) u_carbon.freq = 60;
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
if (!u_carbon.id) {
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
@@ -45,172 +88,254 @@ void carbon_post_init() {
}
}
u_carbon.hostname = uwsgi_str(uwsgi.hostname);
if (u_carbon.hostname_dot_replacement) {
for(i=0;i<(int)strlen(u_carbon.hostname);i++) {
if (u_carbon.hostname[i] == '.') u_carbon.hostname[i] = u_carbon.hostname_dot_replacement[0];
}
}
if (!u_carbon.last_busyness_values) {
u_carbon.last_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
}
if (!u_carbon.current_busyness_values) {
u_carbon.current_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
}
if (!u_carbon.was_busy) {
u_carbon.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
}
// set next update to now()+retry_delay, this way we will have first flush just after start
u_carbon.last_update = uwsgi_now() - u_carbon.freq + u_carbon.retry_delay;
uwsgi_log("[carbon] carbon plugin started, %is frequency, %is timeout, max retries %i, retry delay %is\n",
u_carbon.freq, u_carbon.timeout, u_carbon.max_retries, u_carbon.retry_delay);
struct uwsgi_stats_pusher_instance *uspi = uwsgi_stats_pusher_add(u_carbon.pusher, NULL);
uspi->freq = u_carbon.freq;
// no need to generate the json
uspi->raw=1;
}
void carbon_master_cycle() {
static int carbon_write(int fd, char *fmt,...) {
va_list ap;
va_start(ap, fmt);
static time_t last_update = 0;
char ptr[4096];
int rlen, i;
int rlen;
rlen = vsnprintf(ptr, 4096, fmt, ap);
va_end(ap);
if (rlen < 1) return 0;
if (uwsgi_write_nb(fd, ptr, rlen, u_carbon.timeout)) {
uwsgi_error("carbon_write()");
return 0;
}
return 1;
}
static void carbon_push_stats(int retry_cycle, time_t now) {
struct carbon_server_list *usl = u_carbon.servers_data;
int i;
int fd;
struct uwsgi_string_list *usl = u_carbon.servers;
int wok;
if (!u_carbon.servers) return ;
for (i = 0; i < uwsgi.numproc; i++) {
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
u_carbon.last_busyness_values[i] = uwsgi.workers[i+1].running_time;
u_carbon.was_busy[i-1] += uwsgi.workers[i+1].busy;
}
if (last_update == 0) last_update = uwsgi_now();
u_carbon.need_retry = 0;
while(usl) {
if (retry_cycle && usl->healthy)
// skip healthy servers during retry cycle
goto nxt;
if (retry_cycle && usl->healthy == 0)
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->value, usl->errors);
// update
if (uwsgi.current_time - last_update >= u_carbon.freq || uwsgi.cleaning) {
for (i = 0; i < uwsgi.numproc; i++) {
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
u_carbon.last_busyness_values[i] = uwsgi.workers[i+1].running_time;
if (!retry_cycle) {
usl->healthy = 1;
usl->errors = 0;
}
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
if (fd < 0) {
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", usl->value);
if (usl->errors < u_carbon.max_retries) {
u_carbon.need_retry = 1;
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
} else {
uwsgi_log("[carbon] Maximum number of retries for %s (%d)\n",
usl->value, u_carbon.max_retries);
usl->healthy = 0;
usl->errors = 0;
}
usl->healthy = 0;
usl->errors++;
goto nxt;
}
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
while(usl) {
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
if (fd < 0) goto nxt;
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
unsigned long long total_rss = 0;
unsigned long long total_vsz = 0;
unsigned long long total_tx = 0;
unsigned long long total_avg_rt = 0; // total avg_rt
unsigned long long avg_rt = 0; // per worker avg_rt reported to carbon
unsigned long long active_workers = 0; // number of workers used to calculate total avg_rt
unsigned long long total_busyness = 0;
unsigned long long total_avg_busyness = 0;
unsigned long long worker_busyness = 0;
unsigned long long total_harakiri = 0;
unsigned long long total_rss = 0;
unsigned long long total_vsz = 0;
unsigned long long total_tx = 0;
unsigned long long total_avg_rt = 0; // total avg_rt
unsigned long long avg_rt = 0; // per worker avg_rt reported to carbon
unsigned long long active_workers = 0; // number of workers used to calculate total avg_rt
unsigned long long total_busyness = 0;
unsigned long long total_avg_busyness = 0;
unsigned long long worker_busyness = 0;
unsigned long long total_harakiri = 0;
wok = carbon_write(fd, "%s%s.%s.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) uwsgi.workers[0].requests, (unsigned long long) now);
if (!wok) goto clear;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.workers[0].requests, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
for(i=1;i<=uwsgi.numproc;i++) {
total_tx += uwsgi.workers[i].tx;
total_harakiri += uwsgi.workers[i].harakiri_count;
for(i=1;i<=uwsgi.numproc;i++) {
total_tx += uwsgi.workers[i].tx;
if (uwsgi.workers[i].cheaped) {
// also if worker is cheaped than we report its average response time as zero, sending last value might be confusing
avg_rt = 0;
worker_busyness = 0;
if (uwsgi.workers[i].cheaped) {
// also if worker is cheaped than we report its average response time as zero, sending last value might be confusing
avg_rt = 0;
worker_busyness = 0;
}
else {
// global average response time is calculated from active/idle workers, cheaped workers are excluded, otherwise it is not accurate
avg_rt = uwsgi.workers[i].avg_response_time;
active_workers++;
total_avg_rt += uwsgi.workers[i].avg_response_time;
// calculate worker busyness
if (u_carbon.current_busyness_values[i-1] == 0 && u_carbon.was_busy[i-1]) {
worker_busyness = 100;
}
else {
// global average response time is calcucalted from active/idle workers, cheaped workers are excluded, otherwise it is not accurate
avg_rt = uwsgi.workers[i].avg_response_time;
active_workers++;
total_avg_rt += uwsgi.workers[i].avg_response_time;
// calculate worker busyness
worker_busyness = ((u_carbon.current_busyness_values[i-1]*100) / (u_carbon.freq*1000000));
if (worker_busyness > 100) worker_busyness = 100;
total_busyness += worker_busyness;
}
total_busyness += worker_busyness;
u_carbon.was_busy[i-1] = 0;
// only running workers are counted in total memory stats
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
// only running workers are counted in total memory stats and if memory-report option is enabled
total_rss += uwsgi.workers[i].rss_size;
total_vsz += uwsgi.workers[i].vsz_size;
total_harakiri += uwsgi.workers[i].harakiri_count/2;
}
//skip per worker metrics when disabled
if (u_carbon.no_workers) continue;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].requests, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].rss_size, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].vsz_size, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) avg_rt, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].tx, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.busyness %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) worker_busyness, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.harakiri %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].harakiri_count/2, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_rss, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
//skip per worker metrics when disabled
if (u_carbon.no_workers) continue;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_vsz, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
wok = carbon_write(fd, "%s%s.%s.worker%d.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].requests, (unsigned long long) now);
if (!wok) goto clear;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
wok = carbon_write(fd, "%s%s.%s.worker%d.rss_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].rss_size, (unsigned long long) now);
if (!wok) goto clear;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_tx, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
if (active_workers > 0) {
total_avg_busyness = total_busyness / active_workers;
if (total_avg_busyness > 100) total_avg_busyness = 100;
} else {
total_avg_busyness = 0;
}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.busyness %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_avg_busyness, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.active_workers %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) active_workers, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
if (uwsgi.cheaper) {
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.cheaped_workers %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.numproc - active_workers, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
wok = carbon_write(fd, "%s%s.%s.worker%d.vsz_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].vsz_size, (unsigned long long) now);
if (!wok) goto clear;
}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.harakiri %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_harakiri, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(fd, "%s%s.%s.worker%d.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].tx, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(fd, "%s%s.%s.worker%d.busyness %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) worker_busyness, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(fd, "%s%s.%s.worker%d.harakiri %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].harakiri_count, (unsigned long long) now);
if (!wok) goto clear;
}
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
wok = carbon_write(fd, "%s%s.%s.rss_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_rss, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(fd, "%s%s.%s.vsz_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_vsz, (unsigned long long) now);
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(fd, "%s%s.%s.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_tx, (unsigned long long) now);
if (!wok) goto clear;
if (active_workers > 0) {
total_avg_busyness = total_busyness / active_workers;
if (total_avg_busyness > 100) total_avg_busyness = 100;
} else {
total_avg_busyness = 0;
}
wok = carbon_write(fd, "%s%s.%s.busyness %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_avg_busyness, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(fd, "%s%s.%s.active_workers %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) active_workers, (unsigned long long) now);
if (!wok) goto clear;
if (uwsgi.cheaper) {
wok = carbon_write(fd, "%s%s.%s.cheaped_workers %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) uwsgi.numproc - active_workers, (unsigned long long) now);
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.harakiri %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_harakiri, (unsigned long long) now);
if (!wok) goto clear;
usl->healthy = 1;
usl->errors = 0;
clear:
close(fd);
close(fd);
nxt:
usl = usl->next;
}
last_update = uwsgi_now();
usl = usl->next;
}
if (!retry_cycle) u_carbon.last_update = uwsgi_now();
if (u_carbon.need_retry)
// timeouts and retries might cause additional lags in carbon cycles, we will adjust timer to fix that
u_carbon.last_update -= u_carbon.timeout;
}
static void carbon_push(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
if (u_carbon.need_retry && now >= u_carbon.next_retry) {
carbon_push_stats(1, now);
}
else {
// update
u_carbon.need_retry = 0;
carbon_push_stats(0, now);
}
}
static void carbon_cleanup() {
carbon_push_stats(0, uwsgi_now());
}
static void carbon_register() {
u_carbon.pusher = uwsgi_register_stats_pusher("carbon", carbon_push);
}
struct uwsgi_plugin carbon_plugin = {
.name = "carbon",
.master_cleanup = carbon_master_cycle,
.master_cleanup = carbon_cleanup,
.options = carbon_options,
.master_cycle = carbon_master_cycle,
.on_load = carbon_register,
.post_init = carbon_post_init,
};
+9 -3
View File
@@ -838,9 +838,15 @@ clear2:
uwsgi_error("setenv()");
}
if (setenv("PATH_TRANSLATED", uwsgi_concat3n(docroot, docroot_len, path_info, pi_len, "", 0) , 1)) {
uwsgi_error("setenv()");
if (wsgi_req->document_root_len > 0) {
if (setenv("PATH_TRANSLATED", uwsgi_concat3n(wsgi_req->document_root, wsgi_req->document_root_len, path_info, pi_len, "", 0) , 1)) {
uwsgi_error("setenv()");
}
}
else {
if (setenv("PATH_TRANSLATED", uwsgi_concat3n(docroot, docroot_len, path_info, pi_len, "", 0) , 1)) {
uwsgi_error("setenv()");
}
}
}
+14 -14
View File
@@ -78,7 +78,7 @@ void set_next_cheap_time(void) {
// to have quicker recovery from big but short load spikes
// otherwise we might wait a lot before cheaping all emergency workers
if (uwsgi_cheaper_busyness_global.verbose)
uwsgi_log("[busyness] %d emergency worker(s) running, using %d seconds cheaper timer\n",
uwsgi_log("[busyness] %d emergency worker(s) running, using %llu seconds cheaper timer\n",
uwsgi_cheaper_busyness_global.emergency_workers, uwsgi.cheaper_overload*uwsgi_cheaper_busyness_global.backlog_multi);
uwsgi_cheaper_busyness_global.next_cheap = now + uwsgi.cheaper_overload*uwsgi_cheaper_busyness_global.backlog_multi*1000000;
} else {
@@ -95,7 +95,7 @@ void decrease_multi(void) {
// will decrease multiplier but only down to initial value
if (uwsgi_cheaper_busyness_global.cheap_multi > uwsgi_cheaper_busyness_global.min_multi) {
uwsgi_cheaper_busyness_global.cheap_multi--;
uwsgi_log("[busyness] decreasing cheaper multiplier to %d\n", uwsgi_cheaper_busyness_global.cheap_multi);
uwsgi_log("[busyness] decreasing cheaper multiplier to %llu\n", uwsgi_cheaper_busyness_global.cheap_multi);
}
}
@@ -157,7 +157,7 @@ int cheaper_busyness_algo(void) {
// store initial multiplier so we don't loose its initial value
uwsgi_cheaper_busyness_global.min_multi = uwsgi_cheaper_busyness_global.cheap_multi;
// since this is first run we will print current values
uwsgi_log("[busyness] settings: min=%d%%, max=%d%%, overload=%d, multiplier=%d, respawn penalty=%d\n",
uwsgi_log("[busyness] settings: min=%llu%%, max=%llu%%, overload=%llu, multiplier=%llu, respawn penalty=%llu\n",
uwsgi_cheaper_busyness_global.busyness_min, uwsgi_cheaper_busyness_global.busyness_max,
uwsgi.cheaper_overload, uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
#ifdef __linux__
@@ -171,7 +171,7 @@ int cheaper_busyness_algo(void) {
if (uwsgi_cheaper_busyness_global.next_cheap == 0) set_next_cheap_time();
int64_t active_workers = 0;
int active_workers = 0;
uint64_t total_busyness = 0;
uint64_t avg_busyness = 0;
@@ -195,7 +195,7 @@ int cheaper_busyness_algo(void) {
if (percent > 100) percent = 100;
total_busyness += percent;
if (uwsgi_cheaper_busyness_global.verbose && active_workers > 1)
uwsgi_log("[busyness] worker nr %d %ds average busyness is at %d%%\n",
uwsgi_log("[busyness] worker nr %d %llus average busyness is at %llu%%\n",
i+1, uwsgi.cheaper_overload, percent);
}
uwsgi_cheaper_busyness_global.last_values[i] = uwsgi.workers[i+1].running_time;
@@ -204,7 +204,7 @@ int cheaper_busyness_algo(void) {
avg_busyness = (active_workers ? total_busyness / active_workers : 0);
if (uwsgi_cheaper_busyness_global.verbose)
uwsgi_log("[busyness] %ds average busyness of %d worker(s) is at %d%%\n",
uwsgi.cheaper_overload, active_workers, avg_busyness);
(int) uwsgi.cheaper_overload, (int) active_workers, (int) avg_busyness);
if (avg_busyness > uwsgi_cheaper_busyness_global.busyness_max) {
@@ -229,7 +229,7 @@ int cheaper_busyness_algo(void) {
// worker was cheaped and then spawned back in less than current multiplier*cheaper_overload seconds
// we will increase the multiplier so that next time worker will need to wait longer before being cheaped
uwsgi_cheaper_busyness_global.cheap_multi += uwsgi_cheaper_busyness_global.penalty;
uwsgi_log("[busyness] worker(s) respawned to fast, increasing chpeaper multiplier to %d (+%d)\n",
uwsgi_log("[busyness] worker(s) respawned to fast, increasing chpeaper multiplier to %llu (+%llu)\n",
uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
} else {
decrease_multi();
@@ -237,10 +237,10 @@ int cheaper_busyness_algo(void) {
set_next_cheap_time();
uwsgi_log("[busyness] %ds average busyness is at %d%%, will spawn %d new worker(s)\n",
uwsgi_log("[busyness] %llus average busyness is at %llu%%, will spawn %d new worker(s)\n",
uwsgi.cheaper_overload, avg_busyness, decheaped);
} else {
uwsgi_log("[busyness] %ds average busyness is at %d%% but we already started maximum number of workers (%d)\n",
uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers (%d)\n",
uwsgi.cheaper_overload, avg_busyness, uwsgi.numproc);
}
@@ -267,8 +267,8 @@ int cheaper_busyness_algo(void) {
if (uwsgi_cheaper_busyness_global.last_action == 2) decrease_multi();
set_next_cheap_time();
uwsgi_log("[busyness] %ds average busyness is at %d%%, cheap one of %d running workers\n",
uwsgi.cheaper_overload, avg_busyness, active_workers);
uwsgi_log("[busyness] %llus average busyness is at %llu%%, cheap one of %d running workers\n",
uwsgi.cheaper_overload, avg_busyness, (int) active_workers);
// store timestamp
uwsgi_cheaper_busyness_global.last_cheaped = uwsgi_micros();
@@ -280,7 +280,7 @@ int cheaper_busyness_algo(void) {
return -1;
} else if (uwsgi_cheaper_busyness_global.verbose)
uwsgi_log("[busyness] need to wait %d more second(s) to cheap worker\n", (uwsgi_cheaper_busyness_global.next_cheap - now)/1000000);
uwsgi_log("[busyness] need to wait %llu more second(s) to cheap worker\n", (uwsgi_cheaper_busyness_global.next_cheap - now)/1000000);
}
} else {
@@ -301,14 +301,14 @@ int cheaper_busyness_algo(void) {
// time needed to cheap them, than a lot min<busy<max when we do not reset timer
// and then another idle cycle than would trigger cheaping
if (uwsgi_cheaper_busyness_global.verbose)
uwsgi_log("[busyness] %ds average busyness is at %d%%, %d non-idle cycle(s), reseting cheaper timer\n",
uwsgi_log("[busyness] %llus average busyness is at %llu%%, %llu non-idle cycle(s), reseting cheaper timer\n",
uwsgi.cheaper_overload, avg_busyness, uwsgi_cheaper_busyness_global.tolerance_counter);
set_next_cheap_time();
} else {
// we had < 3 idle cycles in a row so we won't reset idle timer yet since this might be just short load spike
// but we need to add cheaper-overload seconds to the cheaper timer so this cycle isn't counted as idle
if (uwsgi_cheaper_busyness_global.verbose)
uwsgi_log("[busyness] %ds average busyness is at %d%%, %d non-idle cycle(s), adjusting cheaper timer\n",
uwsgi_log("[busyness] %llus average busyness is at %llu%%, %llu non-idle cycle(s), adjusting cheaper timer\n",
uwsgi.cheaper_overload, avg_busyness, uwsgi_cheaper_busyness_global.tolerance_counter);
uwsgi_cheaper_busyness_global.next_cheap += uwsgi.cheaper_overload*1000000;
}
+1 -1
View File
@@ -11,7 +11,7 @@ time_t uwsgi_monotonic_seconds() {
uint64_t uwsgi_monotonic_microseconds() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
return ((uint64_t)ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
}
+1 -1
View File
@@ -11,7 +11,7 @@ time_t uwsgi_realtime_seconds() {
uint64_t uwsgi_realtime_microseconds() {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return (ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
return ((uint64_t) ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
}
+379 -88
View File
@@ -22,6 +22,13 @@ void uwsgi_opt_corerouter(char *opt, char *value, void *cr) {
ucr->has_sockets++;
}
void uwsgi_opt_undeferred_corerouter(char *opt, char *value, void *cr) {
struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr;
struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(value, ucr->name);
ugs->no_defer = 1;
ucr->has_sockets++;
}
void uwsgi_opt_corerouter_use_socket(char *opt, char *value, void *cr) {
struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr;
ucr->use_socket = 1;
@@ -127,7 +134,7 @@ void uwsgi_opt_corerouter_ss(char *opt, char *value, void *cr) {
ucr->has_subscription_sockets++;
// this is the subscription hash table
ucr->subscriptions = uwsgi_calloc(sizeof(struct uwsgi_subscription_slot *) * UMAX16);
ucr->subscriptions = uwsgi_subscription_init_ht();
ucr->has_backends++;
@@ -195,16 +202,13 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
if (cr_session->soopt) {
if (!ucr->quiet)
uwsgi_log("unable to connect() to uwsgi instance \"%.*s\": %s\n", (int) cr_session->instance_address_len, cr_session->instance_address, strerror(cr_session->soopt));
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\": %s\n", ucr->short_name, (int) cr_session->instance_address_len, cr_session->instance_address, strerror(cr_session->soopt));
}
else if (cr_session->timed_out) {
if (cr_session->instance_address_len > 0) {
if (cr_session->status == COREROUTER_STATUS_CONNECTING) {
if (cr_session->connecting) {
if (!ucr->quiet)
uwsgi_log("unable to connect() to uwsgi instance \"%.*s\": timeout\n", (int) cr_session->instance_address_len, cr_session->instance_address);
}
else if (cr_session->status == COREROUTER_STATUS_RESPONSE) {
uwsgi_log("timeout waiting for instance \"%.*s\"\n", (int) cr_session->instance_address_len, cr_session->instance_address);
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\": timeout\n", ucr->short_name, (int) cr_session->instance_address_len, cr_session->instance_address);
}
}
}
@@ -237,6 +241,29 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
cr_session->tmp_socket_name = NULL;
}
if (!cr_session->retry) goto end;
// check for max retries
if (cr_session->retries >= (size_t) ucr->max_retries) goto end;
cr_session->retries++;
// reset error and timeout
cr_session->instance_failed = 0;
cr_session->timeout = corerouter_reset_timeout(ucr, cr_session);
cr_session->timed_out = 0;
cr_session->soopt = 0;
// reset nodes
cr_session->un = NULL;
cr_session->static_node = NULL;
cr_session->instance_fd = -1;
// reset hooks (safe as fd is closed)
cr_session->event_hook_read = NULL;
cr_session->event_hook_write = NULL;
cr_session->event_hook_instance_read = NULL;
cr_session->event_hook_instance_write = NULL;
if (ucr->fallback) {
// ok let's try with the fallback nodes
if (!cr_session->fallback) {
@@ -250,35 +277,18 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
cr_session->instance_address = cr_session->fallback->value;
cr_session->instance_address_len = cr_session->fallback->len;
// reset error and timeout
cr_session->timeout = corerouter_reset_timeout(ucr, cr_session);
cr_session->timed_out = 0;
cr_session->soopt = 0;
// reset nodes
cr_session->un = NULL;
cr_session->static_node = NULL;
cr_session->pass_fd = is_unix(cr_session->instance_address, cr_session->instance_address_len);
cr_session->instance_fd = uwsgi_connectn(cr_session->instance_address, cr_session->instance_address_len, 0, 1);
if (cr_session->instance_fd < 0) {
cr_session->instance_failed = 1;
cr_session->soopt = errno;
corerouter_close_session(ucr, cr_session);
return;
if (cr_session->retry(ucr, cr_session)) {
if (!cr_session->instance_failed) goto end;
}
ucr->cr_table[cr_session->instance_fd] = cr_session;
cr_session->status = COREROUTER_STATUS_CONNECTING;
ucr->cr_table[cr_session->instance_fd] = cr_session;
event_queue_add_fd_write(ucr->queue, cr_session->instance_fd);
return;
}
cr_session->instance_address = NULL;
cr_session->instance_address_len = 0;
if (cr_session->retry(ucr, cr_session)) {
if (!cr_session->instance_failed) goto end;
}
return;
}
end:
@@ -297,24 +307,15 @@ end:
free(cr_session->buf_file_name);
}
if (cr_session->write_queue)
free(cr_session->write_queue);
if (cr_session->instance_write_queue)
free(cr_session->instance_write_queue);
// could be used to free additional resources
if (cr_session->close)
cr_session->close(ucr, cr_session);
if (cr_session->keepalive) {
cr_session->keepalive = 0;
return;
}
cr_session->close(cr_session);
close(cr_session->fd);
ucr->cr_table[cr_session->fd] = NULL;
uwsgi_buffer_destroy(cr_session->buffer);
cr_del_timeout(ucr, cr_session);
free(cr_session);
}
@@ -326,32 +327,22 @@ static struct uwsgi_rb_timer *corerouter_reset_timeout(struct uwsgi_corerouter *
static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr) {
time_t current = uwsgi_now();
uint64_t current = (uint64_t) uwsgi_now();
struct uwsgi_rb_timer *urbt;
struct corerouter_session *cr_session;
for (;;) {
urbt = uwsgi_min_rb_timer(ucr->timeouts);
urbt = uwsgi_min_rb_timer(ucr->timeouts, NULL);
if (urbt == NULL)
return;
if (urbt->key <= current) {
if (urbt->value <= current) {
cr_session = (struct corerouter_session *) urbt->data;
cr_session->timed_out = 1;
if (cr_session->retry) {
cr_session->retry = 0;
ucr->switch_events(ucr, cr_session, -1);
if (cr_session->retry) {
cr_del_timeout(ucr, cr_session);
cr_session->timeout = cr_add_fake_timeout(ucr, cr_session);
}
else {
cr_session->timeout = corerouter_reset_timeout(ucr, cr_session);
}
}
else {
corerouter_close_session(ucr, cr_session);
if (cr_session->connecting) {
cr_session->instance_failed = 1;
}
corerouter_close_session(ucr, cr_session);
continue;
}
@@ -359,23 +350,235 @@ static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr) {
}
}
int uwsgi_cr_hook_read(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
struct uwsgi_corerouter *ucr = cs->corerouter;
// first check the case of event removal
if (hook == NULL) {
// nothing changed
if (!cs->event_hook_read) goto unchanged;
// if there is a write event defined, le'ts modify it
if (cs->event_hook_write) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_fd_readwrite_to_write() for %d\n", cs->fd);
#endif
if (event_queue_fd_readwrite_to_write(ucr->queue, cs->fd)) return -1;
}
// simply remove the read event
else {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_del_fd() for %d\n", cs->fd);
#endif
if (event_queue_del_fd(ucr->queue, cs->fd, event_queue_read())) return -1;
}
}
else {
// set the hook
// if write is not defined, simply add a single monitor
if (cs->event_hook_write == NULL) {
if (!cs->event_hook_read) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_add_fd_read() for %d\n", cs->fd);
#endif
if (event_queue_add_fd_read(ucr->queue, cs->fd)) return -1;
}
}
else {
if (!cs->event_hook_read) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_fd_write_to_readwrite() for %d\n", cs->fd);
#endif
if (event_queue_fd_write_to_readwrite(ucr->queue, cs->fd)) return -1;
}
}
}
unchanged:
#ifdef UWSGI_DEBUG
uwsgi_log("event_hook_read set to %p for %d\n", hook, cs->fd);
#endif
cs->event_hook_read = hook;
return 0;
}
int uwsgi_cr_hook_write(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
struct uwsgi_corerouter *ucr = cs->corerouter;
// first check the case of event removal
if (hook == NULL) {
// nothing changed
if (!cs->event_hook_write) goto unchanged;
// if there is a read event defined, le'ts modify it
if (cs->event_hook_read) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_fd_readwrite_to_read() for %d\n", cs->fd);
#endif
if (event_queue_fd_readwrite_to_read(ucr->queue, cs->fd)) return -1;
}
// simply remove the write event
else {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_del_fd() for %d\n", cs->fd);
#endif
if (event_queue_del_fd(ucr->queue, cs->fd, event_queue_write())) return -1;
}
}
else {
// set the hook
// if read is not defined, simply add a single monitor
if (cs->event_hook_read == NULL) {
if (!cs->event_hook_write) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_add_fd_write() for %d\n", cs->fd);
#endif
if (event_queue_add_fd_write(ucr->queue, cs->fd)) return -1;
}
}
else {
if (!cs->event_hook_write) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_fd_read_to_readwrite() for %d\n", cs->fd);
#endif
if (event_queue_fd_read_to_readwrite(ucr->queue, cs->fd)) return -1;
}
}
}
unchanged:
#ifdef UWSGI_DEBUG
uwsgi_log("event_hook_write set to %p for %d\n", hook, cs->fd);
#endif
cs->event_hook_write = hook;
return 0;
}
int uwsgi_cr_hook_instance_read(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
struct uwsgi_corerouter *ucr = cs->corerouter;
// first check the case of event removal
if (hook == NULL) {
// nothing changed
if (!cs->event_hook_instance_read) goto unchanged;
// if there is a write event defined, le'ts modify it
if (cs->event_hook_instance_write) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_fd_readwrite_to_write() for %d\n", cs->instance_fd);
#endif
if (event_queue_fd_readwrite_to_write(ucr->queue, cs->instance_fd)) return -1;
}
// simply remove the read event
else {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_del_fd() for %d\n", cs->instance_fd);
#endif
if (event_queue_del_fd(ucr->queue, cs->instance_fd, event_queue_read())) return -1;
}
}
else {
// set the hook
// if write is not defined, simply add a single monitor
if (cs->event_hook_instance_write == NULL) {
if (!cs->event_hook_instance_read) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_add_fd_read() for %d\n", cs->instance_fd);
#endif
if (event_queue_add_fd_read(ucr->queue, cs->instance_fd)) return -1;
}
}
else {
if (!cs->event_hook_instance_read) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_fd_write_to_readwrite() for %d\n", cs->instance_fd);
#endif
if (event_queue_fd_write_to_readwrite(ucr->queue, cs->instance_fd)) return -1;
}
}
}
unchanged:
#ifdef UWSGI_DEBUG
uwsgi_log("event_hook_instance_read set to %p for %d\n", hook, cs->instance_fd);
#endif
cs->event_hook_instance_read = hook;
return 0;
}
int uwsgi_cr_hook_instance_write(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
struct uwsgi_corerouter *ucr = cs->corerouter;
// first check the case of event removal
if (hook == NULL) {
// nothing changed
if (!cs->event_hook_instance_write) goto unchanged;
// if there is a read event defined, le'ts modify it
if (cs->event_hook_instance_read) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_fd_readwrite_to_read() for %d\n", cs->instance_fd);
#endif
if (event_queue_fd_readwrite_to_read(ucr->queue, cs->instance_fd)) return -1;
}
// simply remove the write event
else {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_del_fd() for %d\n", cs->instance_fd);
#endif
if (event_queue_del_fd(ucr->queue, cs->instance_fd, event_queue_write())) return -1;
}
}
else {
// set the hook
// if read is not defined, simply add a single monitor
if (cs->event_hook_instance_read == NULL) {
if (!cs->event_hook_instance_write) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_add_fd_write() for %d\n", cs->instance_fd);
#endif
if (event_queue_add_fd_write(ucr->queue, cs->instance_fd)) return -1;
}
}
else {
if (!cs->event_hook_instance_write) {
#ifdef UWSGI_DEBUG
uwsgi_log("event_queue_fd_read_to_readwrite() for %d\n", cs->instance_fd);
#endif
if (event_queue_fd_read_to_readwrite(ucr->queue, cs->instance_fd)) return -1;
}
}
}
unchanged:
#ifdef UWSGI_DEBUG
uwsgi_log("event_hook_instance_write set to %p for %d\n", hook, cs->instance_fd);
#endif
cs->event_hook_instance_write = hook;
return 0;
}
struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, int new_connection, struct sockaddr *cr_addr, socklen_t cr_addr_len) {
ucr->cr_table[new_connection] = uwsgi_calloc(ucr->session_size);
ucr->cr_table[new_connection]->fd = new_connection;
ucr->cr_table[new_connection]->instance_fd = -1;
ucr->cr_table[new_connection]->status = COREROUTER_STATUS_RECV_HDR;
ucr->cr_table[new_connection]->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
// map corerouter and socket
ucr->cr_table[new_connection]->corerouter = ucr;
ucr->cr_table[new_connection]->ugs = ugs;
ucr->cr_table[new_connection]->recv = uwsgi_cr_simple_recv;
ucr->cr_table[new_connection]->send = uwsgi_cr_simple_send;
ucr->cr_table[new_connection]->instance_recv = uwsgi_cr_simple_instance_recv;
ucr->cr_table[new_connection]->instance_send = uwsgi_cr_simple_instance_send;
// set initial timeout
ucr->cr_table[new_connection]->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
// create dynamic buffer
ucr->cr_table[new_connection]->buffer = uwsgi_buffer_new(uwsgi.page_size);
// here we prepare the real session and set the hooks
ucr->alloc_session(ucr, ugs, ucr->cr_table[new_connection], cr_addr, cr_addr_len);
event_queue_add_fd_read(ucr->queue, new_connection);
return ucr->cr_table[new_connection];
}
@@ -479,6 +682,9 @@ void uwsgi_corerouter_loop(int id, void *data) {
}
else if (ucr->has_subscription_sockets) {
ucr->mapper = uwsgi_cr_map_use_subscription;
if (uwsgi.subscription_dotsplit) {
ucr->mapper = uwsgi_cr_map_use_subscription_dotsplit;
}
}
else if (ucr->base) {
ucr->mapper = uwsgi_cr_map_use_base;
@@ -501,12 +707,13 @@ void uwsgi_corerouter_loop(int id, void *data) {
for (;;) {
min_timeout = uwsgi_min_rb_timer(ucr->timeouts);
// set timeouts and harakiri
min_timeout = uwsgi_min_rb_timer(ucr->timeouts, NULL);
if (min_timeout == NULL) {
delta = -1;
}
else {
delta = min_timeout->key - uwsgi_now();
delta = min_timeout->value - uwsgi_now();
if (delta <= 0) {
corerouter_expire_timeouts(ucr);
delta = 0;
@@ -517,6 +724,7 @@ void uwsgi_corerouter_loop(int id, void *data) {
ushared->gateways_harakiri[id] = 0;
}
// wait for events
nevents = event_queue_wait_multi(ucr->queue, delta, events, ucr->nevents);
if (uwsgi.master_process && ucr->harakiri > 0) {
@@ -529,28 +737,40 @@ void uwsgi_corerouter_loop(int id, void *data) {
for (i = 0; i < nevents; i++) {
// get the interesting fd
interesting_fd = event_queue_interesting_fd(events, i);
// something bad happened
if (interesting_fd < 0) continue;
// check if the interesting_fd matches a gateway socket
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
int taken = 0;
while (ugs) {
if (ugs->gateway == &ushared->gateways[id] && interesting_fd == ugs->fd) {
if (!ugs->subscription) {
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
new_connection = accept4(interesting_fd, (struct sockaddr *) &cr_addr, &cr_addr_len, SOCK_NONBLOCK);
if (new_connection < 0) {
taken = 1;
break;
}
#else
new_connection = accept(interesting_fd, (struct sockaddr *) &cr_addr, &cr_addr_len);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ucr->queue, interesting_fd);
#endif
if (new_connection < 0) {
taken = 1;
break;
}
// set socket in non-blocking mode, on non-linux platforms, clients get the server mode
#ifdef __linux__
uwsgi_socket_nb(new_connection);
#endif
#endif
corerouter_alloc_session(ucr, ugs, new_connection, (struct sockaddr *) &cr_addr, cr_addr_len);
struct corerouter_session *cr = corerouter_alloc_session(ucr, ugs, new_connection, (struct sockaddr *) &cr_addr, cr_addr_len);
//something wrong in the allocation
if (cr->instance_failed) {
corerouter_close_session(ucr, cr);
}
}
else if (ugs->subscription) {
uwsgi_corerouter_manage_subscription(ucr, id, ugs);
@@ -568,9 +788,11 @@ void uwsgi_corerouter_loop(int id, void *data) {
continue;
}
// manage internal subscription
if (interesting_fd == ushared->gateways[id].internal_subscription_pipe[1]) {
uwsgi_corerouter_manage_internal_subscription(ucr, interesting_fd);
}
// manage a stats request
else if (interesting_fd == ucr->cr_stats_server) {
corerouter_send_stats(ucr);
}
@@ -581,24 +803,59 @@ void uwsgi_corerouter_loop(int id, void *data) {
if (cr_session == NULL)
continue;
// on error, destroy the session
if (event_queue_interesting_fd_has_error(events, i)) {
corerouter_close_session(ucr, cr_session);
continue;
if (interesting_fd == cr_session->instance_fd) {
cr_session->instance_failed = 1;
}
corerouter_close_session(ucr, cr_session);
continue;
}
cr_session->timeout = corerouter_reset_timeout(ucr, cr_session);
// implementation specific cycle;
ucr->switch_events(ucr, cr_session, interesting_fd);
// set timeout
cr_session->timeout = corerouter_reset_timeout(ucr, cr_session);
// call event hook
ssize_t (*hook)(struct corerouter_session *) = NULL;
if (interesting_fd == cr_session->fd) {
if (event_queue_interesting_fd_is_read(events, i)) {
hook = cr_session->event_hook_read;
}
else if (event_queue_interesting_fd_is_write(events, i)) {
hook = cr_session->event_hook_write;
}
}
else if (interesting_fd == cr_session->instance_fd) {
if (event_queue_interesting_fd_is_read(events, i)) {
hook = cr_session->event_hook_instance_read;
}
else if (event_queue_interesting_fd_is_write(events, i)) {
hook = cr_session->event_hook_instance_write;
}
}
// not having a hook could mean a previous event in the loop cleared it...
if (!hook) continue;
// reset errno (as we use it for internal signalling)
errno = 0;
ssize_t ret = hook(cr_session);
// connection closed
if (ret == 0) {
corerouter_close_session(ucr, cr_session);
continue;
}
else if (ret < 0) {
if (errno == EINPROGRESS) continue;
corerouter_close_session(ucr, cr_session);
continue;
}
}
}
}
}
int uwsgi_courerouter_has_has_backends(struct uwsgi_corerouter *ucr) {
int uwsgi_corerouter_has_backends(struct uwsgi_corerouter *ucr) {
if (ucr->has_backends) return 1;
@@ -634,8 +891,11 @@ int uwsgi_corerouter_init(struct uwsgi_corerouter *ucr) {
if (!ucr->nevents)
ucr->nevents = 64;
if (!ucr->max_retries)
ucr->max_retries = 3;
ucr->has_backends = uwsgi_courerouter_has_has_backends(ucr);
ucr->has_backends = uwsgi_corerouter_has_backends(ucr);
uwsgi_corerouter_setup_sockets(ucr);
@@ -659,7 +919,7 @@ int uwsgi_corerouter_init(struct uwsgi_corerouter *ucr) {
struct uwsgi_plugin corerouter_plugin = {
.name = "courerouter",
.name = "corerouter",
};
void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
@@ -668,14 +928,18 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
socklen_t client_src_len = 0;
int client_fd = accept(ucr->cr_stats_server, (struct sockaddr *) &client_src, &client_src_len);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ucr->queue, ucr->cr_stats_server);
#endif
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 = uwsgi_stats_new(8192);
if (uwsgi_stats_keyval_comma(us, "version", UWSGI_VERSION)) goto end;
@@ -702,6 +966,29 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
if (uwsgi_stats_list_close(us)) goto end0;
if (uwsgi_stats_comma(us)) goto end0;
if (ucr->static_nodes) {
if (uwsgi_stats_key(us , "static_nodes")) goto end0;
if (uwsgi_stats_list_open(us)) goto end0;
struct uwsgi_string_list *usl = ucr->static_nodes;
while(usl) {
if (uwsgi_stats_object_open(us)) goto end0;
if (uwsgi_stats_keyvaln_comma(us, "name", usl->value, usl->len)) goto end0;
if (uwsgi_stats_keylong_comma(us, "hits", (unsigned long long) usl->custom2)) goto end0;
if (uwsgi_stats_keylong(us, "grace", (unsigned long long) usl->custom)) goto end0;
if (uwsgi_stats_object_close(us)) goto end0;
usl = usl->next;
if (usl) {
if (uwsgi_stats_comma(us)) goto end0;
}
}
if (uwsgi_stats_list_close(us)) goto end0;
if (uwsgi_stats_comma(us)) goto end0;
}
if (ucr->has_subscription_sockets) {
if (uwsgi_stats_key(us , "subscriptions")) goto end0;
if (uwsgi_stats_list_open(us)) goto end0;
@@ -773,6 +1060,10 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
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) {
+41 -37
View File
@@ -6,8 +6,14 @@
#define cr_add_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, time(NULL)+u->socket_timeout, x)
#define cr_add_fake_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, time(NULL)+1, x)
#define cr_add_check_timeout(x) uwsgi_add_rb_timer(timeouts, time(NULL)+x, NULL)
#define cr_del_check_timeout(x) rb_erase(&x->rbt, timeouts);
#define cr_del_timeout(u, x) rb_erase(&x->timeout->rbt, u->timeouts); free(x->timeout);
#define cr_del_check_timeout(x) uwsgi_del_rb_timer(timeouts, x);
#define cr_del_timeout(u, x) uwsgi_del_rb_timer(u->timeouts, x->timeout); free(x->timeout);
#define cr_try_again if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {\
errno = EINPROGRESS;\
return -1;\
}
struct corerouter_session;
@@ -19,7 +25,6 @@ struct uwsgi_corerouter {
void (*alloc_session)(struct uwsgi_corerouter *, struct uwsgi_gateway_socket *, struct corerouter_session *, struct sockaddr *, socklen_t);
int (*mapper)(struct uwsgi_corerouter *, struct corerouter_session *);
void (*switch_events)(struct uwsgi_corerouter *, struct corerouter_session *, int);
int has_sockets;
int has_backends;
@@ -28,11 +33,13 @@ struct uwsgi_corerouter {
int processes;
int quiet;
struct rb_root *timeouts;
struct uwsgi_rbtree *timeouts;
int use_cache;
int nevents;
int max_retries;
char *magic_table[256];
int queue;
@@ -60,7 +67,6 @@ struct uwsgi_corerouter {
int use_cluster;
struct uwsgi_subscribe_slot **subscriptions;
int subscription_regexp;
struct uwsgi_string_list *fallback;
@@ -87,35 +93,31 @@ struct corerouter_session {
int fd;
int instance_fd;
int instance_stopped;
int status;
uint8_t h_pos;
uint16_t pos;
// corerouter related to this session
struct uwsgi_corerouter *corerouter;
// gateway socket related to this session
struct uwsgi_gateway_socket *ugs;
// parsed hostname
char *hostname;
uint16_t hostname_len;
int has_key;
int retry;
int connecting;
char *instance_address;
uint64_t instance_address_len;
struct uwsgi_subscribe_node *un;
struct uwsgi_string_list *static_node;
int pass_fd;
int soopt;
int timed_out;
// used for tracking required event
int fd_state;
int instance_fd_state;
struct uwsgi_rb_timer *timeout;
int instance_failed;
// check content_length
size_t post_cl;
size_t post_remains;
@@ -124,33 +126,35 @@ struct corerouter_session {
char *buf_file_name;
FILE *buf_file;
uint8_t modifier1;
uint8_t modifier2;
char *tmp_socket_name;
// store the client address
struct sockaddr_un addr;
socklen_t addr_len;
int keepalive;
// async hooks:
// the session is watiting for this fd
ssize_t (*event_hook_read)(struct corerouter_session *);
ssize_t (*event_hook_write)(struct corerouter_session *);
ssize_t (*event_hook_instance_read)(struct corerouter_session *);
ssize_t (*event_hook_instance_write)(struct corerouter_session *);
char *write_queue;
size_t write_queue_len;
int write_queue_close;
void (*close)(struct corerouter_session *);
int (*retry)(struct uwsgi_corerouter *, struct corerouter_session *);
size_t retries;
char *instance_write_queue;
size_t instance_write_queue_len;
struct uwsgi_buffer *buffer;
size_t buffer_len;
off_t buffer_pos;
void (*close)(struct uwsgi_corerouter *, struct corerouter_session *);
ssize_t (*recv)(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
ssize_t (*send)(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
ssize_t (*instance_recv)(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
ssize_t (*instance_send)(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
struct uwsgi_header uh;
uint8_t modifier1;
uint8_t modifier2;
};
void uwsgi_opt_corerouter(char *, char *, void *);
void uwsgi_opt_undeferred_corerouter(char *, char *, void *);
void uwsgi_opt_corerouter_use_socket(char *, char *, void *);
void uwsgi_opt_corerouter_use_base(char *, char *, void *);
void uwsgi_opt_corerouter_use_pattern(char *, char *, void *);
@@ -175,15 +179,15 @@ int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *, struct corerouter_session
int uwsgi_cr_map_use_pattern(struct uwsgi_corerouter *, struct corerouter_session *);
int uwsgi_cr_map_use_cluster(struct uwsgi_corerouter *, struct corerouter_session *);
int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *, struct corerouter_session *);
int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *, struct corerouter_session *);
int uwsgi_cr_map_use_base(struct uwsgi_corerouter *, struct corerouter_session *);
int uwsgi_cr_map_use_cs(struct uwsgi_corerouter *, struct corerouter_session *);
int uwsgi_cr_map_use_to(struct uwsgi_corerouter *, struct corerouter_session *);
int uwsgi_cr_map_use_static_nodes(struct uwsgi_corerouter *, struct corerouter_session *);
int uwsgi_courerouter_has_has_backends(struct uwsgi_corerouter *);
int uwsgi_corerouter_has_backends(struct uwsgi_corerouter *);
ssize_t uwsgi_cr_simple_recv(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
ssize_t uwsgi_cr_simple_send(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
ssize_t uwsgi_cr_simple_instance_recv(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
ssize_t uwsgi_cr_simple_instance_send(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
int uwsgi_cr_hook_read(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
int uwsgi_cr_hook_write(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
int uwsgi_cr_hook_instance_read(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
int uwsgi_cr_hook_instance_write(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
+33 -213
View File
@@ -10,197 +10,6 @@ extern struct uwsgi_server uwsgi;
#include "cr.h"
ssize_t uwsgi_cr_simple_recv(struct uwsgi_corerouter *uc, struct corerouter_session *cs, char *buf, size_t len) {
ssize_t ret = recv(cs->fd, buf, len, 0);
if (ret < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
errno = EINPROGRESS;
return -1;
}
uwsgi_error("recv()");
}
return ret;
}
ssize_t uwsgi_cr_simple_instance_recv(struct uwsgi_corerouter *uc, struct corerouter_session *cs, char *buf, size_t len) {
ssize_t ret = recv(cs->instance_fd, buf, len, 0);
if (ret < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
errno = EINPROGRESS;
return -1;
}
uwsgi_error("recv()");
}
return ret;
}
ssize_t uwsgi_cr_simple_send(struct uwsgi_corerouter *uc, struct corerouter_session *cs, char *buf, size_t len) {
ssize_t ret = -1;
char *tmp_buf;
off_t pos = 0;
size_t partial_len = len;
off_t partial_pos = 0;
if (cs->write_queue_len > 0) {
ret = send(cs->fd, cs->write_queue, cs->write_queue_len, 0);
if (ret > 0) {
cs->write_queue_len-=ret;
pos = ret;
if (cs->write_queue_len == 0) {
free(cs->write_queue);
cs->write_queue = NULL;
if (cs->fd_state) {
event_queue_fd_write_to_read(uc->queue, cs->fd);
cs->fd_state = 0;
}
goto next;
}
goto blocking;
}
else if (ret == 0) {
return 0;
}
else {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto blocking;
}
uwsgi_error("send()");
return -1;
}
}
next:
if (len == 0) goto end;
ret = send(cs->fd, buf, len, 0);
if (ret > 0) {
if ((size_t)ret == len) return len;
partial_len-=ret;
partial_pos = ret;
goto blocking;
}
if (ret == 0) {
return 0;
}
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto blocking;
}
uwsgi_error("send()");
return -1;
end:
if (cs->write_queue_close) {
return 0;
}
return ret;
blocking:
// wait for write
if (!cs->fd_state) {
event_queue_fd_read_to_write(uc->queue, cs->fd);
cs->fd_state = 1;
}
// add new datas to the buffer
tmp_buf = malloc(cs->write_queue_len+partial_len);
if (!tmp_buf) {
uwsgi_error("malloc()");
return -1;
}
if (cs->write_queue_len>0) {
memcpy(tmp_buf, cs->write_queue+pos, cs->write_queue_len);
free(cs->write_queue);
}
memcpy(tmp_buf+cs->write_queue_len, buf+partial_pos, partial_len);
cs->write_queue = tmp_buf;
cs->write_queue_len+=partial_len;
errno = EINPROGRESS;
return -1;
}
ssize_t uwsgi_cr_simple_instance_send(struct uwsgi_corerouter *uc, struct corerouter_session *cs, char *buf, size_t len) {
ssize_t ret;
char *tmp_buf;
off_t pos = 0;
size_t partial_len = len;
off_t partial_pos = 0;
if (cs->instance_write_queue_len > 0) {
ret = send(cs->instance_fd, cs->instance_write_queue, cs->instance_write_queue_len, 0);
if (ret > 0) {
cs->instance_write_queue_len-=ret;
pos=ret;
if (cs->instance_write_queue_len == 0) {
free(cs->instance_write_queue);
cs->instance_write_queue = NULL;
if (cs->instance_fd_state) {
event_queue_fd_write_to_read(uc->queue, cs->instance_fd);
cs->instance_fd_state = 0;
}
goto next;
}
goto blocking;
}
else if (ret == 0) {
return 0;
}
else {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto blocking;
}
uwsgi_error("send()");
return -1;
}
}
next:
ret = send(cs->instance_fd, buf, len, 0);
if (ret > 0) {
if ((size_t)ret == len) return len;
partial_len-=ret;
partial_pos = ret;
goto blocking;
}
if (ret == 0) {
return 0;
}
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto blocking;
}
uwsgi_error("send()");
return -1;
blocking:
// wait for write
if (!cs->instance_fd_state) {
event_queue_fd_read_to_write(uc->queue, cs->instance_fd);
cs->instance_fd_state = 1;
}
// add new datas to the buffer
tmp_buf = malloc(cs->instance_write_queue_len+partial_len);
if (!tmp_buf) {
uwsgi_error("malloc()");
return -1;
}
if (cs->instance_write_queue_len>0) {
memcpy(tmp_buf, cs->instance_write_queue+pos, cs->instance_write_queue_len);
free(cs->instance_write_queue);
}
memcpy(tmp_buf+cs->instance_write_queue_len, buf+partial_pos, partial_len);
cs->instance_write_queue = tmp_buf;
cs->instance_write_queue_len+=partial_len;
errno = EINPROGRESS;
return -1;
}
void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
@@ -208,30 +17,34 @@ void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
if (!strcmp(ucr->name, ugs->owner)) {
if (!ugs->subscription) {
if (ugs->name[0] == '=') {
int shared_socket = atoi(ugs->name+1);
if (shared_socket >= 0) {
ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
int shared_socket = atoi(ugs->name + 1);
if (shared_socket >= 0) {
ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
ugs->shared = 1;
if (ugs->fd == -1) {
uwsgi_log("unable to use shared socket %d\n", shared_socket);
if (ugs->fd == -1) {
uwsgi_log("unable to use shared socket %d\n", shared_socket);
exit(1);
}
}
ugs->name = uwsgi_getsockname(ugs->fd);
}
}
}
else if (!uwsgi_startswith("fd://", ugs->name, 5 )) {
int fd_socket = atoi(ugs->name+5);
else if (!uwsgi_startswith("fd://", ugs->name, 5)) {
int fd_socket = atoi(ugs->name + 5);
if (fd_socket >= 0) {
ugs->fd = fd_socket;
ugs->name = uwsgi_getsockname(ugs->fd);
if (!ugs->name) {
uwsgi_log("unable to use file descriptor %d as socket\n", fd_socket);
uwsgi_log("unable to use file descriptor %d as socket\n", fd_socket);
exit(1);
}
}
}
else {
ugs->port = strchr(ugs->name, ':');
int current_defer_accept = uwsgi.no_defer_accept;
if (ugs->no_defer) {
uwsgi.no_defer_accept = 1;
}
if (ugs->fd == -1) {
if (ugs->port) {
ugs->fd = bind_to_tcp(ugs->name, uwsgi.listen_queue, ugs->port);
@@ -242,7 +55,18 @@ void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
ugs->fd = bind_to_unix(ugs->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
}
if (ugs->no_defer) {
uwsgi.no_defer_accept = current_defer_accept;
}
}
// fix SERVER_PORT
if (!ugs->port || !ugs->port_len) {
ugs->port = strchr(ugs->name, ':');
if (ugs->port) {
ugs->port++;
ugs->port_len = strlen(ugs->port);
}
}
// put socket in non-blocking mode
uwsgi_socket_nb(ugs->fd);
uwsgi_log("%s bound on %s fd %d\n", ucr->name, ugs->name, ugs->fd);
@@ -295,9 +119,6 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
char bbuf[4096];
ssize_t len = recv(ugs->fd, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ucr->queue, ugs->fd);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf + 4, len - 4, corerouter_manage_subscription, &usr);
@@ -309,7 +130,7 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
// subscribe request ?
if (bbuf[3] == 0) {
if (uwsgi_add_subscribe_node(ucr->subscriptions, &usr, ucr->subscription_regexp) && ucr->i_am_cheap) {
if (uwsgi_add_subscribe_node(ucr->subscriptions, &usr) && ucr->i_am_cheap) {
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, ucr->name) && !ugs->subscription) {
@@ -323,12 +144,14 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
}
//unsubscribe
else {
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(ucr->subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, ucr->subscription_regexp);
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(ucr->subscriptions, usr.key, usr.keylen, usr.address, usr.address_len);
if (node && node->len) {
#ifdef UWSGI_SSL
if (uwsgi.subscriptions_sign_check_dir) {
if (usr.sign_len == 0 || usr.base_len == 0) return;
if (usr.unix_check <= node->unix_check) return ;
if (usr.sign_len == 0 || usr.base_len == 0)
return;
if (usr.unix_check <= node->unix_check)
return;
if (!uwsgi_subscription_sign_check(node->slot, &usr)) {
return;
}
@@ -369,16 +192,13 @@ void uwsgi_corerouter_manage_internal_subscription(struct uwsgi_corerouter *ucr,
char bbuf[4096];
ssize_t len = recv(fd, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ucr->queue, fd);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf + 4, len - 4, corerouter_manage_subscription, &usr);
// subscribe request ?
if (bbuf[3] == 0) {
if (uwsgi_add_subscribe_node(ucr->subscriptions, &usr, ucr->subscription_regexp) && ucr->i_am_cheap) {
if (uwsgi_add_subscribe_node(ucr->subscriptions, &usr) && ucr->i_am_cheap) {
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, ucr->name) && !ugs->subscription) {
@@ -392,7 +212,7 @@ void uwsgi_corerouter_manage_internal_subscription(struct uwsgi_corerouter *ucr,
}
//unsubscribe
else {
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(ucr->subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, ucr->subscription_regexp);
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(ucr->subscriptions, usr.key, usr.keylen, usr.address, usr.address_len);
if (node && node->len) {
if (node->death_mark == 0)
uwsgi_log("[%s pid %d] %.*s => marking %.*s as failed\n", ucr->name, (int) uwsgi.mypid, (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
+33 -1
View File
@@ -31,7 +31,7 @@ int uwsgi_cr_map_use_pattern(struct uwsgi_corerouter *ucr, struct corerouter_ses
int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
cr_session->un = uwsgi_get_subscribe_node(ucr->subscriptions, cr_session->hostname, cr_session->hostname_len, ucr->subscription_regexp);
cr_session->un = uwsgi_get_subscribe_node(ucr->subscriptions, cr_session->hostname, cr_session->hostname_len);
if (cr_session->un && cr_session->un->len) {
cr_session->instance_address = cr_session->un->name;
cr_session->instance_address_len = cr_session->un->len;
@@ -44,6 +44,38 @@ int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *ucr, struct coreroute
return 0;
}
int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
char *name = cr_session->hostname;
uint16_t name_len = cr_session->hostname_len;
split:
#ifdef UWSGI_DEBUG
uwsgi_log("trying with %.*s\n", name_len, name);
#endif
cr_session->un = uwsgi_get_subscribe_node(ucr->subscriptions, name, name_len);
if (!cr_session->un) {
char *next = memchr(name+1, '.', name_len-1);
if (next) {
name_len -= next - name;
name = next;
goto split;
}
}
if (cr_session->un && cr_session->un->len) {
cr_session->instance_address = cr_session->un->name;
cr_session->instance_address_len = cr_session->un->len;
cr_session->modifier1 = cr_session->un->modifier1;
}
else if (ucr->cheap && !ucr->i_am_cheap && uwsgi_no_subscriptions(ucr->subscriptions)) {
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
}
return 0;
}
int uwsgi_cr_map_use_base(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
int tmp_socket_name_len = 0;
+69
View File
@@ -0,0 +1,69 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
// global variables for configuration
static uint8_t dumbloop_modifier1 = 0;
static char *dumbloop_code = "";
static char *dumbloop_function = "dumbloop";
struct uwsgi_option dumbloop_options[] = {
{"dumbloop-modifier1", required_argument, 0, "set the modifier1 for the code_string", uwsgi_opt_set_int, &dumbloop_modifier1, 0},
{"dumbloop-code", required_argument, 0, "set the script to load for the code_string", uwsgi_opt_set_str, &dumbloop_code, 0},
{"dumbloop-function", required_argument, 0, "set the function to run for the code_string", uwsgi_opt_set_str, &dumbloop_function, 0},
{0, 0, 0, 0, 0, 0, 0},
};
// this function is executed for each thread
static void *dumb_loop_run(void *arg1) {
// get the core id (pthreads take a void pointer as argument, so we need this ugly trick)
long core_id = (long) arg1;
#ifdef UWSGI_THREADING
// complete threads setup (this is required for fixing things like UNIX signal handling)
if (uwsgi.threads > 1) {
// wsgi_request mapped to the core
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;
// fix it
uwsgi_setup_thread_req(core_id, wsgi_req);
}
#endif
// this strign will be passed to the code_string function
char *str_core = uwsgi_num2str(core_id);
// ok we are ready, let's run custom code
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
if (uwsgi.p[dumbloop_modifier1]->code_string) {
// "uwsgi_dumbloop" is the name of the module (will be used while importing the file, if needed)
uwsgi.p[dumbloop_modifier1]->code_string("uwsgi_dumbloop", dumbloop_code, dumbloop_function, str_core, strlen(str_core));
}
else {
uwsgi_log("the requested plugin does not support code_string hook\n");
exit(1);
}
}
return NULL;
}
static void dumb_loop() {
// this run the dumb_loop_run in each thread (core)
uwsgi_loop_cores_run(dumb_loop_run);
}
// register the new loop engine
static void dumbloop_register() {
uwsgi_register_loop( (char *) "dumb", dumb_loop);
}
struct uwsgi_plugin dumbloop_plugin = {
.name = "dumbloop",
.on_load = dumbloop_register,
.options = dumbloop_options,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='dumbloop'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['dumb']
+121
View File
@@ -0,0 +1,121 @@
#include "../../uwsgi.h"
#include "client/dbclient.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_instance *ui;
// one for each mongodb imperial monitor
struct uwsgi_emperor_mongodb_state {
char *address;
char *collection;
char *json;
};
extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues) {
struct uwsgi_emperor_mongodb_state *uems = (struct uwsgi_emperor_mongodb_state *) ues->data;
try {
// requested fields
mongo::BSONObj p = BSON( "name" << 1 << "config" << 1 << "ts" << 1 << "uid" << 1 << "gid" << 1 );
mongo::BSONObj q = mongo::fromjson(uems->json);
// the connection object (will be automatically destroyed at each cycle)
mongo::DBClientConnection c;
// set the socket timeout
c.setSoTimeout(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
// connect
c.connect(uems->address);
// run the query
std::auto_ptr<mongo::DBClientCursor> cursor = c.query(uems->collection, q, 0, 0, &p);
while( cursor->more() ) {
mongo::BSONObj p = cursor->next();
// checking for an empty string is not required, but we reduce the load
// in case of badly strctured databases
const char *name = p.getStringField("name");
if (strlen(name) == 0) continue;
const char *config = p.getStringField("config");
time_t vassal_ts = 0;
// ts must be a Date object !!!
mongo::BSONElement ts = p.getField("ts");
if (ts.type() == mongo::Date) {
vassal_ts = ts.date();
}
uid_t vassal_uid = 0;
gid_t vassal_gid = 0;
// check for tyrant mode
if (uwsgi.emperor_tyrant) {
int tmp_uid = p.getIntField("uid");
int tmp_gid = p.getIntField("gid");
if (tmp_uid < 0) tmp_uid = 0;
if (tmp_gid < 0) tmp_gid = 0;
vassal_uid = tmp_uid;
vassal_gid = tmp_gid;
}
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid);
}
// now check for removed instances
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
if (c_ui->scanner == ues) {
mongo::BSONObjBuilder b;
b.appendElements(q);
b.append("name", c_ui->name);
mongo::BSONObj q2 = b.obj();
cursor = c.query(uems->collection, q2, 0, 0, &p);
#ifdef UWSGI_DEBUG
uwsgi_log("JSON: %s\n", q2.toString().c_str());
#endif
if (!cursor->more()) {
emperor_stop(c_ui);
}
}
c_ui = c_ui->ui_next;
}
}
catch ( mongo::DBException &e ) {
uwsgi_log("[emperor-mongodb] ERROR(%s/%s): %s\n", uems->address, uems->collection, e.what());
}
}
// setup a new mongodb imperial monitor
extern "C" void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *ues) {
// allocate a new state
ues->data = uwsgi_calloc(sizeof(struct uwsgi_emperor_mongodb_state));
size_t arg_len = strlen(ues->arg);
struct uwsgi_emperor_mongodb_state *uems = (struct uwsgi_emperor_mongodb_state *) ues->data;
// parse args/ set defaults
uems->address = (char *) "127.0.0.1:27017";
uems->collection = (char *) "uwsgi.emperor.vassals";
uems->json = (char *) "";
if (arg_len > 10) {
uems->address = uwsgi_str(ues->arg+10);
char *comma = strchr(uems->address, ',');
if (!comma) goto done;
*comma = 0;
uems->collection = comma+1;
comma = strchr(uems->collection, ',');
if (!comma) goto done;
*comma = 0;
uems->json = comma+1;
}
done:
uwsgi_log("[emperor] enabled emperor MongoDB monitor for %s on collection %s\n", uems->address, uems->collection);
}
+14
View File
@@ -0,0 +1,14 @@
#include "../../uwsgi.h"
void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *);
void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *);
void emperor_mongodb_init(void) {
uwsgi_register_imperial_monitor("mongodb", uwsgi_imperial_monitor_mongodb_init, uwsgi_imperial_monitor_mongodb);
}
struct uwsgi_plugin emperor_mongodb_plugin = {
.name = "emperor_mongodb",
.on_load = emperor_mongodb_init,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='emperor_mongodb'
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
LDFLAGS = []
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
GCC_LIST = ['plugin', 'emperor_mongodb.cc']
+1 -35
View File
@@ -7,7 +7,6 @@ extern struct uwsgi_instance *ui;
void uwsgi_imperial_monitor_pg_init(struct uwsgi_emperor_scanner *);
void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *);
void emperor_pg_init(void);
void emperor_pg_do(struct uwsgi_emperor_scanner *, char *, char *, time_t, uid_t, gid_t);
void emperor_pg_init(void) {
uwsgi_register_imperial_monitor("pg", uwsgi_imperial_monitor_pg_init, uwsgi_imperial_monitor_pg);
@@ -17,39 +16,6 @@ void uwsgi_imperial_monitor_pg_init(struct uwsgi_emperor_scanner *ues) {
uwsgi_log("[emperor] enabled emperor PostgreSQL monitor\n");
}
void emperor_pg_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
if (!uwsgi_emperor_is_valid(name))
return;
struct uwsgi_instance *ui_current = emperor_get(name);
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (uid != ui_current->uid || gid != ui_current->gid) {
uwsgi_log("[emperor-tyrant] !!! permissions of vassal %s changed. stopping the instance... !!!\n", name);
emperor_stop(ui_current);
return;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (ts > ui_current->last_mod) {
// make a new config (free the old one)
free(ui_current->config);
ui_current->config = config;
ui_current->config_len = strlen(config);
// always respawn (no need for amqp-style rules)
emperor_respawn(ui_current, ts);
}
}
else {
// make a copy of the config as it will be freed
emperor_add(ues, name, ts, uwsgi_str(config), strlen(config), uid, gid);
}
}
void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) {
PGconn *conn = NULL;
@@ -102,7 +68,7 @@ void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) {
vassal_uid = uwsgi_str_num(q_uid, strlen(q_uid));
vassal_gid = uwsgi_str_num(q_gid, strlen(q_gid));
}
emperor_pg_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid);
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid);
}
}
+2 -2
View File
@@ -244,7 +244,7 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
}
void erlang_loop(int id) {
void erlang_loop(int id, void *data) {
ErlConnect econn;
//ErlMessage em;
@@ -422,7 +422,7 @@ int erlang_init() {
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
if (register_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
if (register_gateway("uWSGI erlang c-node", erlang_loop, NULL) == NULL) {
uwsgi_log("unable to register the erlang gateway\n");
exit(1);
}
+304 -16
View File
@@ -2,35 +2,37 @@
uWSGI fastrouter
requires:
- async
- caching
- pcre (optional)
*/
#include "../../uwsgi.h"
#include "../corerouter/cr.h"
struct uwsgi_fastrouter {
struct uwsgi_corerouter cr;
} ufr;
extern struct uwsgi_server uwsgi;
#include "fr.h"
struct uwsgi_fastrouter ufr;
struct fastrouter_session {
struct corerouter_session crs;
struct uwsgi_buffer *post_buf;
size_t post_buf_max;
size_t post_buf_len;
off_t post_buf_pos;
};
struct uwsgi_option fastrouter_options[] = {
{"fastrouter", required_argument, 0, "run the fastrouter on the specified port", uwsgi_opt_corerouter, &ufr, 0},
{"fastrouter-processes", required_argument, 0, "prefork the specified number of fastrouter processes", uwsgi_opt_set_int, &ufr.cr.processes, 0},
{"fastrouter-workers", required_argument, 0, "prefork the specified number of fastrouter processes", uwsgi_opt_set_int, &ufr.cr.processes, 0},
{"fastrouter-zerg", required_argument, 0, "attach the fastrouter to a zerg server", uwsgi_opt_corerouter_zerg, &ufr, 0 },
{"fastrouter-zerg", required_argument, 0, "attach the fastrouter to a zerg server", uwsgi_opt_corerouter_zerg, &ufr, 0},
{"fastrouter-use-cache", no_argument, 0, "use uWSGI cache as hostname->server mapper for the fastrouter", uwsgi_opt_true, &ufr.cr.use_cache, 0},
{"fastrouter-use-pattern", required_argument, 0, "use a pattern for fastrouter hostname->server mapping", uwsgi_opt_corerouter_use_pattern, &ufr, 0},
{"fastrouter-use-base", required_argument, 0, "use a base dir for fastrouter hostname->server mapping", uwsgi_opt_corerouter_use_base, &ufr, 0},
{"fastrouter-fallback", required_argument, 0, "fallback to the specified node in case of error", uwsgi_opt_add_string_list, &ufr.cr.fallback, 0},
{"fastrouter-use-cluster", no_argument, 0, "load balance to nodes subscribed to the cluster", uwsgi_opt_true, &ufr.cr.use_cluster, 0},
{"fastrouter-use-code-string", required_argument, 0, "use code string as hostname->server mapper for the fastrouter", uwsgi_opt_corerouter_cs, &ufr, 0},
@@ -42,7 +44,6 @@ struct uwsgi_option fastrouter_options[] = {
{"fastrouter-cheap", no_argument, 0, "run the fastrouter in cheap mode", uwsgi_opt_true, &ufr.cr.cheap, 0},
{"fastrouter-subscription-server", required_argument, 0, "run the fastrouter subscription server on the spcified address", uwsgi_opt_corerouter_ss, &ufr, 0},
{"fastrouter-subscription-slot", required_argument, 0, "*** deprecated ***", uwsgi_opt_deprecated, (void *) "useless thanks to the new implementation", 0},
{"fastrouter-subscription-use-regexp", no_argument, 0, "enable regexp for subscription system", uwsgi_opt_true, &ufr.cr.subscription_regexp, 0},
{"fastrouter-timeout", required_argument, 0, "set fastrouter timeout", uwsgi_opt_set_int, &ufr.cr.socket_timeout, 0},
{"fastrouter-post-buffering", required_argument, 0, "enable fastrouter post buffering", uwsgi_opt_set_64bit, &ufr.cr.post_buffering, 0},
@@ -51,19 +52,306 @@ struct uwsgi_option fastrouter_options[] = {
{"fastrouter-stats", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
{"fastrouter-stats-server", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
{"fastrouter-ss", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
{"fastrouter-harakiri", required_argument, 0, "enable fastrouter harakiri", uwsgi_opt_set_int, &ufr.cr.harakiri, 0 },
{"fastrouter-harakiri", required_argument, 0, "enable fastrouter harakiri", uwsgi_opt_set_int, &ufr.cr.harakiri, 0},
{0, 0, 0, 0, 0, 0, 0},
};
ssize_t fr_recv_uwsgi_header(struct corerouter_session *);
ssize_t fr_instance_read_response(struct corerouter_session *);
ssize_t fr_read_body(struct corerouter_session *);
void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
// here i use directly corerouter_session
struct corerouter_session *cs = (struct corerouter_session *) data;
//uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !cs->hostname_len) {
cs->hostname = val;
cs->hostname_len = vallen;
return;
}
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !cs->has_key) {
cs->hostname = val;
cs->hostname_len = vallen;
return;
}
if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) {
cs->has_key = 1;
cs->hostname = val;
cs->hostname_len = vallen;
return;
}
if (!uwsgi_strncmp("CONTENT_LENGTH", 14, key, keylen)) {
cs->post_cl = uwsgi_str_num(val, vallen);
return;
}
}
ssize_t fr_write_body(struct corerouter_session * cs) {
struct fastrouter_session *fs = (struct fastrouter_session *) cs;
ssize_t len = write(cs->instance_fd, fs->post_buf->buf + fs->post_buf_pos, fs->post_buf_len - fs->post_buf_pos);
if (len < 0) {
cr_try_again;
uwsgi_error("fr_write_body()");
return -1;
}
fs->post_buf_pos += len;
// the body chunk has been sent, start again reading from client and instance
if (fs->post_buf_pos == (ssize_t) fs->post_buf_len) {
uwsgi_cr_hook_instance_write(cs, NULL);
uwsgi_cr_hook_instance_read(cs, fr_instance_read_response);
uwsgi_cr_hook_read(cs, fr_read_body);
}
return len;
}
ssize_t fr_read_body(struct corerouter_session * cs) {
struct fastrouter_session *fs = (struct fastrouter_session *) cs;
ssize_t len = read(cs->fd, fs->post_buf->buf, fs->post_buf_max);
if (len < 0) {
cr_try_again;
uwsgi_error("fr_read_body()");
return -1;
}
// connection closed
if (len == 0)
return 0;
fs->post_buf_len = len;
fs->post_buf_pos = 0;
// ok we have a body, stop reading from the client and the instance and start writing to the instance
uwsgi_cr_hook_read(cs, NULL);
uwsgi_cr_hook_instance_read(cs, NULL);
uwsgi_cr_hook_instance_write(cs, fr_write_body);
return len;
}
ssize_t fr_write_response(struct corerouter_session * cs) {
ssize_t len = write(cs->fd, cs->buffer->buf + cs->buffer_pos, cs->buffer_len - cs->buffer_pos);
if (len < 0) {
cr_try_again;
uwsgi_error("fr_write_response()");
return -1;
}
cs->buffer_pos += len;
// ok this response chunk is sent, let's wait for another one
if (cs->buffer_pos == (ssize_t) cs->buffer_len) {
uwsgi_cr_hook_write(cs, NULL);
uwsgi_cr_hook_instance_read(cs, fr_instance_read_response);
}
return len;
}
ssize_t fr_instance_read_response(struct corerouter_session * cs) {
ssize_t len = read(cs->instance_fd, cs->buffer->buf, cs->buffer->len);
if (len < 0) {
cr_try_again;
uwsgi_error("fr_instance_read_response()");
return -1;
}
// end of the response
if (len == 0) {
return 0;
}
cs->buffer_pos = 0;
cs->buffer_len = len;
// ok stop reading from the instance, and start writing to the client
uwsgi_cr_hook_instance_read(cs, NULL);
uwsgi_cr_hook_write(cs, fr_write_response);
return len;
}
ssize_t fr_instance_send_request(struct corerouter_session * cs) {
ssize_t len = write(cs->instance_fd, cs->buffer->buf + cs->buffer_pos, cs->uh.pktsize - cs->buffer_pos);
if (len < 0) {
cr_try_again;
uwsgi_error("fr_instance_send_request()");
return -1;
}
cs->buffer_pos += len;
// ok the request is sent, we can start sending client body (if any) and we can start waiting
// for response
if (cs->buffer_pos == cs->uh.pktsize) {
cs->buffer_pos = 0;
// stop writing to the instance
uwsgi_cr_hook_instance_write(cs, NULL);
// start reading from the instance
uwsgi_cr_hook_instance_read(cs, fr_instance_read_response);
// re-start reading from the client (for body or connection close)
struct fastrouter_session *fs = (struct fastrouter_session *) cs;
// allocate a buffer for client body (could be delimited or dynamic)
fs->post_buf_max = UMAX16;
if (cs->post_cl > 0) {
fs->post_buf_max = UMIN(UMAX16, cs->post_cl);
}
fs->post_buf = uwsgi_buffer_new(fs->post_buf_max);
if (!fs->post_buf)
return -1;
uwsgi_cr_hook_read(cs, fr_read_body);
}
return len;
}
ssize_t fr_instance_send_request_header(struct corerouter_session * cs) {
ssize_t len = write(cs->instance_fd, &cs->uh + cs->buffer_pos, 4 - cs->buffer_pos);
if (len < 0) {
cr_try_again;
uwsgi_error("fr_instance_send_request_header()");
return -1;
}
cs->buffer_pos += len;
// ok the request is sent, we can start sending client body (if any) and we can start waiting
// for response
if (cs->buffer_pos == 4) {
cs->buffer_pos = 0;
uwsgi_cr_hook_instance_write(cs, fr_instance_send_request);
}
return len;
}
ssize_t fr_instance_connected(struct corerouter_session * cs) {
cs->connecting = 0;
socklen_t solen = sizeof(int);
// first check for errors
if (getsockopt(cs->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&cs->soopt), &solen) < 0) {
uwsgi_error("fr_instance_connected()/getsockopt()");
cs->instance_failed = 1;
return -1;
}
if (cs->soopt) {
cs->instance_failed = 1;
return -1;
}
cs->buffer_pos = 0;
// ok instance is connected, wait for write again
if (cs->static_node) cs->static_node->custom2++;
if (cs->un) cs->un->requests++;
uwsgi_cr_hook_instance_write(cs, fr_instance_send_request_header);
// return a value > 0
return 1;
}
ssize_t fr_recv_uwsgi_vars(struct corerouter_session * cs) {
// increase buffer if needed
if (uwsgi_buffer_fix(cs->buffer, cs->uh.pktsize))
return -1;
ssize_t len = read(cs->fd, cs->buffer->buf + cs->buffer_pos, cs->uh.pktsize - cs->buffer_pos);
if (len < 0) {
cr_try_again;
uwsgi_error("fr_recv_uwsgi_vars()");
return -1;
}
cs->buffer_pos += len;
// headers received, ready to choose the instance
if (cs->buffer_pos == cs->uh.pktsize) {
struct uwsgi_corerouter *ucr = cs->corerouter;
// find the hostname
if (uwsgi_hooked_parse(cs->buffer->buf, cs->uh.pktsize, fr_get_hostname, (void *) cs)) {
return -1;
}
// check the hostname;
if (cs->hostname_len == 0)
return -1;
// find an instance using the key
if (cs->corerouter->mapper(cs->corerouter, cs))
return -1;
// check instance
if (cs->instance_address_len == 0) {
// if fallback nodes are configured, trigger them
if (ucr->fallback) {
cs->instance_failed = 1;
}
return -1;
}
// stop receiving from the client
uwsgi_cr_hook_read(cs, NULL);
// start async connect
cs->instance_fd = uwsgi_connectn(cs->instance_address, cs->instance_address_len, 0, 1);
if (cs->instance_fd < 0) {
cs->instance_failed = 1;
cs->soopt = errno;
return -1;
}
// map the instance
cs->corerouter->cr_table[cs->instance_fd] = cs;
// wait for connection
cs->connecting = 1;
uwsgi_cr_hook_instance_write(cs, fr_instance_connected);
}
return len;
}
ssize_t fr_recv_uwsgi_header(struct corerouter_session * cs) {
ssize_t len = read(cs->fd, cs->buffer->buf + cs->buffer_pos, 4 - cs->buffer_pos);
if (len < 0) {
cr_try_again;
uwsgi_error("fr_recv_uwsgi_header()");
return -1;
}
cs->buffer_pos += len;
// header ready
if (cs->buffer_pos == 4) {
memcpy(&cs->uh, cs->buffer->buf, 4);
cs->buffer_pos = 0;
uwsgi_cr_hook_read(cs, fr_recv_uwsgi_vars);
}
return len;
}
void fr_session_close(struct corerouter_session *cs) {
struct fastrouter_session *fr = (struct fastrouter_session *) cs;
if (fr->post_buf) {
uwsgi_buffer_destroy(fr->post_buf);
}
}
void fastrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
cs->close = fr_session_close;
// set the first hook
uwsgi_cr_hook_read(cs, fr_recv_uwsgi_header);
}
int fastrouter_init() {
ufr.cr.session_size = sizeof(struct fastrouter_session);
ufr.cr.switch_events = uwsgi_fastrouter_switch_events;
ufr.cr.alloc_session = fastrouter_alloc_session;
uwsgi_corerouter_init((struct uwsgi_corerouter *) &ufr);
uwsgi_corerouter_init((struct uwsgi_corerouter *) &ufr);
return 0;
}
-20
View File
@@ -1,20 +0,0 @@
#include "../corerouter/cr.h"
#define FASTROUTER_STATUS_RECV_VARS 10
#define FASTROUTER_STATUS_BUFFERING 11
struct uwsgi_fastrouter {
struct uwsgi_corerouter cr;
};
struct fastrouter_session {
struct corerouter_session crs;
struct uwsgi_header uh;
char buffer[UMAX16];
};
void uwsgi_fastrouter_switch_events(struct uwsgi_corerouter *, struct corerouter_session *, int interesting_fd);
-356
View File
@@ -1,356 +0,0 @@
#include "../../uwsgi.h"
#include "fr.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_fastrouter ufr;
void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
// here i use directly corerouter_session
struct corerouter_session *fr_session = (struct corerouter_session *) data;
//uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !fr_session->hostname_len) {
fr_session->hostname = val;
fr_session->hostname_len = vallen;
return;
}
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !fr_session->has_key) {
fr_session->hostname = val;
fr_session->hostname_len = vallen;
return;
}
if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) {
fr_session->has_key = 1;
fr_session->hostname = val;
fr_session->hostname_len = vallen;
return;
}
if (ufr.cr.post_buffering > 0) {
if (!uwsgi_strncmp("CONTENT_LENGTH", 14, key, keylen)) {
fr_session->post_cl = uwsgi_str_num(val, vallen);
return;
}
}
}
void uwsgi_fastrouter_switch_events(struct uwsgi_corerouter *ucr, struct corerouter_session *cs, int interesting_fd) {
struct fastrouter_session *fr_session = (struct fastrouter_session *) cs;
socklen_t solen = sizeof(int);
struct iovec iov[2];
struct msghdr msg;
union {
struct cmsghdr cmsg;
char control[CMSG_SPACE(sizeof(int))];
} msg_control;
struct cmsghdr *cmsg;
ssize_t len;
char *post_tmp_buf[UMAX16];
switch (cs->status) {
case COREROUTER_STATUS_RECV_HDR:
len = recv(cs->fd, (char *) (&fr_session->uh) + cs->h_pos, 4 - cs->h_pos, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ucr->queue, cs->fd);
#endif
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
corerouter_close_session(ucr, cs);
break;
}
cs->h_pos += len;
if (cs->h_pos == 4) {
#ifdef UWSGI_DEBUG
uwsgi_log("modifier1: %d pktsize: %d modifier2: %d\n", fr_session->uh.modifier1, fr_session->uh.pktsize, fr_session->uh.modifier2);
#endif
cs->status = FASTROUTER_STATUS_RECV_VARS;
}
break;
case FASTROUTER_STATUS_RECV_VARS:
if (interesting_fd == -1) {
goto choose_node;
}
len = recv(cs->fd, fr_session->buffer + cs->pos, fr_session->uh.pktsize - cs->pos, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ucr->queue, cs->fd);
#endif
if (len <= 0) {
uwsgi_error("recv()");
corerouter_close_session(ucr, cs);
break;
}
cs->pos += len;
if (cs->pos == fr_session->uh.pktsize) {
if (uwsgi_hooked_parse(fr_session->buffer, fr_session->uh.pktsize, fr_get_hostname, (void *) fr_session)) {
corerouter_close_session(ucr, cs);
break;
}
if (cs->hostname_len == 0) {
corerouter_close_session(ucr, cs);
break;
}
// the mapper hook
choose_node:
if (ucr->mapper(ucr, cs))
break;
// no address found
if (!cs->instance_address_len) {
// if fallback nodes are configured, trigger them
if (ucr->fallback) {
cs->instance_failed = 1;
}
corerouter_close_session(ucr, cs);
break;
}
if (ucr->post_buffering > 0 && cs->post_cl > ucr->post_buffering) {
cs->status = FASTROUTER_STATUS_BUFFERING;
cs->buf_file_name = uwsgi_tmpname(ucr->pb_base_dir, "uwsgiXXXXX");
if (!cs->buf_file_name) {
uwsgi_error("tempnam()");
corerouter_close_session(ucr, cs);
break;
}
cs->post_remains = cs->post_cl;
// 2 + UWSGI_POSTFILE + 2 + cs->buf_file_name
if (fr_session->uh.pktsize + (2 + 14 + 2 + strlen(cs->buf_file_name)) > UMAX16) {
uwsgi_log("unable to buffer request body to file %s: not enough space\n", cs->buf_file_name);
corerouter_close_session(ucr, cs);
break;
}
char *ptr = fr_session->buffer + fr_session->uh.pktsize;
uint16_t bfn_len = strlen(cs->buf_file_name);
*ptr++ = 14;
*ptr++ = 0;
memcpy(ptr, "UWSGI_POSTFILE", 14);
ptr += 14;
*ptr++ = (char) (bfn_len & 0xff);
*ptr++ = (char) ((bfn_len >> 8) & 0xff);
memcpy(ptr, cs->buf_file_name, bfn_len);
fr_session->uh.pktsize += 2 + 14 + 2 + bfn_len;
cs->buf_file = fopen(cs->buf_file_name, "w");
if (!cs->buf_file) {
uwsgi_error_open(cs->buf_file_name);
corerouter_close_session(ucr, cs);
break;
}
}
else {
cs->pass_fd = is_unix(cs->instance_address, cs->instance_address_len);
cs->instance_fd = uwsgi_connectn(cs->instance_address, cs->instance_address_len, 0, 1);
if (cs->instance_fd < 0) {
cs->instance_failed = 1;
cs->soopt = errno;
corerouter_close_session(ucr, cs);
break;
}
cs->status = COREROUTER_STATUS_CONNECTING;
ucr->cr_table[cs->instance_fd] = cs;
event_queue_add_fd_write(ucr->queue, cs->instance_fd);
}
}
break;
case COREROUTER_STATUS_CONNECTING:
if (interesting_fd == cs->instance_fd) {
if (getsockopt(cs->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&cs->soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
cs->instance_failed = 1;
corerouter_close_session(ucr, cs);
break;
}
if (cs->soopt) {
cs->instance_failed = 1;
corerouter_close_session(ucr, cs);
break;
}
fr_session->uh.modifier1 = cs->modifier1;
iov[0].iov_base = &fr_session->uh;
iov[0].iov_len = 4;
iov[1].iov_base = fr_session->buffer;
iov[1].iov_len = fr_session->uh.pktsize;
// increment node requests counter
if (cs->un)
cs->un->requests++;
// fd passing: PERFORMANCE EXTREME BOOST !!!
if (cs->pass_fd && !uwsgi.no_fd_passing) {
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 2;
msg.msg_flags = 0;
msg.msg_control = &msg_control;
msg.msg_controllen = sizeof(msg_control);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(cmsg), &cs->fd, sizeof(int));
if (sendmsg(cs->instance_fd, &msg, 0) < 0) {
uwsgi_error("sendmsg()");
}
corerouter_close_session(ucr, cs);
break;
}
if (writev(cs->instance_fd, iov, 2) < 0) {
uwsgi_error("writev()");
corerouter_close_session(ucr, cs);
break;
}
event_queue_fd_write_to_read(ucr->queue, cs->instance_fd);
cs->status = COREROUTER_STATUS_RESPONSE;
}
break;
case COREROUTER_STATUS_RESPONSE:
// data from instance
if (interesting_fd == cs->instance_fd) {
len = recv(cs->instance_fd, fr_session->buffer, UMAX16, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ucr->queue, cs->instance_fd);
#endif
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
corerouter_close_session(ucr, cs);
break;
}
len = send(cs->fd, fr_session->buffer, len, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("send()");
corerouter_close_session(ucr, cs);
break;
}
// update transfer statistics
if (cs->un)
cs->un->transferred += len;
}
// body from client
else if (interesting_fd == cs->fd) {
//uwsgi_log("receiving body...\n");
len = recv(cs->fd, fr_session->buffer, UMAX16, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ucr->queue, cs->fd);
#endif
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
corerouter_close_session(ucr, cs);
break;
}
len = send(cs->instance_fd, fr_session->buffer, len, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("send()");
corerouter_close_session(ucr, cs);
break;
}
}
break;
case FASTROUTER_STATUS_BUFFERING:
len = recv(cs->fd, post_tmp_buf, UMIN(UMAX16, cs->post_remains), 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ucr->queue, cs->fd);
#endif
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
corerouter_close_session(ucr, cs);
break;
}
if (fwrite(post_tmp_buf, len, 1, cs->buf_file) != 1) {
uwsgi_error("fwrite()");
corerouter_close_session(ucr, cs);
break;
}
cs->post_remains -= len;
if (cs->post_remains == 0) {
// close the buf_file ASAP
fclose(cs->buf_file);
cs->buf_file = NULL;
cs->pass_fd = is_unix(cs->instance_address, cs->instance_address_len);
cs->instance_fd = uwsgi_connectn(cs->instance_address, cs->instance_address_len, 0, 1);
if (cs->instance_fd < 0) {
cs->instance_failed = 1;
corerouter_close_session(ucr, cs);
break;
}
cs->status = COREROUTER_STATUS_CONNECTING;
ucr->cr_table[cs->instance_fd] = cs;
event_queue_add_fd_write(ucr->queue, cs->instance_fd);
}
break;
// fallback to destroy !!!
default:
uwsgi_log("unknown event: closing session\n");
corerouter_close_session(ucr, cs);
break;
}
}
+3 -1
View File
@@ -4,4 +4,6 @@ CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['fastrouter', 'fr_events']
REQUIRES = ['corerouter']
GCC_LIST = ['fastrouter']
+2 -2
View File
@@ -15,7 +15,7 @@ VALUE uwsgi_fiber_request() {
return Qnil;
}
inline static void fiber_schedule_to_req() {
static inline void fiber_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
@@ -33,7 +33,7 @@ inline static void fiber_schedule_to_req() {
}
inline static void fiber_schedule_to_main(struct wsgi_request *wsgi_req) {
static inline void fiber_schedule_to_main(struct wsgi_request *wsgi_req) {
rb_fiber_yield(0, NULL);
uwsgi.wsgi_req = wsgi_req;
+10 -7
View File
@@ -1,27 +1,30 @@
import os
NAME='fiber'
try:
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
except:
RUBYPATH = 'ruby'
NAME='fiber'
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-DRUBY19')
CFLAGS.append('-Wno-unused-parameter')
rbconfig = 'RbConfig'
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyhdrdir']\"" % rbconfig).read().rstrip()
if includedir == 'nil':
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + includedir)
else:
CFLAGS.append('-I' + includedir)
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['arch']\"").read().rstrip()
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + archdir)
CFLAGS.append('-I' + archdir + '/' + arch)
CFLAGS.append('-I' + includedir + '/' + arch)
LDFLAGS = []
LIBS = []
+246 -8
View File
@@ -10,6 +10,10 @@ extern struct uwsgi_python up;
if (ret) { Py_DECREF(ret); }\
ret = PyObject_CallMethod(watcher, "stop", NULL);\
if (ret) { Py_DECREF(ret); }
#define stop_the_watchers_and_clear stop_the_watchers\
Py_DECREF(current); Py_DECREF(current_greenlet);\
Py_DECREF(watcher);\
Py_DECREF(timer);
struct uwsgi_gevent {
@@ -32,6 +36,9 @@ void uwsgi_opt_setup_gevent(char *opt, char *value, void *null) {
// set async mode
uwsgi_opt_set_int(opt, value, &uwsgi.async);
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 30;
}
// set loop engine
uwsgi.loop = "gevent";
@@ -173,9 +180,13 @@ edge:
goto edge;
}
goto clear;
}
// on linux we need to set the socket in non-blocking as it is not inherited
#ifdef __linux__
uwsgi_socket_nb(wsgi_req->poll.fd);
#endif
// hack to easily pass wsgi_req pointer to the greenlet
PyTuple_SetItem(ugevent.greenlet_args, 1, PyLong_FromLong((long)wsgi_req));
@@ -195,6 +206,221 @@ clear:
return Py_None;
}
ssize_t uwsgi_gevent_hook_input_read(struct wsgi_request *wsgi_req, char *tmp_buf, size_t remains, size_t *tmp_pos) {
/// create a watcher for reads
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
if (!watcher) return -1;
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (!timer) {
Py_DECREF(watcher);
return -1;
}
PyObject *current_greenlet = GET_CURRENT_GREENLET;
PyObject *current = PyObject_GetAttrString(current_greenlet, "switch");
while(remains) {
PyObject *ret = PyObject_CallMethod(watcher, "start", "OO", current, watcher);
if (!ret) {
stop_the_watchers_and_clear
return -1;
}
Py_DECREF(ret);
ret = PyObject_CallMethod(timer, "again", "OO", current, timer);
if (!ret) {
stop_the_watchers_and_clear
return -1;
}
Py_DECREF(ret);
ret = PyObject_CallMethod(ugevent.hub, "switch", NULL);
wsgi_req->switches++;
if (!ret) {
stop_the_watchers_and_clear
return -1;
}
Py_DECREF(ret);
if (ret == timer) {
stop_the_watchers_and_clear
return 0;
}
UWSGI_RELEASE_GIL;
ssize_t rlen = read(wsgi_req->poll.fd, tmp_buf+*tmp_pos, remains);
if (rlen <= 0) {
if (rlen < 0)
uwsgi_error("[uwsgi-gevent] read()");
UWSGI_GET_GIL
stop_the_watchers_and_clear
return -1;
}
*tmp_pos += rlen;
remains -= rlen;
UWSGI_GET_GIL
stop_the_watchers
}
Py_DECREF(current);
Py_DECREF(current_greenlet);
Py_DECREF(watcher);
Py_DECREF(timer);
return *tmp_pos;
}
ssize_t uwsgi_gevent_hook_input_readline(struct wsgi_request *wsgi_req, char *readline, size_t max_size) {
ssize_t rlen = 0;
/// create a watcher for reads
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
if (!watcher) return -1;
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (!timer) {
Py_DECREF(watcher);
return -1;
}
PyObject *current_greenlet = GET_CURRENT_GREENLET;
PyObject *current = PyObject_GetAttrString(current_greenlet, "switch");
PyObject *ret = PyObject_CallMethod(watcher, "start", "OO", current, watcher);
if (!ret) {
stop_the_watchers_and_clear
return -1;
}
Py_DECREF(ret);
ret = PyObject_CallMethod(timer, "again", "OO", current, timer);
if (!ret) {
stop_the_watchers_and_clear
return -1;
}
Py_DECREF(ret);
ret = PyObject_CallMethod(ugevent.hub, "switch", NULL);
wsgi_req->switches++;
if (!ret) {
stop_the_watchers_and_clear
return -1;
}
Py_DECREF(ret);
if (ret == timer) {
stop_the_watchers_and_clear
return 0;
}
UWSGI_RELEASE_GIL;
if (max_size > 0 && max_size < UWSGI_PY_READLINE_BUFSIZE) {
rlen = read(wsgi_req->poll.fd, readline, max_size);
}
else {
rlen = read(wsgi_req->poll.fd, readline, UWSGI_PY_READLINE_BUFSIZE);
}
UWSGI_GET_GIL;
stop_the_watchers_and_clear
return rlen;
}
void uwsgi_gevent_nb_write(struct wsgi_request *wsgi_req, PyObject *str) {
PyObject *ret;
char *content = PyString_AsString(str);
size_t content_len = PyString_Size(str);
// do not try to write empty chunks
if (content_len == 0) return;
/// create a watcher for writes
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 2);
if (!watcher) goto error;
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (!timer) {
Py_DECREF(watcher);
goto error;
}
PyObject *current_greenlet = GET_CURRENT_GREENLET;
PyObject *current = PyObject_GetAttrString(current_greenlet, "switch");
char *ptr = content;
size_t remains = content_len;
// this is the main writing cycle, wait for writability and send...
for(;;) {
ret = PyObject_CallMethod(watcher, "start", "OO", current, watcher);
if (!ret) {
stop_the_watchers_and_clear
goto error;
}
Py_DECREF(ret);
ret = PyObject_CallMethod(timer, "again", "OO", current, timer);
if (!ret) {
stop_the_watchers_and_clear
goto error;
}
Py_DECREF(ret);
ret = PyObject_CallMethod(ugevent.hub, "switch", NULL);
wsgi_req->switches++;
if (!ret) {
stop_the_watchers_and_clear
goto error;
}
Py_DECREF(ret);
if (ret == timer) {
goto fail;
}
// ok we can write a chunk to the socket
UWSGI_RELEASE_GIL
ssize_t len = write(wsgi_req->poll.fd, ptr, remains);
UWSGI_GET_GIL
if (len > 0) {
ptr += len;
remains -= len;
wsgi_req->response_size += len;
if (remains == 0) {
break;
}
stop_the_watchers
continue;
}
else if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
stop_the_watchers
continue;
}
}
fail:
stop_the_watchers_and_clear
goto error;
}
stop_the_watchers
Py_DECREF(current); Py_DECREF(current_greenlet);
Py_DECREF(watcher);
Py_DECREF(timer);
return ;
error:
if (PyErr_Occurred())
PyErr_Print();
wsgi_req->write_errors++;
}
PyObject *uwsgi_gevent_wait(PyObject *watcher, PyObject *timer, PyObject *current) {
PyObject *ret;
@@ -205,7 +431,7 @@ PyObject *uwsgi_gevent_wait(PyObject *watcher, PyObject *timer, PyObject *curren
Py_DECREF(ret);
// start the timeout handler
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
ret = PyObject_CallMethod(timer, "again", "OO", current, timer);
if (!ret) return NULL;
Py_DECREF(ret);
@@ -237,7 +463,7 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
if (!watcher) goto clear1;
// a timer to implement timeoit (thanks Denis)
// a timer to implement timeout (thanks Denis)
timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (!timer) goto clear0;
@@ -246,6 +472,7 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
for(;;) {
// wait for data in the socket
ret = uwsgi_gevent_wait(watcher, timer, greenlet_switch);
wsgi_req->switches++;
if (!ret) goto clear_and_stop;
// we can safely decref here as watcher and timer has got a +1 for start() method
@@ -316,6 +543,13 @@ PyMethodDef uwsgi_gevent_my_signal_def[] = { {"uwsgi_gevent_my_signal", py_uwsgi
PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler", py_uwsgi_gevent_signal_handler, METH_VARARGS, ""} };
PyMethodDef uwsgi_gevent_unix_signal_handler_def[] = { {"uwsgi_gevent_unix_signal_handler", py_uwsgi_gevent_graceful, METH_VARARGS, ""} };
void gil_gevent_get() {
pthread_setspecific(up.upt_gil_key, (void *) PyGILState_Ensure());
}
void gil_gevent_release() {
PyGILState_Release((PyGILState_STATE) pthread_getspecific(up.upt_gil_key));
}
void gevent_loop() {
@@ -323,12 +557,15 @@ void gevent_loop() {
uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n");
}
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
uwsgi_log("!!! Running gevent with a socket-timeout lower than 30 seconds is not recommended, tune it with --socket-timeout !!!\n");
}
// get the GIL
UWSGI_GET_GIL
// ..then reset GIL subsystem as noop (gevent IO will take care of it...)
up.gil_get = gil_fake_get;
up.gil_release = gil_fake_release;
up.gil_get = gil_gevent_get;
up.gil_release = gil_gevent_release;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
@@ -338,6 +575,9 @@ void gevent_loop() {
}
uwsgi.current_wsgi_req = uwsgi_gevent_current_wsgi_req;
up.hook_write_string = uwsgi_gevent_nb_write;
up.hook_wsgi_input_read = uwsgi_gevent_hook_input_read;
up.hook_wsgi_input_readline = uwsgi_gevent_hook_input_readline;
PyObject *gevent_dict = get_uwsgi_pydict("gevent");
if (!gevent_dict) uwsgi_pyexit;
@@ -350,8 +590,6 @@ void gevent_loop() {
exit(1);
}
ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn");
if (!ugevent.spawn) uwsgi_pyexit;
+110
View File
@@ -0,0 +1,110 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
void (*uwsgi_go_helper_post_fork_c)();
void (*uwsgi_go_helper_post_init_c)();
void * (*uwsgi_go_helper_env_new_c)(struct wsgi_request *);
void (*uwsgi_go_helper_env_add_c)(void *, char *, int, char *, int);
void (*uwsgi_go_helper_request_c)(void *, struct wsgi_request *);
int (*uwsgi_go_helper_signal_handler_c)(int, void *);
void (*uwsgi_go_helper_run_core_c)(int);
void uwsgi_go_post_fork() {
uwsgi_go_helper_post_fork_c();
}
void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
// set async mode
uwsgi_opt_set_int(opt, value, &uwsgi.async);
// set loop engine
uwsgi.loop = "goroutines";
}
struct uwsgi_option uwsgi_go_options[] = {
{"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
{0, 0, 0, 0, 0, 0, 0},
};
#define uwsgi_go_get_symbol(x) x ## _c = dlsym(RTLD_DEFAULT, #x);\
if (!x ## _c) {\
uwsgi_log("[uwsgi-go] unable to load " #x " function\n"); exit(1);\
}
int uwsgi_go_init() {
// build the functions table
uwsgi_go_get_symbol(uwsgi_go_helper_post_fork)
uwsgi_go_get_symbol(uwsgi_go_helper_post_init)
uwsgi_go_get_symbol(uwsgi_go_helper_env_new)
uwsgi_go_get_symbol(uwsgi_go_helper_env_add)
uwsgi_go_get_symbol(uwsgi_go_helper_request)
uwsgi_go_get_symbol(uwsgi_go_helper_signal_handler)
uwsgi_go_get_symbol(uwsgi_go_helper_run_core)
// call PostInit()
uwsgi_go_helper_post_init_c();
return 0;
}
int uwsgi_go_request(struct wsgi_request *wsgi_req) {
/* Standard GO request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log("Invalid GO request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
wsgi_req->async_environ = uwsgi_go_helper_env_new_c(wsgi_req);
int i;
for(i=0;i<wsgi_req->var_cnt;i++) {
uwsgi_go_helper_env_add_c(wsgi_req->async_environ, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len,
wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
i++;
}
uwsgi_go_helper_request_c(wsgi_req->async_environ, wsgi_req);
return UWSGI_OK;
}
void uwsgi_go_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
int uwsgi_go_signal_handler(uint8_t signum, void *handler) {
return uwsgi_go_helper_signal_handler_c((int)signum, handler);
}
void goroutines_loop() {
int i;
for (i = 1; i < uwsgi.async; i++) {
uwsgi_go_helper_run_core_c(i);
}
simple_loop_run_int(0);
}
void uwsgi_go_on_load() {
uwsgi_register_loop("goroutines", goroutines_loop);
}
struct uwsgi_plugin go_plugin = {
.name = "go",
.modifier1 = 11,
.request = uwsgi_go_request,
.after_request = uwsgi_go_after_request,
.post_fork = uwsgi_go_post_fork,
.init = uwsgi_go_init,
.signal_handler = uwsgi_go_signal_handler,
.on_load = uwsgi_go_on_load,
.options = uwsgi_go_options,
};
+409
View File
@@ -0,0 +1,409 @@
/*
uWSGI go integration package
*/
package uwsgi
/*
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
// commodity functions to simulate argc/argv
static char ** uwsgi_go_helper_create_argv(int len) {
return uwsgi_calloc(sizeof(char *) * len);
}
static void uwsgi_go_helper_set_argv(char **argv, int pos, char *item) {
argv[pos] = item;
}
*/
import "C"
import (
"os"
"net/http"
"net/http/cgi"
"unsafe"
"strings"
"strconv"
"io"
)
// this stores the modifier used by the go plugin (default 11)
var uwsgi_modifier1 int = -1;
// the following to objects are used to implement a sort of GC to avoid request environ and
// signal handlers to be garbage collected
var uwsgi_env_gc = make(map[*C.struct_wsgi_request](*map[string]string))
var uwsgi_signals_gc = make([]*func(int), 256)
var uwsgi_default_request_handler func(http.ResponseWriter, *http.Request) = nil
var uwsgi_default_handler http.Handler = nil
var uwsgi_post_fork_hook func() = nil
var uwsgi_post_init_hook func() = nil
/*
uWSGI api functions
*/
// raise a uWSGI signal
func Signal(signum int) {
if C.uwsgi.master_process == 0 {
return
}
C.uwsgi_signal_send(C.uwsgi.signal_socket, C.uint8_t(signum))
}
// set a user lock
func Lock(num int) {
C.uwsgi_user_lock(C.int(num));
}
// unset a user lock
func Unlock(num int) {
C.uwsgi_user_unlock(C.int(num));
}
// add a timer
func AddTimer(signum int, seconds int) bool {
if C.uwsgi.master_process == 0 {
return false
}
if int(C.uwsgi_add_timer(C.uint8_t(signum), C.int(seconds))) == 0 {
return true
}
return false
}
// add a red black timer
func AddRbTimer(signum int, seconds int) bool {
if C.uwsgi.master_process == 0 {
return false
}
if int(C.uwsgi_signal_add_rb_timer(C.uint8_t(signum), C.int(seconds), C.int(0))) == 0 {
return true
}
return false
}
// check if a signal is registered
func SignalRegistered(signum int) bool {
if C.uwsgi.master_process == 0 {
return false
}
if int(C.uwsgi_signal_registered(C.uint8_t(signum))) == 0 {
return false
}
return true
}
// register a signal
func RegisterSignal(signum int, who string, handler func(int)) bool {
if C.uwsgi.master_process == 0 {
return false
}
if uwsgi_modifier1 == -1 {
c_go := C.CString("go")
defer C.free(unsafe.Pointer(c_go))
uwsgi_modifier1 = int(C.uwsgi_plugin_modifier1(c_go))
if uwsgi_modifier1 == -1 {
return false
}
}
c_who := C.CString(who)
defer C.free(unsafe.Pointer(c_who))
if int(C.uwsgi_register_signal(C.uint8_t(signum), c_who, unsafe.Pointer(&handler), C.uint8_t(uwsgi_modifier1))) == 0 {
uwsgi_signals_gc[signum] = &handler
return true
}
return false
}
// get an item from the cache
func CacheGet(key string) []byte {
if int(C.uwsgi_cache_enabled()) == 0 {
return nil
}
k := C.CString(key)
defer C.free(unsafe.Pointer(k))
kl := len(key)
var vl C.uint64_t = C.uint64_t(0)
C.uwsgi_cache_rlock()
c_value := C.uwsgi_cache_get(k, C.uint16_t(kl), &vl)
var p []byte
if vl > 0 {
p = C.GoBytes((unsafe.Pointer)(c_value), C.int(vl))
} else {
p = nil
}
C.uwsgi_cache_rwunlock()
return p
}
// remove an intem from the cache
func CacheDel(key string) bool {
if int(C.uwsgi_cache_enabled()) == 0 {
return false
}
k := C.CString(key)
defer C.free(unsafe.Pointer(k))
kl := len(key)
C.uwsgi_cache_wlock()
if int(C.uwsgi_cache_del(k, C.uint16_t(kl), C.uint64_t(0))) < 0 {
C.uwsgi_cache_rwunlock();
return false;
}
C.uwsgi_cache_rwunlock();
return true
}
// check if an item exists in the cache
func CacheExists(key string) bool {
if int(C.uwsgi_cache_enabled()) == 0 {
return false
}
k := C.CString(key)
defer C.free(unsafe.Pointer(k))
kl := len(key)
C.uwsgi_cache_rlock()
if int(C.uwsgi_cache_exists(k, C.uint16_t(kl))) > 0 {
C.uwsgi_cache_rwunlock();
return true;
}
C.uwsgi_cache_rwunlock();
return false
}
// put an item in the cache
func CacheSetFlags(key string, p []byte, expires uint64, flags int) bool {
if int(C.uwsgi_cache_enabled()) == 0 {
return false
}
k := C.CString(key)
defer C.free(unsafe.Pointer(k))
kl := len(key)
v := unsafe.Pointer(&p[0])
vl := len(p)
C.uwsgi_cache_wlock()
if int(C.uwsgi_cache_set(k, C.uint16_t(kl), (*C.char)(v), C.uint64_t(vl), C.uint64_t(expires), C.uint16_t(flags))) < 0 {
C.uwsgi_cache_rwunlock();
return false;
}
C.uwsgi_cache_rwunlock();
return true
}
func CacheSet(key string, p []byte, expires uint64) bool {
return CacheSetFlags(key, p, expires, 0);
}
func CacheUpdate(key string, p []byte, expires uint64) bool {
return CacheSetFlags(key, p, expires, 2);
}
// get the current worker id
func WorkerId() int {
return int(C.uwsgi.mywid)
}
// get the current mule id
func MuleId() int {
return int(C.uwsgi.muleid)
}
// get the current logsize (if available)
func LogSize() int64 {
return int64(C.uwsgi.shared.logsize)
}
func PostFork(hook func()) {
uwsgi_post_fork_hook = hook
}
func PostInit(hook func()) {
uwsgi_post_init_hook = hook
}
func RequestHandler(hook func(http.ResponseWriter, *http.Request)) {
uwsgi_default_request_handler = hook
}
func Handler(handler http.Handler) {
uwsgi_default_handler = handler
}
/*
C -> go and go -> C bridges
*/
//export uwsgi_go_helper_post_fork
func uwsgi_go_helper_post_fork() {
if uwsgi_post_fork_hook != nil {
uwsgi_post_fork_hook()
}
}
//export uwsgi_go_helper_post_init
func uwsgi_go_helper_post_init() {
if uwsgi_post_init_hook != nil {
uwsgi_post_init_hook()
}
}
//export uwsgi_go_helper_env_new
func uwsgi_go_helper_env_new(wsgi_req *C.struct_wsgi_request) *map[string]string {
var env map[string]string
env = make(map[string]string)
// track env to avoid it being garbage collected...
uwsgi_env_gc[wsgi_req] = &env
return &env
}
//export uwsgi_go_helper_env_add
func uwsgi_go_helper_env_add(env *map[string]string, k *C.char, kl C.int, v *C.char, vl C.int) {
var mk string = C.GoStringN(k, kl)
var mv string = C.GoStringN(v, vl)
(*env)[mk] = mv
}
/*
http.* implementations
*/
type ResponseWriter struct {
r *http.Request
wsgi_req *C.struct_wsgi_request
headers http.Header
wroteHeader bool
headers_chunk string
}
func (w *ResponseWriter) Write(p []byte) (n int, err error) {
if !w.wroteHeader {
w.WriteHeader(http.StatusOK)
}
m := len(p)
C.uwsgi_simple_response_write(w.wsgi_req, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(m))
return m+n, err
}
func (w *ResponseWriter) WriteHeader(status int) {
proto := "HTTP/1.0"
if w.r.ProtoAtLeast(1, 1) {
proto = "HTTP/1.1"
}
codestring := http.StatusText(status)
w.headers_chunk += proto + " " + strconv.Itoa(status) + " " + codestring + "\r\n"
C.uwsgi_simple_set_status(w.wsgi_req, C.int(status))
if w.headers.Get("Content-Type") == "" {
w.headers.Set("Content-Type", "text/html; charset=utf-8")
}
for k := range w.headers {
for _, v := range w.headers[k] {
v = strings.NewReplacer("\n", " ", "\r", " ").Replace(v)
v = strings.TrimSpace(v)
w.headers_chunk += k + ": " + v + "\r\n"
C.uwsgi_simple_inc_headers(w.wsgi_req)
}
}
w.headers_chunk += "\r\n"
c_h_chunk := C.CString(w.headers_chunk)
defer C.free(unsafe.Pointer(c_h_chunk))
C.uwsgi_simple_response_write_header(w.wsgi_req, c_h_chunk, C.size_t(len(w.headers_chunk)))
w.wroteHeader = true
}
func (w *ResponseWriter) Header() http.Header {
return w.headers
}
type BodyReader struct {
wsgi_req *C.struct_wsgi_request
}
// there is no close in request body
func (br *BodyReader) Close() error {
return nil
}
func (br *BodyReader) Read(p []byte) (n int, err error) {
m := len(p)
rlen := int(C.uwsgi_simple_request_read(br.wsgi_req, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(m)))
if rlen < 0 {
err = io.ErrUnexpectedEOF
rlen = 0
} else if rlen == 0 {
err = io.EOF
}
return rlen, err
}
//export uwsgi_go_helper_request
func uwsgi_go_helper_request(env *map[string]string, wsgi_req *C.struct_wsgi_request) {
httpReq, err := cgi.RequestFromMap(*env)
if err != nil {
} else {
httpReq.Body = &BodyReader{wsgi_req}
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false, ""}
if uwsgi_default_request_handler != nil {
uwsgi_default_request_handler(&w, httpReq)
} else if uwsgi_default_handler != nil {
uwsgi_default_handler.ServeHTTP(&w, httpReq)
} else {
http.DefaultServeMux.ServeHTTP(&w, httpReq)
}
}
}
//export uwsgi_go_helper_signal_handler
func uwsgi_go_helper_signal_handler(signum int, handler *func(int)) int {
(*handler)(signum)
return 0;
}
//export uwsgi_go_helper_run_core
func uwsgi_go_helper_run_core(core_id int) {
go C.simple_loop_run_int(C.int(core_id))
}
/*
the main function, running the uWSGI server via libuwsgi.so
*/
func Run() {
argc := len(os.Args)
argv := C.uwsgi_go_helper_create_argv(C.int(argc))
for i, s := range os.Args {
C.uwsgi_go_helper_set_argv(argv, C.int(i), C.CString(s))
}
C.uwsgi_init(C.int(argc), argv, nil)
}
+28
View File
@@ -0,0 +1,28 @@
import os
NAME='go'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['go_plugin']
def post_build(config):
os.environ['GOPATH'] = 'plugins/go'
cflags = ['-I'+os.getcwd()]
for c in config.cflags:
if not c.startswith('-DUWSGI_BUILD_DATE') and not c.startswith('-DUWSGI_CFLAGS'):
cflags.append(c)
cflags.append('-Wno-implicit-function-declaration')
cflags.append('-Wno-implicit-int')
cflags.append('-Wno-unused-function')
cflags.append('-Wno-unused-variable')
os.environ['CGO_CFLAGS'] = ' '.join(cflags).replace('\\"', '')
base = os.path.dirname(config.get('bin_name'))
if not base:
base = "."
os.environ['CGO_LDFLAGS'] = '-L' + base + ' -L'+os.getcwd() + ' -luwsgi'
if os.system("go install uwsgi") != 0:
os._exit(1)
print("*** uwsgi go module available in $GOPATH %s/plugins/go ***" % os.getcwd())
+2 -2
View File
@@ -28,7 +28,7 @@ PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
PyMethodDef uwsgi_greenlet_request_method[] = {{"uwsgi_greenlet_request", py_uwsgi_greenlet_request, METH_VARARGS, ""}};
inline static void greenlet_schedule_to_req() {
static inline void greenlet_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
@@ -45,7 +45,7 @@ inline static void greenlet_schedule_to_req() {
}
inline static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
static inline void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
PyGreenlet_Switch(ugl.main, NULL, NULL);
uwsgi.wsgi_req = wsgi_req;
+853 -748
View File
File diff suppressed because it is too large Load Diff

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