Compare commits

..
616 Commits
Author SHA1 Message Date
Unbit ab4afdbeaa fixed template plugin 2013-11-09 06:39:29 +01:00
Unbit 54e2d698cb prepare for uWSGI 1.9.19 2013-11-09 04:58:52 +01:00
Unbit 8b0565c0b8 added metric api to ruby 2013-11-09 04:31:14 +01:00
unbit 102d6f25ed Merge pull request #447 from flavour/master
Support HTTP Status 509
2013-11-08 03:05:11 -08:00
Fran Boon d0a53aa976 Support HTTP Status 509
Whilst this isn't an official RFC, it's documented on e.g. Wikipedia. http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_Server_Error
2013-11-08 10:49:48 +00:00
Unbit f8cf808e47 metrics as objects in stats subsystem 2013-11-07 12:10:56 +01:00
Unbit f8bbd2177e added stats pusher default plugins 2013-11-07 11:27:40 +01:00
Unbit f44c145941 do not destroy the stats pusher loop on EINTR 2013-11-07 09:54:16 +01:00
Unbit f34ac9f6aa completed metric threshold subystem 2013-11-07 09:43:01 +01:00
Unbit b971230fd9 use uwsgi.start_tv for srand instead of recomputing it 2013-11-07 08:56:04 +01:00
Unbit 5c6340caac busy_workers and idle_workers must be GAUGE 2013-11-07 07:45:12 +01:00
Unbit c0b97b47d3 implemented #284 2013-11-07 06:43:13 +01:00
Unbit a6b7f6e5bb added better random initialization and rr/rand hash algos 2013-11-06 18:20:38 +01:00
Unbit 1b99f9a750 added no_content_length to the cache router 2013-11-06 11:44:47 +01:00
Unbit a434195318 transformation_template has been moved to a plugin 2013-11-06 11:39:34 +01:00
Unbit a6a8faea78 added 'uwsgi' transformation 2013-11-06 10:52:19 +01:00
Unbit 31458320ab optimization in sendnl routing 2013-11-06 10:35:39 +01:00
Unbit 037a1f7f77 fixed #404 2013-11-05 09:43:11 +01:00
Unbit 10d4d10ac9 do not register metrics if metrics subsystem is not enabled 2013-11-04 15:12:18 +01:00
Unbit 00e8d509f8 metrics for routed and unrouted signals 2013-11-04 15:07:40 +01:00
Unbit c9ca14df4d fixed rbtimers 2013-11-03 19:31:18 +01:00
unbit 841cdfc62d Merge pull request #443 from prymitive/carbon_no_retry
allow disabling retries in carbon
2013-11-02 11:19:08 -07:00
Łukasz Mierzwa fc7026c076 allow disabling retries in carbon 2013-11-02 18:59:25 +01:00
unbit b96581c183 Merge pull request #442 from xrmx/coverityjvm
Add jvm plugins to coverity build profile
2013-11-02 10:35:24 -07:00
Riccardo Magliocchetti 4fa5d72af6 Add jvm plugins to coverity build profile 2013-11-02 18:13:57 +01:00
unbit f4be581666 Merge pull request #441 from xrmx/jvmarch2
plugins/jvm: let override jvm arch
2013-11-02 10:07:39 -07:00
unbit 24fb5518d8 Merge pull request #440 from Kapishin/master
Fix typos
2013-11-02 10:07:08 -07:00
unbit 2e8061d62a Merge pull request #439 from xrmx/coverity0211
More Coverity fixes
2013-11-02 10:06:42 -07:00
Riccardo Magliocchetti 23d70f6936 plugins/jvm: let override jvm arch
On mixed 64 bit kernel / 32 bit userspace linux systems the jvm
does not get recognized automatically if installed.

Permit to force an arch by exporting JVM_ARCH which is way more
easier than exporting the full path for includes and libraries.
2013-11-02 17:54:20 +01:00
Pavlo Kapyshin 95ea88628a Fix typos 2013-11-02 18:40:05 +02:00
Riccardo Magliocchetti 68b411f487 plugins/xslt: correct logical operator
Fixes a null pointer dereference.

Reported by Coverity as CID #1125160
2013-11-02 16:38:10 +01:00
Riccardo Magliocchetti 40bfbc0a44 plugins/pty: Fix a couple of memory issues
Rpoerted by Coverity as CID #1125163 and #1125162
2013-11-02 16:33:48 +01:00
Riccardo Magliocchetti fc9b6ea275 plugins/xslt: fix memory leaks
Rpeorted by Coverity as CID #1125164
2013-11-02 16:25:50 +01:00
Riccardo Magliocchetti 522f3bb3a1 plugins/xslt: fix xmlfile lifecycle
Fixes an use after free and a memory leak.

Reported by Coverity as CID #1125165, #1125167
2013-11-02 16:17:53 +01:00
Riccardo Magliocchetti 743c7ceaa6 plugins/v8: fix double free
Reported by Coverity as CID #1125166
2013-11-02 16:09:58 +01:00
Riccardo Magliocchetti c780cd47ce Update coverity build profile
Add a few more plugins and remove go that does not build.
2013-11-02 15:53:23 +01:00
unbit 54e7e01c05 Merge pull request #437 from prymitive/stats_pusher_retry
Restore retry handling in carbon
2013-11-01 22:35:22 -07:00
Łukasz Mierzwa 7d422d11e4 port carbon plugin to support retries in stats pusher, replaces old non-functional retry handling 2013-11-01 20:07:08 +01:00
Łukasz Mierzwa 5c35b60d1d add retry support to stats pusher 2013-11-01 19:43:15 +01:00
Unbit 94353efb3f correctly support python2.4 2013-11-01 10:02:35 +01:00
Roberto De Ioris 0586a2ba47 fixed #436 2013-11-01 09:54:01 +01:00
Roberto De Ioris be6081c6f7 port the carbon metric feature to latest api 2013-11-01 09:51:00 +01:00
unbit 955fb6479e Merge pull request #435 from prymitive/carbon_use_metrics
enable switching stats source from carbon's own loop to metrics data
2013-11-01 01:50:09 -07:00
Łukasz Mierzwa 1b334e8cf7 enable switching stats source from carbon's own loop to metrics data, fixes #417 2013-10-31 18:38:54 +01:00
Unbit 718e198ac8 little optimization in master fifo 2013-10-28 22:14:50 +01:00
unbit 3757e5a8bb Merge pull request #433 from xrmx/coverity2810-2
More Coverity fixes
2013-10-28 14:13:25 -07:00
Riccardo Magliocchetti d505964321 plugins/gevent: don't dereference null pointer
We should not pass a NULL pointer to Py_DECREF. This is possible
if wsgi_req->socket->edge_trigger is true.

Reported by Coverity as CID #970981.
2013-10-28 19:38:02 +01:00
Riccardo Magliocchetti 1114c1a429 core/fifo: check array index read before dereferencing uwsgi_master_fifo_manage
Reported by Coverity as CID #1100821
2013-10-28 19:29:25 +01:00
Riccardo Magliocchetti f58a9c6119 plugins/router_hash: don't dereference a null pointer
In case this condition is true:

    if (urhc->items[i] == ';') {

but this is false:

    if (found == hashed_result)

for the latest loop iteration value would be set as NULL

This is a bit unfortunate because later we can:
- use it in arithmetics
- dereference it in uwsgi_req_append

To fix that update vallen only if value is not null.

Reported by Coverity sa CID #1100805.
2013-10-28 19:27:06 +01:00
Riccardo Magliocchetti e791cb2c00 core/utils: cleanup if condition
uwsgi.ksm_mappings_current_size cannot be 0 here.
A couple of lines above:

1219 if (uwsgi.ksm_mappings_current_size <= 0) {
1220     uwsgi_log("[uwsgi-KSM] unable to read /proc/self/maps data\n");
1221     return;
1222 }
2013-10-28 19:26:51 +01:00
Unbit f741dbb01b added options for metric thresholds 2013-10-28 17:18:45 +01:00
Unbit d5f0741e8d metrics threshold structures 2013-10-28 17:16:17 +01:00
Unbit b265ed8313 avoid kevent storm for stats pusher thread 2013-10-28 17:09:27 +01:00
Unbit 6cb160bb26 support for WSGI genrators in tornado 2013-10-28 09:55:06 +01:00
Unbit 009a3f2c0d fixed greenlet memory leaks 2013-10-28 07:59:45 +01:00
Unbit 11b3d1fb94 greenlet plugin still need a bit of checks for reference counting 2013-10-27 19:06:18 +01:00
Unbit 7a39472700 various improvements in greenlet plugin 2013-10-27 18:31:31 +01:00
Unbit 4489b48603 added tornado loop engine 2013-10-27 18:08:34 +01:00
Unbit d2f69af964 fixed #428 2013-10-26 05:47:47 +02:00
unbit 34e9dabffc Merge pull request #430 from xrmx/coverity2510
Fix some leaks reported by coverity
2013-10-25 19:14:19 -07:00
unbit 6a4f46639e Merge pull request #432 from TheRealBill/master
Fixing argument for length of the string 'destroy'
2013-10-25 19:09:56 -07:00
Bill Anderson 0d07ff25f9 Fixing argument for length of the string 'destroy' 2013-10-25 13:20:11 -05:00
Riccardo Magliocchetti c1d9c4ef12 core/utils: fix resource leak in uwsgi_write_intfile
The more error condition you squeeze in one line the more chances
to leak :)

Reported by Coverity as CID #1100812
2013-10-25 19:53:04 +02:00
Riccardo Magliocchetti 0227ff7a9b core/utils: fix resource leak
Reported by Coverity as CID #1100814
2013-10-25 19:45:51 +02:00
Riccardo Magliocchetti 082b178ae3 core/io: Fix resource leak
Reported by Coverity as CID #1100815
2013-10-25 19:41:27 +02:00
Riccardo Magliocchetti 0e695cbd6e core/fsmon: fix memory leak
Reported by Coverity as CID #1100817
2013-10-25 19:35:38 +02:00
Riccardo Magliocchetti be2ed4dc4a core/snmp: fix usage of pointer outside of scope
Reported by Coverity as CID #1112122
2013-10-25 19:30:08 +02:00
Riccardo Magliocchetti 4777666588 plugins/rrdtools: don't leak filename
Reported by coverity as CID #1112121
2013-10-25 19:26:58 +02:00
Unbit 5647057ecc fixed UWSGI_PROFILE usage 2013-10-25 09:27:45 +02:00
Unbit 94cb950058 better error reporting for cgroups 2013-10-25 08:26:51 +02:00
Unbit 8d65371bf6 completely skip cgroups initialization when non-root 2013-10-24 21:34:07 +02:00
Unbit c747a36ae1 added PROFILE to Makefile 2013-10-24 18:55:55 +02:00
Unbit e51cb65857 fixed #427 2013-10-24 18:52:03 +02:00
unbit 8fa4fdb8c8 Merge pull request #426 from apoh/master
set python-bin from enviroment variable in Makefile
2013-10-24 06:16:12 -07:00
apoh d584857c78 set python-bin from enviroment variable in Makefile
currently the Makefile can only deal with the python-binary
wich is link to python. If you like to compile uwsgi with a
different pyhton-version you can just use

export PYTHON_BIN=/path/to/your/python
2013-10-23 17:32:36 +02:00
Unbit f0b1d79f8b added metrics api to pypy 2013-10-22 19:37:21 +02:00
Unbit 28566ad772 threads must be implicit in PyPy 2013-10-22 19:29:12 +02:00
Unbit 40c0e139d4 added metric api to python plugin 2013-10-22 16:25:56 +02:00
Unbit 04f2444ea0 added --zabbix-template 2013-10-22 12:11:19 +02:00
Unbit 9f71d28afa snmp integration with metrics subsystem 2013-10-22 10:18:09 +02:00
Unbit af262fb325 completed metric file collector 2013-10-22 07:08:12 +02:00
Unbit 243657b5aa added pluggables metric collectors 2013-10-22 06:29:01 +02:00
Unbit 032302edaa fixed #425 2013-10-22 05:18:57 +02:00
Unbit d4bd658d84 added restorable metrics 2013-10-21 19:01:06 +02:00
Unbit 78843c3e06 added --vassal-set 2013-10-21 18:21:59 +02:00
Unbit 692ba1f6b3 added shortcut mode for --metric 2013-10-21 16:13:33 +02:00
Unbit 400a9d72ef reimplemented metrics initial_value 2013-10-21 15:59:25 +02:00
Unbit 11f8f0385a added router_metrics plugin 2013-10-21 15:48:37 +02:00
Unbit c40d15981c exposed the metric routing var 2013-10-21 14:32:59 +02:00
Unbit baa1bf21f1 expose metrics to request logging 2013-10-21 10:54:19 +02:00
Unbit 3dd3122236 ported rrdtool to the metric api 2013-10-21 10:37:50 +02:00
Unbit 927ef2ccde added sockets metrics 2013-10-19 18:33:41 +02:00
Unbit af6eaf6737 completed perl metric api 2013-10-19 09:54:28 +02:00
unbit 7c543f5627 Merge pull request #424 from prymitive/daemon_fix
daemon throttle code could pass values < 0 to sleep()
2013-10-18 14:11:52 -07:00
Łukasz Mierzwa b06e35c610 fixed sleep in daemons throttle code, sleep() only accepts unsigned int, but in some cases uWSGI could pass value < 0 2013-10-18 22:33:48 +02:00
unbit 842c2148d7 fixed websocket example 2013-10-18 20:18:51 +02:00
unbit a2a94bd78e fixed websocket example for python3 2013-10-18 19:28:55 +02:00
Unbit 4452c30fc8 fixed typecasting 2013-10-18 18:46:17 +02:00
Unbit f462792c8e fixed uwgsi-docs bug 98 2013-10-18 12:13:02 +02:00
Unbit 03879fdc0c first test for metric api from apps (perl only) 2013-10-18 09:35:04 +02:00
Unbit 389d0b95d5 added the zabbix plugin (metrics based) 2013-10-17 16:30:19 +02:00
Unbit 6ec32e192f added puwsgi protocol 2013-10-17 10:15:34 +02:00
Roberto De Ioris 22c034cdca removed uwsgidump protocol 2013-10-17 05:57:43 +02:00
unbit 396d8c3022 Merge pull request #422 from prymitive/metrics_cast
missing cast to long long in metrics
2013-10-16 15:26:13 -07:00
Łukasz Mierzwa a535ecbe17 missing cast to long long in metrics 2013-10-16 22:56:31 +02:00
Unbit fd436c3e4f starting 1.9.19-dev 2013-10-16 20:59:15 +02:00
Unbit e5c245ea2f fixed stdin and embed configs 2013-10-16 20:51:26 +02:00
Unbit 3008b7c83b fixed #420 2013-10-16 05:39:28 +02:00
Unbit eca6cd3066 added --iprint 2013-10-15 20:11:22 +02:00
Unbit 691a41f290 ignore specific vars with prefix UWSGI_ 2013-10-15 18:16:03 +02:00
Unbit df4cf539a1 automatically enable metrics with stats pushers 2013-10-15 16:11:59 +02:00
Unbit baa1167dfe exposed metric api functions 2013-10-15 16:02:52 +02:00
Unbit d8a83ab7cf added metric aliases 2013-10-15 15:04:10 +02:00
Unbit 8184351b3b implemented SUM metrics and parent/child relationship 2013-10-15 14:46:53 +02:00
Unbit 4a4dbbcf69 ported the stats plugin to the metric subsystem 2013-10-15 14:08:01 +02:00
Unbit 56f79efc74 fixed json format for metrics 2013-10-15 11:13:14 +02:00
Unbit ea073a9bbd exposes metrics to stats 2013-10-15 11:11:18 +02:00
Unbit c5b2ca4b20 added delta_requests and write_errors to metrics 2013-10-15 09:02:43 +02:00
Unbit c0f9d8d2ff prepare for file as metric source 2013-10-14 19:19:05 +02:00
Unbit 497660279f Merge branch 'master' of github.com:unbit/uwsgi 2013-10-14 15:11:09 +02:00
Unbit 625395bd26 preliminary metrics subsystem code 2013-10-14 15:10:53 +02:00
Unbit 79a7797409 fixed #415 2013-10-12 08:05:56 +02:00
Unbit 3b13de3e6e check for NULL dictionary values in python autoreloader 2013-10-12 00:34:31 +02:00
Unbit 7f99855527 1.9.18.1 2013-10-11 14:27:26 +02:00
Unbit 8c29178f81 fixed kFreeBSD support 2013-10-11 16:24:46 +02:00
Unbit ed71000033 fixed FreeBSD compilation 2013-10-11 09:44:50 +02:00
Unbit 20860ed069 fixed python3 build 2013-10-11 14:07:02 +02:00
Unbit 2e62f13917 fixed mono options parsing 2013-10-11 05:59:20 +02:00
Unbit 1b2a83ce70 updated gemspec for 1.9.18 2013-10-11 05:51:19 +02:00
Unbit 113ec5ae9e added minimal profiles 2013-10-11 05:05:07 +02:00
root 68e81828d1 finally fixed the problem with python and arm (raspberrypi/sheevaplug) 2013-10-11 02:50:40 +00:00
Unbit 543790dc83 auto-modifier1 only if modifier1 is 0 2013-10-10 09:29:28 +02:00
unbit be24060578 Merge pull request #414 from arkaitzj/master
Still need to loop again when EAGAIN after a read triggered by an event, Fixes #363
2013-10-09 20:14:05 -07:00
Arkaitz Jimenez bdedc1c94c Still need to loop again when EAGAIN after a read triggered by an event 2013-10-10 00:12:57 +02:00
unbit e2454aa898 Merge pull request #413 from prymitive/backlog2
fixed backlog2 example plugin
2013-10-08 18:55:10 -07:00
Łukasz Mierzwa dfa4834be3 fixed backlog2 example plugin 2013-10-08 23:16:03 +02:00
Unbit f204249110 better fallback for non-zero modifiers 2013-10-07 17:50:43 +02:00
Unbit f4c25a6cd1 prepare for 1.9.18 release 2013-10-07 13:23:05 +02:00
Unbit fbfbacce14 fixed attach.py 2013-10-07 13:03:50 +02:00
Unbit a0eed32b3f move uWSGI 1.9 to GPL2 + linking exception 2013-10-07 12:19:33 +02:00
Unbit 9fe9fe1bb6 fixed data:// scheme 2013-10-07 11:37:52 +02:00
Unbit 192312e3ea avoid crashing on non-conformant PSGI response headers 2013-10-07 10:21:39 +02:00
Unbit ee46fe6ba6 Merge branch 'master' of github.com:unbit/uwsgi 2013-10-07 10:11:59 +02:00
Unbit 58abd07a88 support remote sources for perl scripts 2013-10-07 10:11:50 +02:00
Unbit c246a6008e correctly returns http error on connect 2013-10-07 10:11:23 +02:00
Unbit 706f1b59c3 make clang happy 2013-10-07 09:52:32 +02:00
Unbit ddbc8920f7 use uwsgi_open_and_read for perl files 2013-10-07 09:50:56 +02:00
Roberto De Ioris 7e3bf6868e fixed perl autoreload when under clang 2013-10-06 11:01:12 +02:00
Unbit 4c7ecef577 added perl auto reloader 2013-10-06 10:52:27 +02:00
Unbit e3da0aaad4 automatically returns the default app even if the modifier is wrong 2013-10-06 09:26:08 +02:00
Unbit 99e576e40c support pty on NetBSD 2013-10-06 07:04:12 +02:00
Unbit 7604ce3441 --wsgi-accept-buffers 2013-10-05 12:34:57 +02:00
Unbit a0082b5b98 accepting buffer is an option: --wsgi-accept-buffer 2013-10-05 12:32:49 +02:00
Unbit c90c639348 --wsgi-strict disable string/bytes optimizations too 2013-10-05 09:09:53 +02:00
Unbit 2e188dc25a fixed big endian support for uwsgi protocol 2013-10-05 07:15:36 +02:00
Unbit 312d21cb3f added 'before' variants for vassals templating 2013-10-05 07:07:48 +02:00
unbit 4ee138be7c Merge pull request #411 from thekad/master
updating so jvm plugin can compile in arm
2013-10-04 21:22:01 -07:00
Jorge Gallegos 299aef99b3 updating so jvm plugin can compile in arm
This *should* work for all arm versions so far and still works for i386/x86_64
2013-10-04 16:39:54 -07:00
Unbit 06953e4547 fixed uwsgiconfig.py for embed_config 2013-10-04 17:13:10 +02:00
Unbit 7565ee8740 fixed a memleak spotted by cppcheck 2013-10-04 12:29:16 +02:00
Unbit 10377f02a3 run the autoreloader even in non-apps mode when non-lazy 2013-10-04 06:22:06 +02:00
Unbit a41e6e2c61 added --emperor-cap 2013-10-04 06:11:29 +02:00
Unbit 6b2b909d33 apply PR_SET_PDEATHSIG to vassals on linux 2013-10-03 19:46:33 +02:00
Unbit 70cd18bffb added --unshare2 2013-10-03 19:43:43 +02:00
Unbit d6be4bcad9 added --mountpoint-check 2013-10-03 14:42:52 +02:00
Unbit 85530b5d8e added --exit 2013-10-03 11:38:51 +02:00
Unbit e3848e84d3 expose more clone() flags 2013-10-03 10:42:55 +02:00
Unbit 4ec9312b10 pivot_root improvements 2013-10-02 16:52:14 +02:00
Unbit aedf3b2455 reindented core/utils.c 2013-10-02 13:58:18 +02:00
Unbit 2210ec7f71 added call scheme 2013-10-02 10:58:27 +02:00
Unbit a9bee41707 added UWSGI_ADDITIONAL_SOURCES env var and additional_sources buildconf option 2013-10-02 10:52:53 +02:00
Unbit 3adbfd100f allow overriding schemes 2013-10-02 10:39:41 +02:00
Unbit 8d8de4b8da pluginized uwsgi_open_and_read 2013-10-02 10:37:39 +02:00
Unbit 099403d554 fixed #409 2013-10-02 09:39:33 +02:00
Unbit 13938a6aa7 more consistent placeholders support 2013-10-02 09:31:48 +02:00
Unbit 9be3a4aaf8 various consistency fixes for strict mode + autoload 2013-10-02 08:41:43 +02:00
Unbit 009e42f349 fixed #409 2013-10-02 07:42:41 +02:00
Unbit 207dd3bc77 fixed #407 2013-10-02 07:36:14 +02:00
Unbit feec6b3151 do not set upper magic vars in --inherit or --include mode 2013-10-01 18:42:30 +02:00
Unbit bf8207f0f1 added magic vars for original config file 2013-10-01 18:16:01 +02:00
Unbit 9fcbc6ee68 added --set-placeholder/--set-ph 2013-10-01 15:50:46 +02:00
Unbit dcb58aaa34 added UWSGI_EMBED_CONFIG variable 2013-10-01 15:39:07 +02:00
Unbit 7163d8ddd4 fixed #406 2013-10-01 15:30:39 +02:00
Unbit c7b24eec45 fixed regression in --set as a workaround for broken getopt_long 2013-10-01 15:02:33 +02:00
Unbit 1e7098f787 fixed #405 2013-10-01 13:27:50 +02:00
Unbit b28f0d9863 fixed #405 2013-10-01 12:22:30 +02:00
Unbit b49c4f4af9 chdir at every emperor glob interaction 2013-10-01 11:38:29 +02:00
Unbit 2c39aafb0b honour --force-cwd 2013-10-01 11:32:17 +02:00
unbit 1036d9c18b Merge pull request #402 from xrmx/ia64
Ia64 fixes
2013-09-30 08:31:03 -07:00
Unbit f0c8cbf190 try specified rvm paths first 2013-09-30 17:12:54 +02:00
Unbit f51db4481b added sendfile support to raw mode 2013-09-30 15:45:27 +02:00
Unbit 717eba7ab3 implemented raw response for python 2013-09-30 15:25:00 +02:00
Unbit 3cc971ba55 raw sockets must be undeferred 2013-09-30 15:01:58 +02:00
Unbit 23b3d7483f introducing raw mode 2013-09-30 13:43:13 +02:00
unbit ba03837e29 Merge pull request #297 from prymitive/dfix
fixed dump daemon process termination
2013-09-30 04:41:37 -07:00
Łukasz Mierzwa 06952fbaff wait for deamon pid after SIGTERM to prevent it from becoming zombie 2013-09-30 12:56:01 +02:00
Unbit 27be00b4cc fixed #399 2013-09-30 11:47:14 +02:00
unbit b50a377190 Merge pull request #217 from prymitive/idle_fix
zero pids after worker killed due to --idle usage
2013-09-30 01:51:22 -07:00
Unbit 1ed9cb0bec prepare for 1.9.18 2013-09-30 09:46:17 +02:00
unbit a548ede3c7 Merge pull request #400 from xrmx/config-cleanup
Some uwsgiconfig.py cleanups
2013-09-30 00:44:38 -07:00
unbit de26c09030 Merge pull request #401 from prymitive/cheaper_fix_limit
adapted cheaper algos to work properly with cheaper limits
2013-09-30 00:41:45 -07:00
Unbit 19aa7c2560 clear exception on PyObject_CheckReadBuffer error 2013-09-30 09:40:40 +02:00
Unbit 215e0c4cbc typos 2013-09-30 09:26:58 +02:00
Unbit d484acefa4 use buffer protocol in WSGI response 2013-09-30 09:25:25 +02:00
Riccardo Magliocchetti 4032efd3e8 Add proper ifdefery for namespaces on ia64
Fix #398
2013-09-29 21:45:07 +02:00
Riccardo Magliocchetti f9d412bcca uwsgiconfig: restore obsolete linux check on ia64
Fix #397
2013-09-29 21:35:38 +02:00
Łukasz Mierzwa 5f52063b9e cheaper API change to allow signaling cheaper algo if it can spawn new workers or only cheap them. Fixes #394 2013-09-29 20:30:29 +02:00
Riccardo Magliocchetti 87833abb42 uwsgiconfig: add --debug and --asan options
--debug compiles with debug symbols
--asan adds support for compiling with address sanitizer, see
http://clang.llvm.org/docs/AddressSanitizer.html#usage
Should work with clang and gcc 4.8. Does not find as many issues
as valgrind but having lot less overhead could be enabled in more
situations.

While at it handle --cflags and --build together instead of
duplicating code.
2013-09-29 18:29:14 +02:00
Riccardo Magliocchetti 0fcbd5e334 uwsgiconfig: add --verbose switch
Print the whole compilation commandlines

Based on a patch from Jonas Smedegaard
2013-09-29 17:36:26 +02:00
Riccardo Magliocchetti 5b55bf5f5c uwsgiconfig: use optparse for arguments passing
This opens the possibility (if desired) to have multiple options
passed at the same time, the same options repeated, etc...
Also it gives an help for free.
2013-09-29 17:28:45 +02:00
Riccardo Magliocchetti b8cc1d962f uwsgiconfig: cleanup report initialization 2013-09-29 13:57:06 +02:00
Unbit 762c73e2ac close workers sockets in gateways 2013-09-28 12:06:22 +02:00
Unbit 57cd0e9135 closed #391 and #392 2013-09-28 12:01:59 +02:00
Roberto De Ioris 5e0a85bff0 use execv instead of execve 2013-09-28 05:56:13 +02:00
unbit d2eaef524c Merge pull request #393 from prymitive/cheaper_limit_typo
fixed stupid typo in cheaper rss limits options validation
2013-09-27 19:51:18 -07:00
Łukasz Mierzwa a98c5a3931 fixed stupid typo in cheaper rss limits options validation 2013-09-27 23:21:45 +02:00
Unbit 040da07323 added forkptyrouter-rows and forkptyrouter-cols 2013-09-27 16:10:55 +02:00
Unbit 34f43ec97b support pty in Debian kFreeBSD 2013-09-27 08:12:45 +02:00
Unbit 7e3cfe94d6 improved forkptyrouter 2013-09-26 20:29:04 +02:00
Unbit e2c3b650a1 completed --pty-uconnect 2013-09-26 20:03:02 +02:00
Unbit 404dfaeda7 fixed initial logging 2013-09-26 19:59:49 +02:00
Unbit a1ec530945 implemented uwsgi protocol for forkptyrouter 2013-09-26 19:28:09 +02:00
Unbit b8dfd617f2 minor fixes 2013-09-26 10:18:16 +02:00
Unbit f34ed4dc47 added --attach-control-daemon 2013-09-26 09:36:31 +02:00
Unbit cd2ff0e585 emperor proxy 2013-09-26 07:51:13 +02:00
Unbit 449955562f expose 'cursed' field in emperor stats 2013-09-26 07:09:57 +02:00
Unbit 41a4bbccfc added Emperor curse support 2013-09-26 07:04:08 +02:00
Unbit 87b17c001d some typo 2013-09-26 05:32:27 +02:00
Unbit 67b7753814 use MAP_FAILED check for mmap() 2013-09-25 16:24:20 +02:00
Unbit b190744b77 on kFreeBSD python atexit will make mess, disable it for now 2013-09-25 09:20:20 +02:00
Unbit 4b603071d8 preliminary support for Debian kFreeBSD 2013-09-25 07:18:17 +02:00
Unbit 16c55f0217 preliminary libffi plugin 2013-09-24 17:45:34 +02:00
Unbit c989f2fb33 added api func uwsgi_split_quoted 2013-09-24 17:45:03 +02:00
Unbit 6429a47b0d 1.9.17.1 2013-09-24 09:56:40 +02:00
Unbit f8a48a3ae9 fixed a bug with fd 0 2013-09-24 09:52:49 +02:00
Unbit fb3272d165 fixed a stupid bug with router_http 2013-09-23 16:33:41 +02:00
Unbit be5f67906e added --emperor-wrapper 2013-09-23 14:38:42 +02:00
Unbit f730023e88 fixed a typo 2013-09-23 09:18:43 +02:00
Unbit 50954d34db prepare for 1.9.17 2013-09-22 19:32:11 +02:00
Unbit ef2d9e781f implemented fifo slots and fixed chain reloading 2013-09-22 18:36:28 +02:00
Unbit a9bb310a20 various pty improvements 2013-09-19 11:21:10 +02:00
Unbit 86f37556da fixed logpipe 2013-09-19 11:08:28 +02:00
Unbit a57617c09a added fd: logger and routable log encoders 2013-09-19 06:41:09 +02:00
Unbit 63ac62cf1d allows ANSI sequences in config files via %[ 2013-09-19 05:55:20 +02:00
Unbit ac371730fd rename pypyuwsgi.py to pyuwsgi.py 2013-09-19 04:01:31 +02:00
Unbit 4ed6588c80 fixed #99 2013-09-19 03:59:15 +02:00
Unbit 81d20edc4c more cleanup 2013-09-19 03:55:27 +02:00
Unbit a9fc6adccf fixed #386 2013-09-19 03:41:23 +02:00
Unbit 21ad94ba4e implemented C fifo command 2013-09-18 17:40:02 +02:00
Unbit 571b9f27e1 added + and - fifo commands 2013-09-18 14:44:30 +02:00
Unbit cbf9ccf062 more brutal heartbeat emperor management 2013-09-18 12:03:35 +02:00
Unbit dd8fd8f19c implemented fifo command 'W' 2013-09-18 11:38:39 +02:00
Unbit 1535b8ee13 implemented graceful shutdown 2013-09-18 11:33:50 +02:00
Unbit f2491536dd implemented fifo command P 2013-09-18 11:20:55 +02:00
Unbit 88ce0181b3 added master fifo [2] 2013-09-18 11:16:15 +02:00
Unbit 4ad2658090 added master fifo 2013-09-18 11:08:56 +02:00
unbit 8d80c5e84d Merge pull request #388 from xtfxme/patch-1
pty.c: `--pty-exec` should have a `required_argument`
2013-09-17 23:49:29 -07:00
Unbit bae9235103 added the libtcc plugin (only for hooks) 2013-09-18 07:32:12 +02:00
C Anthony Risinger 8ae2d0d00c pty.c: --pty-exec should have a required_argument 2013-09-17 14:57:15 -05:00
Unbit 373b89e70c finally removed strtok() 2013-09-17 16:03:40 +02:00
Unbit c14e18b270 another round of strtok removals 2013-09-17 15:25:06 +02:00
Unbit 68ec3afd1a another round of strtok removal 2013-09-17 15:14:55 +02:00
Unbit 8918e81256 first attempt to change from strtok to strtok_r 2013-09-17 15:00:33 +02:00
Unbit 469fd697cb fixed #383 2013-09-17 14:16:41 +02:00
Unbit 20844ebfca Merge branch 'master' of github.com:unbit/uwsgi 2013-09-17 14:09:44 +02:00
Unbit 38652076d3 fixed #384 2013-09-17 14:09:00 +02:00
unbit f13ae47fc0 Merge pull request #382 from gdamjan/master
improve php build script
2013-09-16 05:17:39 -07:00
Damjan Georgievski ad4ee9d5c3 improve php build script
use UWSGICONFIG_PHPLIBDIR to specify the directory of the php library,
useful for Debian Wheezy which puts php5.so in /usr/lib/php5

small change: don't use exceptions for flow control
2013-09-16 12:49:14 +02:00
Unbit 03a4e900ea fixed #378 2013-09-16 11:50:37 +02:00
Unbit b52dbf2aa0 added forkptyrouter 2013-09-16 06:38:29 +02:00
Unbit c7a22c3b53 improved logpipe 2013-09-15 12:02:14 +02:00
unbit 775aae3f1e Merge pull request #380 from KLab/logpipe
Add pipe logger.
2013-09-15 03:09:53 -07:00
INADA Naoki 862731ba91 Add pipe logger. 2013-09-15 16:47:58 +09:00
Unbit 8c302eee51 start 1.9.17 now 2013-09-14 15:30:23 +02:00
Unbit b6d34067c4 support for multiple tuntap devices 2013-09-14 15:15:47 +02:00
Unbit dbe15195b7 support for multiple routers 2013-09-14 15:07:43 +02:00
Unbit 5642aa1eb5 should be enough for 1.9.16... 2013-09-14 14:40:16 +02:00
Unbit 5dd465ccc1 added internal counters to the tuntap router 2013-09-14 14:31:12 +02:00
Unbit ae78c3007e fixed tuntap firewall 2013-09-14 12:05:13 +02:00
Unbit 16211d9439 preliminary tuntap firewall implementation 2013-09-14 11:04:26 +02:00
unbit 515619fe2a Merge pull request #379 from prymitive/cheaper_mem_limit
allow setting cheaper rss memory limits
2013-09-14 01:25:14 -07:00
Unbit a7d550165d still refactoring tuntap 2013-09-14 10:03:41 +02:00
Unbit efceacd9e5 refactored tuntap plugin 2013-09-14 09:54:57 +02:00
Unbit ea5ebc2d15 added preliminary version of the tuntap plugin 2013-09-14 08:43:56 +02:00
Unbit fba82c203c minor improvements 2013-09-14 08:43:09 +02:00
Łukasz Mierzwa a50516af7a allow setting cheaper rss memory limits 2013-09-14 01:04:19 +02:00
Unbit 6056b51653 implemented priority in rsyslog 2013-09-13 06:17:34 +02:00
Unbit 23a3170c59 fixed a typo 2013-09-12 15:31:15 +02:00
Unbit e136128408 added compress and suffix log encoders 2013-09-11 14:04:26 +02:00
Unbit fce94e0f54 cleanup the rados plugin 2013-09-10 23:42:08 +02:00
unbit 06fa65bc5d Merge pull request #377 from javierguerragiraldez/master
new rados plugin
2013-09-11 06:49:04 -07:00
Javier Guerra 571ec5ca72 cleanup old (commented) flags inherited from glusterfs 2013-09-11 08:30:06 -05:00
Unbit 39bc0ecd46 OpenBSD has not strndup 2013-09-10 21:43:24 +02:00
Javier Guerra 7a5373360c strip mountpoint prefix, better check file not found error. 2013-09-10 12:30:59 -05:00
Javier Guerra 15453ffef6 compilation infrastructure 2013-09-10 12:30:59 -05:00
Javier Guerra a25747a096 use official modifier1 2013-09-10 12:30:59 -05:00
Javier Guerra bb1ef59b52 initial draft 2013-09-10 12:30:59 -05:00
Javier Guerra 6bb3af840d initial draft 2013-09-10 12:30:58 -05:00
Unbit 0223c74ecc added json log encoder 2013-09-10 19:24:50 +02:00
Unbit c7004d7ba4 added nl and format log encoders 2013-09-10 19:15:20 +02:00
Unbit 915d2e9192 Merge branch 'master' of github.com:unbit/uwsgi 2013-09-10 11:59:37 +02:00
Unbit df79b9367b report thunder lock status 2013-09-10 11:59:21 +02:00
Unbit ce3d026037 link with -lrt on solaris 2013-09-10 06:31:07 +02:00
Unbit d0f6c4130b fixed #376 2013-09-10 06:26:22 +02:00
Unbit 26bcf28182 improved gevent waiting for greenlets 2013-09-09 17:52:28 +02:00
unbit 272d1ccc03 improved mount/unmount support in freebsd 2013-09-08 18:39:31 +02:00
unbit 6c440af24e support for platform non defining MS_PRIVATE 2013-09-08 12:48:45 +02:00
unbit 8954520cb9 hardcode support for MS_REC 2013-09-08 12:47:07 +02:00
unbit 31bde74fab fixed msgpack on 32bit 2013-09-08 11:23:06 +02:00
Unbit 13c64a383c added response routes 2013-09-08 08:23:44 +02:00
Unbit 809028f11b added date/time support to msgpack encoder 2013-09-07 15:01:29 +02:00
Unbit dee9d2ba1e improved float/double support 2013-09-07 14:52:01 +02:00
Unbit 29d80ce061 added msgpack plugin, it misses int and float support 2013-09-07 13:06:10 +02:00
Unbit abcd3242d8 added log encoders 2013-09-07 10:40:40 +02:00
unbit f4762299f9 added callint/callret hooks 2013-09-06 12:28:04 +02:00
unbit 107f4309a4 first public implementation of the advanced hook subsystem 2013-09-06 11:57:23 +02:00
unbit d2a8df19ea prepare for advanced hooks 2013-09-06 11:03:02 +02:00
unbit 29efd15534 Merge pull request #374 from gdamjan/master
remount to private subtree after unshare
2013-09-06 00:00:03 -07:00
Damjan Georgievski e7fb216a8d remount to private subtree after unshare
systemd will makes the VFS tree 'shared' on boot, so mount
operations would propagate between the namespace and the
parent system.
make sure the whole VFS tree is private to the namespace.
2013-09-06 08:41:00 +02:00
unbit 952b96cdcb added --jail-attach 2013-09-04 14:20:02 +02:00
unbit 8ee82fc296 do not call pre-jail on reload 2013-09-04 12:28:22 +02:00
unbit afe2bfb856 improved support for FreeBSD jails 2013-09-04 11:36:45 +02:00
unbit 5b63e9aea0 added FreeBSD jail support 2013-09-04 00:30:39 +02:00
Unbit 91f70259e2 some garbage... 2013-09-03 20:24:04 +02:00
Unbit f120cacc03 added support for O_TMPFILE 2013-09-03 07:15:22 +02:00
Unbit aff1d782b8 Merge branch 'master' of github.com:unbit/uwsgi 2013-09-02 15:55:27 +02:00
Unbit b489fd8a24 added --disable-sendfile 2013-09-02 15:55:02 +02:00
unbit 47e0eb68c2 Merge pull request #373 from ivanjr0/master
Adding **kwargs to @harakiri
2013-09-02 05:26:57 -07:00
Ivan Júnior 9498e25245 Adding **kwargs to @harakiri
I can't see any reason why this decorator doesn't have `**kwargs`, so I add it.
2013-09-02 09:23:53 -03:00
Unbit a33e18b589 --pivot_root and --pivot-root 2013-09-02 10:39:15 +02:00
Unbit f2dcdf2289 added --pivot-root (linux only) 2013-09-02 10:38:40 +02:00
Unbit 74c53e8a61 added --drop-after-init and --drop-after-apps 2013-09-02 10:12:46 +02:00
Unbit 1feed87c10 improved request_id management in fastcgi parser 2013-08-31 12:25:10 +02:00
Unbit f89742d81a fixed fastcgi bug exposed by apache mod_fastcgi 2013-08-31 12:08:27 +02:00
Unbit 340b9d603e fixed --persistent-ipcsem 2013-08-31 11:22:39 +02:00
Unbit 1c0fc64243 better ipcsem support 2013-08-31 11:20:52 +02:00
Unbit 1d5173d923 better BUG reporting in smart-attach-daemon 2013-08-30 20:03:58 +02:00
Unbit 49a8bf0b9b report missing internal routing support 2013-08-30 14:58:15 +02:00
Unbit 0a7e5a41a2 added the Zeus mode analysis 2013-08-30 11:27:47 +02:00
Unbit 43ff563429 prepare for 1.9.16 2013-08-30 10:10:34 +02:00
Roberto De Ioris 2daf6f1f66 fixed #75 2013-08-30 08:07:50 +02:00
Unbit 985f56768f follow Rack specifications for QUERY_STRING,SCRIPT_NAME,SERVER_NAME and SERVER_PORT 2013-08-29 18:58:08 +02:00
Unbit 35278588f5 improved smart-attach-daemon 2013-08-29 17:40:32 +02:00
Unbit f6545be647 fixed reference counting bug in rpc and signal handlers 2013-08-29 14:45:08 +02:00
Unbit f387d27582 prepare for 1.9.15 2013-08-29 10:49:21 +02:00
Unbit 5d8e5d943f improved smartos support 2013-08-29 10:30:01 +00:00
Unbit 4046f76cb2 completed emperor hooks 2013-08-28 15:00:22 +02:00
Unbit 8baeb0af2f prepare for more emperor hooks 2013-08-28 13:25:52 +02:00
Unbit 63e0105a0f added interface waiting infrastructure 2013-08-28 12:43:26 +02:00
Unbit 70daa57caf Merge branch 'master' of github.com:unbit/uwsgi 2013-08-28 11:49:07 +02:00
Unbit db0f7951a9 added --exec-as-vassal and fixed 'fs' unshare 2013-08-28 11:48:51 +02:00
unbit 45a7a3066d Merge pull request #368 from Kapishin/master
Fix two typos in comments
2013-08-27 23:07:20 -07:00
Pavlo Kapyshin c73a6723d7 Fix two typos in comments 2013-08-28 08:57:58 +03:00
Unbit fb55f57531 added --emperor-use-clone 2013-08-27 21:47:00 +02:00
unbit 8cf4d5802a fixed FreeBSD support for pty plugin 2013-08-26 17:42:25 +02:00
Unbit e3c042e567 pty requires -lutil on linux 2013-08-26 15:44:31 +02:00
Unbit 5435f8927c added vassal's hooks 2013-08-26 10:13:08 +02:00
Unbit e1e65c46ac added --refork option 2013-08-26 10:05:41 +02:00
Unbit e1f3665a8e do not set sys,argv in pypy if already available 2013-08-26 05:38:19 +02:00
Unbit ef09a010cf allows pypy plugin to detect already available pypy environment 2013-08-26 05:01:28 +02:00
Unbit 3f5d79c755 added UWSGI_AS_LIB 2013-08-25 19:42:59 +02:00
unbit 3b5468f39f added FreeBSD support to pty plugin 2013-08-25 18:43:44 +02:00
Roberto De Ioris 5598c7cc22 added pty support to OpenBSD 2013-08-25 20:41:28 +02:00
Unbit d6fdb812a2 improved postfork() decorator 2013-08-25 18:35:56 +02:00
Unbit e6d5f6c612 fixed #366 2013-08-23 20:49:39 +02:00
Unbit 8f10daa2bf fixed pty binding 2013-08-23 19:16:38 +02:00
Unbit f027153452 exit on failed --pty-connect 2013-08-23 18:48:07 +02:00
Unbit 0ebda93a50 fixed #365 2013-08-23 18:41:10 +02:00
Unbit dc4e8950d2 sanitize pty options 2013-08-23 17:50:31 +02:00
Unbit 0f5336028f added OSX support for the pty plugin 2013-08-23 16:28:12 +02:00
Unbit e02341bffe include pty.h only on linux 2013-08-23 16:21:40 +02:00
Unbit ac92ff4079 added the pty plugin 2013-08-23 16:19:33 +02:00
Unbit a5da77bc54 added --add-gid 2013-08-23 14:46:06 +02:00
Unbit 0441e88b82 track unix sockets inode to reduce accidental removal on vacuum 2013-08-23 14:28:01 +02:00
Unbit 815f4abec0 fixed #364 2013-08-23 13:59:13 +02:00
Unbit 4f9e2ff3f6 added --perl-exec and --perl-exec-post-fork 2013-08-23 11:50:18 +02:00
Unbit ce8dd001bf ported uwsgi.cache_keys to pypy 2013-08-23 11:06:24 +02:00
Unbit d4e90f5215 added uwsgi.cache_keys function api 2013-08-23 10:43:13 +02:00
unbit da13562890 Merge pull request #362 from KLab/log-ftime
Add `%(ftime)` to logformat.
2013-08-20 00:58:20 -07:00
INADA Naoki d320075ab0 Add %(ftime) to logformat. 2013-08-20 16:45:59 +09:00
Unbit 4061826da4 try to fix python3 static files handling 2013-08-20 07:32:41 +02:00
Unbit 2854321891 improved python3 exceptions management 2013-08-16 07:09:50 +02:00
Unbit c4181cdc55 fixed type in pypy wsgi.input.read 2013-08-14 11:59:42 +02:00
Unbit 327582b695 added --worker-exec2 2013-08-14 10:16:39 +02:00
Unbit f56b9be4c5 allow post_fork hook on general plugins 2013-08-13 19:19:22 +02:00
Unbit 28ccace24f implemented --call hooks 2013-08-12 12:42:32 +02:00
Unbit 13f82176e3 added init_func support for plugins, and --need-plugin variant 2013-08-11 10:22:36 +02:00
Unbit be4d324f6b better symbol detection for pypy 2013-08-11 08:41:02 +02:00
Unbit 36486caabb sizeof on string includes NULL ... 2013-08-11 08:27:20 +02:00
Unbit b3af255727 Merge branch 'master' of github.com:unbit/uwsgi 2013-08-11 07:09:04 +02:00
Unbit a56f726f7d fixed a typo 2013-08-11 07:06:30 +02:00
unbit 24d6470f38 Merge pull request #359 from ryanpetrello/master
Add plugin support for the pecan WSGI framework (http://pecanpy.org).
2013-08-09 23:47:37 -07:00
Ryan Petrello 7e079e4c40 Add my name to the contributors list. 2013-08-10 01:00:12 -04:00
Ryan Petrello 0d9bc03c53 Add plugin support for the pecan WSGI framework (http://pecanpy.org). 2013-08-10 00:44:40 -04:00
Unbit 7598666768 added UWSGI_REMOVE_INCLUDES 2013-08-08 18:27:54 +02:00
Unbit cd6f027705 avoid unix nameclash on cygwin 2013-08-08 11:23:09 +02:00
Roberto De Ioris 0803a7f0b0 added router_expires 2013-08-07 08:14:38 +02:00
Roberto De Ioris 0eb956db4a example mv again 2013-08-06 07:39:20 +02:00
Roberto De Ioris 76c6ae6d16 mv again 2013-08-06 07:38:11 +02:00
Roberto De Ioris 40054e3494 another series of mv 2013-08-06 07:36:16 +02:00
Roberto De Ioris 8927dfd538 moved example files 2013-08-06 07:33:40 +02:00
Roberto De Ioris 68f734fcad announce legion's death on reload 2013-08-06 07:15:35 +02:00
Roberto De Ioris af4c7f74d5 fixed legion death 2013-08-06 07:08:42 +02:00
Roberto De Ioris 4581d1e7ce announce legion death on uwsgi exit 2013-08-06 06:58:04 +02:00
Unbit d465f61506 fix volfile report 2013-07-31 10:14:22 +02:00
Unbit 5cae9b9ba4 fixed glusterfs volfile support 2013-07-31 10:05:49 +02:00
unbit 428a2d9366 Merge pull request #350 from prymitive/matheval_fix
fix matheval check in build profiles
2013-07-30 19:52:39 -07:00
unbit 1c00b54b06 Merge pull request #351 from prymitive/dot_h
handle core/dot_h.c as other build objects
2013-07-30 08:57:39 -07:00
Unbit 6228fb91da preliminary async support for glusterfs 2013-07-30 16:42:56 +02:00
Łukasz Mierzwa 307cf3a0ef add autogenerated core/dot_h.c to .gitignore, so it won't be added by mistake to git, also remove it during make clean 2013-07-30 10:54:33 +02:00
Łukasz Mierzwa f723a804c0 fix matheval check in build profiles, currently matheval is always required while it should be only used if present or if requested by user 2013-07-30 10:27:02 +02:00
Unbit 24ac19e2d6 added last-modified to glusterfs 2013-07-29 17:40:06 +02:00
Unbit 38147d50ff check for matheval 2013-07-29 16:55:28 +02:00
Unbit 9f7db10582 first working glusterfs plugin prototype 2013-07-29 16:50:00 +02:00
Unbit ed35a50e6c rewrite ruby libdir on heroku 2013-07-29 08:49:25 +02:00
Unbit fae08f49cf another heroku workaround 2013-07-29 08:45:33 +02:00
Unbit 35f5b5b2eb improved ruby libdir detection for static builds 2013-07-29 08:25:06 +02:00
Unbit b785c8fccf added a check for ruby --enable-load-relative 2013-07-28 08:50:44 +02:00
Unbit 597c3cd7f1 try removing ruby_sysinit 2013-07-28 06:23:39 +02:00
Unbit bbbe01ef4b change ruby_process_options with ruby_options [5] 2013-07-27 23:49:49 +02:00
Unbit ea1e1cb65f change ruby_process_options with ruby_options [4] 2013-07-27 23:42:05 +02:00
Unbit a1d31ae954 change ruby_process_options with ruby_options [3] 2013-07-27 23:19:15 +02:00
Unbit fa0ed9489a change ruby_process_options with ruby_options [2] 2013-07-27 23:13:37 +02:00
Unbit 7bb7b351e0 change ruby_process_options with ruby_options 2013-07-27 23:01:09 +02:00
Unbit cb45f207a6 another attempt to make heroku happy [6] 2013-07-27 22:46:31 +02:00
Unbit 82ffb60bdd another attempt to make heroku happy [5] 2013-07-27 22:42:16 +02:00
Unbit ec38ce9a26 another attempt to make heroku happy [4] 2013-07-27 22:37:43 +02:00
Unbit 8279926bab another attempt to make heroku happy [3] 2013-07-27 22:18:18 +02:00
Unbit ac17b0910e another attempt to make heroku happy [2] 2013-07-27 22:09:29 +02:00
Unbit aae3e7ff17 another attempt to make heroku happy 2013-07-27 22:04:02 +02:00
Unbit 4cfff98cd1 try to workaround heroku 2013-07-27 22:01:21 +02:00
Unbit 19ee50949c skeleton for glusterfs plugin 2013-07-27 21:48:00 +02:00
Unbit ec27d624c3 fixed http-keepalive memleak 2013-07-26 12:17:23 +02:00
Unbit 0dc8803ff8 added --force-gateway 2013-07-26 12:03:38 +02:00
Unbit e8ea1a55f9 fixed #112 2013-07-25 21:56:29 +02:00
Unbit a0cb71ca78 added --strict mode 2013-07-25 21:24:04 +02:00
Unbit 5c5aef3827 1.9.15 development starts 2013-07-23 11:00:18 +02:00
Unbit 737a7f4d51 attempt to fix spooler's body in python 2013-07-23 08:40:11 +02:00
Unbit c3ee774d56 Merge branch 'master' of github.com:unbit/uwsgi 2013-07-23 06:28:29 +02:00
Unbit 2d5adacc65 preliminary python profiler for python3 2013-07-23 06:28:10 +02:00
unbit b7a8cc0297 Merge pull request #345 from pingswept/patch-1
Convert tabs to spaces to fix indentation error
2013-07-22 12:36:44 -07:00
Brandon Stafford 317b0f79a8 Convert tabs to spaces to fix indentation error
The uwsgi.websocket_handshake call on line 52 was not indented properly, causing the Python interpreter to choke. Converting the few tabs sprinkled through the document to spaces fixes that error.
2013-07-22 15:22:44 -04:00
Unbit 4644578276 file monitor support for OpenBSD,NetBSD,DragonFly 2013-07-21 16:38:48 +02:00
Unbit f1d450c12f updated gemspec 2013-07-21 08:08:48 +02:00
Roberto De Ioris 6624f75ec7 added kqueue support to the fsmon interface 2013-07-21 07:40:47 +02:00
Unbit 8941505ea0 inotify-based fsmon implementation 2013-07-21 07:34:56 +02:00
Unbit 18b177db25 added fsmon skel 2013-07-20 00:07:40 +02:00
Unbit 27421f3642 atexit hook is not needed in the xmldir router 2013-07-19 19:27:22 +02:00
unbit 30f9479e85 Merge pull request #343 from gber/master
Improvements to router_xmldir
2013-07-20 08:40:39 -07:00
Guido Berhoerster a9f7631ab4 Add example configuration and XSL stylesheet 2013-07-20 00:35:11 +02:00
Guido Berhoerster cb8519510f Fix style in router_xmldir 2013-07-20 00:35:11 +02:00
Guido Berhoerster f7881bfb78 Improve router_xmldir output
Root element is now <index> instead of <tree> since the output is not a tree.
Add a path attribute to <index> which contains the content of PATH_INFO.
Only show files and directories and add attributes for their mtime and size.
2013-07-20 00:35:11 +02:00
Guido Berhoerster 4cf4c75d5d Convert filenames from codeset of the current locale to UTF-8 encoding 2013-07-20 00:35:11 +02:00
Guido Berhoerster 91bcbc77b3 Include hidden files in router_xmldir directory listing
Hidden files can be filtered out through a XSL stylesheet if needed.
2013-07-20 00:35:11 +02:00
Guido Berhoerster b1db4d35c3 Return meaningful responses from router_xmldir in case of errors 2013-07-20 00:35:11 +02:00
Guido Berhoerster 060462b849 Fix portability issue in the router_xmldir plugin
Use the portable alphasort(3) insead of the versionsort(3) GNU extension.
2013-07-20 00:35:11 +02:00
Unbit 0e08c0211c Unbit-specific workaround for broken robust mutexes 2013-07-19 13:21:34 +02:00
Unbit e69cc2bcd5 fixed python modifier management 2013-07-18 16:43:37 +02:00
Unbit 996af7d46c fixed hex2num 2013-07-17 20:42:14 +02:00
Unbit e8e66f15da fixed check_hex 2013-07-17 20:41:07 +02:00
Unbit cd09b4a55d more user-friendly error message for undeletable unix sockets 2013-07-17 16:30:25 +02:00
Unbit f4a1d76396 try to fix auto chunking in http router 2013-07-17 16:21:13 +02:00
Unbit ab8cc168e5 fixed #339 2013-07-17 08:38:32 +02:00
Unbit 5e43ef6fae rbthreads improvements 2013-07-17 08:36:49 +02:00
Roberto De Ioris caa3614f78 rbthreads osx fixes 2013-07-17 07:22:58 +02:00
Unbit a81ca89ae9 use ruby2 profile when available 2013-07-17 07:14:45 +02:00
Unbit 5861705cd6 preliminary rbthreads support 2013-07-17 07:08:47 +02:00
Unbit 4e68dacad3 microoptimzation for --reload-on-fd 2013-07-16 10:22:06 +02:00
Unbit 4f8f15a3b6 fixed --safe-fd 2013-07-16 09:12:46 +02:00
Unbit aa6b86fbdf force the emperor to honour --safe-fd 2013-07-16 08:50:51 +02:00
Unbit 7a18ff48ba added --reload-on-fd and --brutal-reload-on-fd 2013-07-16 08:27:56 +02:00
Unbit e354de9f5e fixed sendfile and fastfile headers management 2013-07-15 10:49:28 +02:00
Unbit 10073bc4ae jsp prototype working 2013-07-15 10:06:33 +02:00
Unbit 6fd051b248 more servlet definitions 2013-07-15 07:20:43 +02:00
Unbit 1cf034881e more servlet definitions 2013-07-15 07:20:08 +02:00
Unbit 1393281c74 added prototype servlet plugin 2013-07-14 09:15:12 +02:00
Unbit edf95a4b0a added fastfile routing action 2013-07-13 17:37:26 +02:00
Unbit 8887f83f7f use the right sendfile abstraction 2013-07-13 17:26:43 +02:00
Unbit 7513d80440 added sendfile routing action 2013-07-13 17:21:13 +02:00
Unbit 67289b7cf1 added setdocroot 2013-07-13 11:26:24 +02:00
Unbit a88f478fac support for rb_reserved_fd_p 2013-07-13 05:55:40 +02:00
Roberto De Ioris d385661a93 removed typo on osx 2013-07-12 20:06:48 +02:00
Unbit e8895ba773 better thunder_lock usage on unbit 2013-07-11 09:39:30 +02:00
Unbit 5a23a8d457 better computation of listen queue load 2013-07-11 08:45:46 +02:00
Roberto De Ioris e01a3d8bd2 second attempt of Tiger support 2013-07-10 21:34:28 +02:00
Roberto De Ioris b270bd24d7 first attempt of Tiger support 2013-07-10 21:30:36 +02:00
unbit ab989ebf16 Merge pull request #336 from xrmx/debian-fixes
A couple of patches from debian packaging
2013-07-09 08:34:31 -07:00
Riccardo Magliocchetti 7c31b6657f uwsgiconfig: force no-format-security too
It may happen that a plugin is using -Wformat -Wformat-security so need to remove
both otherwise as seen in emperor_pg plugin:

 cc1: error: -Wformat-security ignored without -Wformat [-Werror=format-security]

Based on a debian patch of Janos Guljas.
2013-07-09 09:58:35 +02:00
Riccardo Magliocchetti ba7d322aaf plugins: try harder to compile alarm_speech on linux
Using GNUStep. Modified from a debian patch of Janos Guljas.
2013-07-09 09:57:15 +02:00
Unbit 537187b7f8 added daemontools envdir support 2013-07-08 19:15:22 +02:00
Unbit d22a7c7223 added UWSGI_DEBUG_BUFFER to catch bugs related to uwsgi_buffer structures 2013-07-08 17:59:56 +02:00
Unbit c9f986fa59 improved v8 build 2013-07-08 13:27:02 +02:00
Unbit d7388ca5e7 fixed pypy rpc 2013-07-08 11:34:09 +02:00
Unbit df5ad62ebf improved http proxy internal router 2013-07-08 10:50:03 +02:00
Unbit 41dab14020 improved chunked api 2013-07-07 10:14:06 +02:00
Unbit 744e166e9d Revert "uwsgi.is_locked raises an exception"
This reverts commit 5a3b93f763.
2013-07-03 15:41:57 +02:00
Unbit 5a3b93f763 uwsgi.is_locked raises an exception 2013-07-03 14:53:55 +02:00
Unbit 656de924eb fixed latin1 encoding with python3 2013-07-02 16:19:12 +02:00
Unbit 703444dd40 added v8 build profile 2013-07-01 17:21:51 +02:00
Roberto De Ioris ff8ca18e8f added --emperor-nofollow 2013-06-29 21:57:10 +02:00
unbit 1f90be1ae1 Merge pull request #328 from anaconda/py-spooler-pass-args
[Python] Added option to pass arguments to spooled function
2013-06-29 03:50:29 -07:00
unbit ee95c2eb0b Merge pull request #329 from anaconda/master
Adding my name to CONTRIBUTORS, as requested in #327.
2013-06-29 03:48:36 -07:00
anaconda 6606f3f0dc Implement pass_arguments parameter for spool* decorators.
Let's say you have a heavily used function or method.  Until now you
had to:
a) change all calls, the spooler dictionary only accepted strings;
b) change the code of your function to read its parameters from a
dictionary and convert them from str.

From now on you just need to add `@spool[forever](pass_arguments=True)` to your
function.
2013-06-25 23:54:07 +02:00
anaconda bcd97f7247 Adding my name to CONTRIBUTORS, as requested in #327. 2013-06-25 23:38:46 +02:00
unbit 271e7f8f4c Merge pull request #327 from anaconda/fix-spooler-ordered
Fix --spooler-ordered, was actually reverse ordered.
2013-06-25 09:31:23 -07:00
Unbit e78d8594a8 avoid mess on 32bit 2013-06-25 18:28:30 +02:00
Unbit 659360b366 fixed php status line 2013-06-25 18:23:33 +02:00
anaconda 6c1c86ea79 --spooler-ordered was actually reverse ordered. 2013-06-25 16:58:22 +02:00
Unbit 5da36b7199 1.9.14 development cycle starts 2013-06-25 11:52:34 +02:00
Unbit 294452eef7 added support for retry in http router 2013-06-25 07:56:01 +02:00
Unbit 3ac0e28d9c added Natanael Copa to CONTRIBUTORS 2013-06-24 16:59:58 +02:00
Unbit ce22b69a2f completed uclibc support 2013-06-24 14:55:59 +00:00
unbit 8b31a998ed Merge pull request #325 from ncopa/master
Support for Lua 5.2
2013-06-24 07:44:24 -07:00
Natanael Copa dad97bc104 add support for lua5.2
The default is still lua5.1 but 5.2 can be picked at compile time
but setting UWSGICONFIG_LUAPC=lua5.2
2013-06-24 14:35:31 +00:00
Natanael Copa e20e43eee0 add support for pkg-config for lua
Allow select what pkg-config module to use with UWSGICONFIG_LUAPC but
let the old LUAINC/LUALIB and LUALIBPATH override the pkg-config
for backwards compatibility.
2013-06-24 14:35:31 +00:00
Unbit aafd4e757d another uclibc fix 2013-06-24 16:15:17 +02:00
Unbit 575fc26bd7 try to support uclibc correctly 2013-06-24 16:01:43 +02:00
Unbit 5743eb2575 refactored lua build 2013-06-24 15:05:34 +02:00
Unbit 31972ded93 moved opt login in core/config.c 2013-06-23 08:18:33 +02:00
Unbit 28321a0f94 more python api static functions 2013-06-23 07:59:36 +02:00
Unbit 406dfbc770 added setscheme routing action 2013-06-23 07:22:09 +02:00
Unbit c59595cefc updated gemspec 2013-06-22 12:10:40 +02:00
Unbit 7108ee1ba0 improved xclient 2013-06-22 11:50:45 +02:00
Unbit cf8e68f7a0 another attempt to fix xclient 2013-06-22 11:18:25 +02:00
Unbit a9510c2209 fixed xclient 2013-06-22 10:51:17 +02:00
Unbit b2be5943a8 added router_xmldir plugin 2013-06-21 06:54:05 +02:00
Unbit 8f19fe292e added --add-cache-item 2013-06-20 15:12:48 +02:00
Unbit d3e7668d0a better clang detection 2013-06-20 11:00:05 +02:00
Unbit 88e67a74e5 fixed #321 2013-06-20 08:59:18 +02:00
Roberta Giordano 7fecda1a23 fixed #324 2013-06-20 06:15:35 +02:00
unbit 56b6fa88f9 Merge pull request #323 from jbert/master
Fix infinite loop in psgi/coroae
2013-06-19 07:47:52 -07:00
John Berthels e847cfe4bc fix infinite loop in coroae/psgi
Perl PSGI app infinite loops since f20213ff10

Looking at that change, other loop termination conditions are '<= UWSGI_OK'.
Using gdb to inspect the app while looping shows thats ->request is returning
UWSGI_OK in this case. However, the numeric value of this is zero, so we
never exit the for(;;) loop.

Cargo culting loop escape conditions from core/async.c (or gevent/gevent.c)
fixes the inf loop for psgi/coroae.
2013-06-19 15:27:31 +01:00
Roberta Giordano 1a854ae3ba varios osx build workaround 2013-06-19 07:14:54 +02:00
unbit c75180bf95 Create logo_uWSGI.svg 2013-06-17 10:26:59 +02:00
Unbit d496450b84 added seturi and setpathinfo routing actions 2013-06-16 07:52:59 +02:00
Unbit d2636ed133 better compiler detection 2013-06-16 07:13:19 +02:00
unbit 59de0c2085 Merge pull request #317 from anaconda/fix-gcc-darwin-llvm
Fix GCC on Darwin for Python 3.
2013-06-15 22:11:11 -07:00
anaconda 4b7df29bd1 Fix GCC on Darwin for Python 3.
distutils.sysconfig.get_config_var('CC') returns the compiler used to
build Python, which may be not installed on the system where uWSGI is
being built.

In my case, I grabbed Python 3.3.2 from python.org: it was apparently
compiled with 'gcc-4.2', but my system only has 'gcc' (symlink) and
'llvm-gcc-4.2'.  This change tries to detect this situation (only on
Darwin) and sets GCC to 'llvm-' + compiler returned by sysconfig.
2013-06-16 01:59:48 +02:00
unbit b099ba6a29 Merge pull request #316 from anaconda/spool-decorator-call
Implement __call__ for @spool* decorators.
2013-06-15 07:09:51 -07:00
anaconda 164069e194 Implement __call__ for @spool* decorators.
Also removed duplicate code.
2013-06-15 15:05:39 +02:00
Unbit b3e4ff8613 cosmetic fix for fastcgi 2013-06-15 14:37:50 +02:00
Unbit 3eb5ec3543 better fastcgi handling 2013-06-15 14:36:18 +02:00
unbit c3c698a615 Update uwsgi.conf 2013-06-15 15:09:22 +03:00
Unbit ac6d2f3e83 rack api functions are now static 2013-06-15 11:55:48 +02:00
Unbit d1f1b8a43a another tests cleanup 2013-06-15 08:03:34 +02:00
Unbit 85586a621c the official API list is now in uwsgi-docs 2013-06-15 08:01:53 +02:00
Unbit 1a384a334f remove mercurial files 2013-06-15 08:00:16 +02:00
Unbit 8901afded5 moved lanunchd examples to contrib 2013-06-15 07:59:27 +02:00
Roberta Giordano ab12703a11 added new set_user_harakiri to python,pypy,perl and ruby 2013-06-15 07:04:53 +02:00
Roberta Giordano 9992b4c964 improved set_user_harakiri to support mules and spoolers 2013-06-15 06:50:10 +02:00
unbit 9a2dbd08cd Merge pull request #315 from prymitive/curl_bug
fix curl crashing master on slow dns responses
2013-06-14 06:48:03 -07:00
Łukasz Mierzwa 5f92a00b71 fix curl crashing master on slow dns responses 2013-06-14 09:24:00 +02:00
Unbit 7bd9d51217 added mule support to pypy 2013-06-12 16:39:10 +02:00
unbit 80c649aa40 Create emperor.conf 2013-06-11 13:47:34 +03:00
Unbit 6c8fe2cc53 improved ready_fd call 2013-06-10 23:01:19 +02:00
Unbit dcc7167d75 added uwsgi[lq] routing var 2013-06-10 02:48:52 +02:00
Unbit e3a52e4039 added --use-abort 2013-06-09 23:14:52 +02:00
Unbit 498f6162f7 fixed debug 2013-06-09 23:00:22 +02:00
Unbit 33d85d3670 added coroae build profile 2013-06-09 22:58:18 +02:00
Unbit afbf5b9633 fixed typo doc 2013-06-09 22:54:42 +02:00
Unbit a8505be6c0 standardized uwsgi.disconnect() 2013-06-09 22:47:44 +02:00
Unbit 4a07632569 uwsgi.add_cron does not return a value 2013-06-09 22:35:52 +02:00
Unbit d4f0589c39 fixed uwsgi.fd_ready() 2013-06-09 22:22:59 +02:00
Roberta Giordano a9989d46fc set default lock to 0 in pypy uwsgi.lock/uwsgi.unlock 2013-06-10 06:08:15 +02:00
Unbit 99cf598c0c added chunked input support to pypy 2013-06-09 08:47:50 +02:00
Unbit a6af22b8f0 ported websockets api to pypy 2013-06-09 08:35:12 +02:00
Unbit 0961d61a88 added chunked async support 2013-06-09 08:06:45 +02:00
Unbit 7b76a2d749 first test for chunked input 2013-06-09 03:25:46 +02:00
Unbit b516f1d3ec added --chunked-input-limit and --chunked-input-timeout 2013-06-09 03:06:12 +02:00
Unbit 8fdef7a1f9 added chunked input api 2013-06-09 03:02:16 +02:00
Unbit 10258db4ae removed python 3 need for 'imp' module 2013-06-08 23:36:49 +02:00
unbit 621c9523cf fixed python3 compilation and added UWSGI_INCLUDES 2013-06-09 07:01:34 +02:00
Unbit c415adab28 added setmethod routing action 2013-06-08 01:05:44 +02:00
Unbit 7fef1048b3 added pypy greenlet contrib module 2013-06-07 10:15:25 +02:00
Unbit 1e7aaeeeed fix harakiri routing 2013-06-07 09:11:54 +02:00
Unbit c5b4564001 added 2 example of continulets 2013-06-06 18:16:01 +02:00
Unbit a9127c8d79 added support for pypy uwsgi.async_sleep 2013-06-06 17:25:03 +02:00
Unbit a0f7a5c70f added support for pypy continulets 2013-06-06 17:17:51 +02:00
Unbit ecf3cae35b use ffi.string instead of ffi.buffer in pypy 2013-06-06 16:05:20 +02:00
Unbit d553bc8014 let's start with 1.9.13 2013-06-06 15:49:51 +02:00
Unbit a1553d3632 removed debug print from pypy_setup.py 2013-06-06 14:54:39 +02:00
Unbit bb42ae1b4a fixed cron and alarm in pypy_setup.py 2013-06-06 14:16:38 +02:00
Unbit 61ac2efe0e added user_lock/unlock to new pypy setup 2013-06-06 14:15:02 +02:00
Unbit 1c0a3ec413 refactored the pypy plugin to make best use of cffi and to avoid the need of helpers 2013-06-06 14:10:34 +02:00
Unbit 8b7e93385b missing newline in --cflags 2013-06-06 11:27:14 +02:00
Unbit c742624054 added uwsgi_get_cflags() 2013-06-06 11:25:17 +02:00
Unbit 8011f0615d added --dot-h infrastructure 2013-06-06 11:18:25 +02:00
Unbit 8096b2198f fixed --print-sym and embed uwsgi.h in the server binary 2013-06-06 10:06:40 +02:00
Unbit 3556bd5283 removed PTRACE check, was an old stupid attempt 2013-06-06 09:42:08 +02:00
Unbit 26710694af fixed #306 2013-06-05 15:19:21 +02:00
Unbit 0f397eeb55 fixed #305 2013-06-05 11:14:47 +02:00
Unbit bf929398a9 updated gemspec for 1.9.12 2013-06-05 09:19:57 +02:00
Unbit 4f8a0f753e added router_hash and extended support for memcached and redis 2013-06-05 06:26:39 +02:00
Unbit 7db5da9566 fixed support for newer cygwin 2013-06-04 17:13:18 +02:00
Unbit 4d1389805c added redis router code 2013-06-04 13:20:47 +02:00
Unbit ee87e2b946 memcached and redis routers are now builtin by default 2013-06-04 13:07:51 +02:00
Unbit 6356d78768 completed memcachedstore 2013-06-04 12:04:42 +02:00
Unbit afdf7e740e prepare for memcachedstore 2013-06-04 11:40:19 +02:00
Unbit 51ce3ddf78 added offloading to memcached internal router 2013-06-04 11:18:02 +02:00
Unbit 192186056e added pipe offload engine 2013-06-04 10:34:19 +02:00
Unbit 336a7febd7 prepate for 1.9.12 2013-06-03 15:35:17 +02:00
Unbit 63e73d1b73 added --touch-signal 2013-06-03 11:15:39 +02:00
Unbit a02ab9a723 automatically search for 'application' method in jwsgi 2013-06-03 06:33:48 +02:00
Unbit 95f15ab9dd added a note for python logger 2013-06-02 19:20:35 +02:00
Unbit 5d0ea0066a fixed fastcgi body read 2013-06-02 12:52:13 +02:00
Unbit 9ff6b2da9b improved tmp file generation and first implementation of offload transformation 2013-06-02 11:12:28 +02:00
Roberta Giordano 6ac7e27847 added seek() support to jvm input 2013-06-01 19:53:29 +02:00
Roberta Giordano 4ed1c5e747 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-06-01 19:42:29 +02:00
Roberta Giordano bae3bc096f added readLine featute to jvm input 2013-06-01 19:42:11 +02:00
unbit 9d73683de2 Merge pull request #298 from prymitive/csfix
try to escape json
2013-06-01 08:15:19 -07:00
Roberta Giordano f5fec0ab71 added support for jvm list and uwsgi.opt 2013-06-01 16:32:39 +02:00
Łukasz Mierzwa 9909ab10c4 try to escape json 2013-06-01 15:53:35 +02:00
Roberta Giordano 65cff01fee implemented non-static JWSGI apps 2013-06-01 12:20:19 +02:00
unbit 10190a3012 Merge pull request #301 from jimfunk/master
Fix signed/unsigned comparison in emperor_amqp plugin
2013-05-31 21:56:23 -07:00
James Oakley 79ab696f4e Fix signed/unsigned comparison 2013-05-31 13:24:49 -07:00
Łukasz Mierzwa edbff83fd6 zero pids after worker killed due to --idle usage 2013-04-08 10:32:39 +02:00
252 changed files with 17981 additions and 3288 deletions
+2
View File
@@ -9,3 +9,5 @@
/uwsgibuild.*
/t/ring/target
core/dot_h.c
-4
View File
@@ -1,4 +0,0 @@
syntax: glob
*.o
*.pyc
-58
View File
@@ -1,58 +0,0 @@
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
3c70927335856883283fe4db448e092cecc0ccdb 1.0
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
620e0cb6ccdb0ce27561b4240cb3a0ef4c3527fd 1.3
+3
View File
@@ -22,3 +22,6 @@ Aarni Koskela
C Anthony Risinger
Stephen Pierce
Mingli Yuan
Natanael Copa
Roberto Leandrini
Ryan Petrello
+16
View File
@@ -1,3 +1,19 @@
----------------------------------------------------------------------
LINKING EXCEPTION
In addition to the permissions in the GNU General Public License,
the authors give you unlimited permission to link the compiled
version of this library into combinations with other programs,
and to distribute those combinations without any restriction
coming from the use of this file. (The General Public License
restrictions do apply in other respects; for example, they cover
modification of the file, and distribution when not linked into
a combined executable.)
----------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
+5 -3
View File
@@ -1,8 +1,10 @@
PYTHON := python
all:
python uwsgiconfig.py --build
$(PYTHON) uwsgiconfig.py --build $(PROFILE)
clean:
python uwsgiconfig.py --clean
$(PYTHON) uwsgiconfig.py --clean
check:
python uwsgiconfig.py --check
$(PYTHON) uwsgiconfig.py --check
+2 -2
View File
@@ -7,7 +7,7 @@ filename = sys.argv[1]
size = os.path.getsize(filename)
f = open(filename, 'r')
print(f.read())
os.write(1, f.read())
f.close()
print(struct.pack("<Q", size))
os.write(1, (struct.pack("<Q", size)))
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados
inherit = base
+2 -1
View File
@@ -6,6 +6,7 @@ zeromq = auto
ssl = auto
pcre = auto
routing = auto
matheval = auto
debug = false
unbit = false
xml_implementation = libxml2
@@ -16,7 +17,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, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked
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, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires, router_metrics, transformation_template, stats_pusher_socket
as_shared_library = false
locking = auto
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = psgi,coroae
inherit = base
+2 -2
View File
@@ -1,4 +1,4 @@
[uwsgi]
# pypy,jvm,ring,jwsgi
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
# pypy,go
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,pyerl,glusterfs,pty,xslt,msgpack,geoip,v8,pam,ldap,mono,jvm,ring,jwsgi
inherit = base
+1
View File
@@ -1,3 +1,4 @@
[uwsgi]
main_plugin = python,gevent
inherit = base
debug = false
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
main_plugin = glusterfs
inherit = base
matheval = false
+33
View File
@@ -0,0 +1,33 @@
[uwsgi]
xml = false
yaml = false
json = false
zeromq = false
ssl = false
pcre = false
routing = false
matheval = false
debug = false
unbit = false
xml_implementation = none
yaml_implementation = none
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = psgi
inherit = minimal
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = python
inherit = minimal
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = pypy
inherit = minimal
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = rados
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = rack
inherit = minimal
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = rack,rbthreads,fiber
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = jvm,servlet
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = v8
inherit = base
+61
View File
@@ -0,0 +1,61 @@
"""
Greenlets support
simply --pypy-exec this file to enable PyPy's greenlet mode
Example:
uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi werkzeug.testapp:test_app --pypy-exec contrib/pypy/uwsgi_pypy_greenlets.py --async 8
"""
import greenlet
uwsgi_pypy_greenlets = {}
def uwsgi_pypy_greenlet_wrapper():
lib.async_schedule_to_req_green()
@ffi.callback("void()")
def uwsgi_pypy_greenlet_schedule():
id = lib.uwsgi.wsgi_req.async_id
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
# generate a new greenlet
if not lib.uwsgi.wsgi_req.suspended:
uwsgi_pypy_greenlets[id] = greenlet.greenlet(uwsgi_pypy_greenlet_wrapper)
lib.uwsgi.wsgi_req.suspended = 1
# this is called in the main stack
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
# let's switch
uwsgi_pypy_greenlets[id].switch()
# back to the main stack
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(ffi.NULL)
@ffi.callback("void(struct wsgi_request *)")
def uwsgi_pypy_greenlet_switch(wsgi_req):
id = wsgi_req.async_id
modifier1 = wsgi_req.uh.modifier1;
# this is called in the current greenlet
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(wsgi_req)
uwsgi_pypy_main_greenlet.switch()
# back to the greenlet
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(wsgi_req)
# update current running greenlet
lib.uwsgi.wsgi_req = wsgi_req
if lib.uwsgi.async <= 1:
raise Exception("pypy greenlets require async mode !!!")
lib.uwsgi.schedule_to_main = uwsgi_pypy_greenlet_switch
lib.uwsgi.schedule_to_req = uwsgi_pypy_greenlet_schedule
uwsgi_pypy_main_greenlet = greenlet.getcurrent()
View File
+15
View File
@@ -0,0 +1,15 @@
# uWSGI - Emperor
#
description "uWSGI Emperor"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
env VASSALS=/etc/uwsgi
exec $BINPATH --emperor $VASSALS --logto $LOGTO
+2 -3
View File
@@ -11,7 +11,6 @@ respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --no-orphans avoid workers without master
# --die-on-term could be a good idea
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
# --die-on-term is upstart friendly
exec $BINPATH --die-on-term --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
+2 -3
View File
@@ -184,8 +184,8 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
// map instances to the log
char *list = uwsgi_str(alarms);
char *p = strtok(list, ",");
while (p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(list, ",", p, ctx) {
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
if (!uai) {
free(list);
@@ -205,7 +205,6 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
else {
ual->alarms = uall;
}
p = strtok(NULL, ",");
}
free(list);
return 0;
+32 -18
View File
@@ -206,7 +206,11 @@ int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
}
static int async_wait_fd_read(int fd, int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_read(wsgi_req, fd, timeout)) {
return -1;
}
@@ -222,6 +226,8 @@ static int async_wait_fd_read(int fd, int timeout) {
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
wsgi_req->async_ready_fd = 0;
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);
}
@@ -265,6 +271,9 @@ int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
static int async_wait_fd_write(int fd, int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_write(wsgi_req, fd, timeout)) {
return -1;
}
@@ -299,29 +308,42 @@ end:
async_reset_request(uwsgi.wsgi_req);
uwsgi_close_request(uwsgi.wsgi_req);
uwsgi.wsgi_req->async_status = UWSGI_OK;
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
void async_schedule_to_req_green(void) {
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
goto end;
}
#endif
for(;;) {
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
break;
}
uwsgi.wsgi_req->switches++;
wsgi_req->switches++;
if (uwsgi.schedule_fix) {
uwsgi.schedule_fix(wsgi_req);
}
// switch after each yield
uwsgi.schedule_to_main(uwsgi.wsgi_req);
uwsgi.schedule_to_main(wsgi_req);
}
#ifdef UWSGI_ROUTING
end:
#endif
async_reset_request(uwsgi.wsgi_req);
uwsgi_close_request(uwsgi.wsgi_req);
uwsgi.wsgi_req->async_status = UWSGI_OK;
// re-set the global state
uwsgi.wsgi_req = wsgi_req;
async_reset_request(wsgi_req);
uwsgi_close_request(wsgi_req);
// re-set the global state (routing could have changed it)
uwsgi.wsgi_req = wsgi_req;
wsgi_req->async_status = UWSGI_OK;
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req;
}
void async_loop() {
@@ -359,7 +381,7 @@ void async_loop() {
uwsgi.schedule_to_req = async_schedule_to_req;
if (!uwsgi.schedule_to_main) {
uwsgi_log("*** WARNING *** async mode without coroutine/greenthread engine loaded !!!\n");
uwsgi_log("*** DANGER *** async mode without coroutine/greenthread engine loaded !!!\n");
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
@@ -502,19 +524,11 @@ void async_loop() {
uwsgi.wsgi_req->switches++;
// request ended ?
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
if (uwsgi.wsgi_req->async_status <= UWSGI_OK ||
uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove from the runqueue
runqueue_remove(current_request);
// push wsgi_request in the unused stack
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from the runqueue
runqueue_remove(current_request);
}
current_request = next_request;
}
+47
View File
@@ -3,6 +3,9 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_buffer *uwsgi_buffer_new(size_t len) {
#ifdef UWSGI_DEBUG_BUFFER
uwsgi_log("[uwsgi-buffer] allocating a new buffer of %llu\n", (unsigned long long) len);
#endif
struct uwsgi_buffer *ub = uwsgi_calloc(sizeof(struct uwsgi_buffer));
if (len) {
@@ -169,6 +172,16 @@ int uwsgi_buffer_u32be(struct uwsgi_buffer *ub, uint32_t num) {
return uwsgi_buffer_append(ub, (char *) buf, 4);
}
int uwsgi_buffer_f32be(struct uwsgi_buffer *ub, float num) {
uint8_t buf[4];
uint32_t *pnum = (uint32_t *) &num;
buf[3] = (uint8_t) (*pnum & 0xff);
buf[2] = (uint8_t) ((*pnum >> 8) & 0xff);
buf[1] = (uint8_t) ((*pnum >> 16) & 0xff);
buf[0] = (uint8_t) ((*pnum >> 24) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 4);
}
int uwsgi_buffer_u32le(struct uwsgi_buffer *ub, uint32_t num) {
uint8_t buf[4];
buf[0] = (uint8_t) (num & 0xff);
@@ -191,6 +204,33 @@ int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
return uwsgi_buffer_append(ub, (char *) buf, 8);
}
int uwsgi_buffer_u64le(struct uwsgi_buffer *ub, uint64_t num) {
uint8_t buf[8];
buf[0] = (uint8_t) (num & 0xff);
buf[1] = (uint8_t) ((num >> 8) & 0xff);
buf[2] = (uint8_t) ((num >> 16) & 0xff);
buf[3] = (uint8_t) ((num >> 24) & 0xff);
buf[4] = (uint8_t) ((num >> 32) & 0xff);
buf[5] = (uint8_t) ((num >> 40) & 0xff);
buf[6] = (uint8_t) ((num >> 48) & 0xff);
buf[7] = (uint8_t) ((num >> 56) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 8);
}
int uwsgi_buffer_f64be(struct uwsgi_buffer *ub, double num) {
uint8_t buf[8];
uint64_t *pnum = (uint64_t *) &num;
buf[7] = (uint8_t) (*pnum & 0xff);
buf[6] = (uint8_t) ((*pnum >> 8) & 0xff);
buf[5] = (uint8_t) ((*pnum >> 16) & 0xff);
buf[4] = (uint8_t) ((*pnum >> 24) & 0xff);
buf[3] = (uint8_t) ((*pnum >> 32) & 0xff);
buf[2] = (uint8_t) ((*pnum >> 40) & 0xff);
buf[1] = (uint8_t) ((*pnum >> 48) & 0xff);
buf[0] = (uint8_t) ((*pnum >> 56) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 8);
}
int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *ub, void *addr) {
char ip[INET_ADDRSTRLEN];
@@ -270,6 +310,13 @@ int uwsgi_buffer_append_base64(struct uwsgi_buffer *ub, char *s, size_t len) {
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
#ifdef UWSGI_DEBUG_BUFFER
uwsgi_log("[uwsgi-buffer] destroying buffer of %llu bytes\n", (unsigned long long) ub->len);
if (ub->freed) {
uwsgi_log("[uwsgi-buffer][BUG] buffer at %p already destroyed !!!\n", ub);
}
ub->freed = 1;
#endif
if (ub->buf)
free(ub->buf);
free(ub);
+102 -13
View File
@@ -7,7 +7,7 @@ extern struct uwsgi_server uwsgi;
/* how the cache bitmap works:
a bitmap is a shared mempry area allocated when requested by the user with --cache2
a bitmap is a shared memory area allocated when requested by the user with --cache2
Each block maps to a bit in the bitmap. If the corresponding bit is cleared
the block is usable otherwise the block scanner will search for the next one.
@@ -171,6 +171,42 @@ static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *da
}
}
static void uwsgi_cache_add_items(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uwsgi.add_cache_item;
while(usl) {
char *space = strchr(usl->value, ' ');
char *key = usl->value;
uint16_t key_len = usl->len;
if (space) {
// need to skip ?
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
goto next;
}
key = space+1;
key_len = usl->len - ((space-usl->value)+1);
}
char *value = strchr(key, '=');
if (!value) {
uwsgi_log("[cache] unable to store item %s\n", usl->value);
goto next;
}
key_len = value - key;
value++;
uint64_t len = (usl->value + usl->len) - value;
uwsgi_wlock(uc->lock);
if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) {
uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
else {
uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
uwsgi_rwunlock(uc->lock);
next:
usl = usl->next;
}
}
static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uwsgi.load_file_in_cache;
@@ -289,7 +325,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
exit(1);
}
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
if (!uc->items) {
if (uc->items == MAP_FAILED) {
uwsgi_error("uwsgi_cache_init()/mmap() [with store]");
exit(1);
}
@@ -299,7 +335,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
}
else {
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uc->items) {
if (uc->items == MAP_FAILED) {
uwsgi_error("uwsgi_cache_init()/mmap()");
exit(1);
}
@@ -341,6 +377,8 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
uwsgi_cache_load_files(uc);
uwsgi_cache_add_items(uc);
}
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
@@ -461,6 +499,27 @@ char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
return NULL;
}
char *uwsgi_cache_get4(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize, uint64_t *hits) {
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
if (index) {
struct uwsgi_cache_item *uci = cache_item(index);
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
return NULL;
*valsize = uci->valsize;
if (hits)
*hits = uci->hits;
uci->hits++;
uc->hits++;
return uc->data + (uci->first_block * uc->blocksize);
}
uc->miss++;
return NULL;
}
int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t index, uint16_t flags) {
@@ -714,7 +773,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
cache_unmark_blocks(uc, uci->first_block, uci->valsize);
}
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
memcpy(uc->data + (uci->first_block * uc->blocksize), val, vallen);
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
}
else {
int64_t *num = (int64_t *)(((char *) uc->data) + (uci->first_block * uc->blocksize));
@@ -1132,26 +1191,23 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
uc->store = c_store;
if (c_nodes) {
char *p = strtok(c_nodes, ";");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(c_nodes, ";", p, ctx) {
uwsgi_string_new_list(&uc->nodes, p);
p = strtok(NULL, ";");
}
}
if (c_sync) {
char *p = strtok(c_sync, ";");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(c_sync, ";", p, ctx) {
uwsgi_string_new_list(&uc->sync_nodes, p);
p = strtok(NULL, ";");
}
}
if (c_udp_servers) {
char *p = strtok(c_udp_servers, ";");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(c_udp_servers, ";", p, ctx) {
uwsgi_string_new_list(&uc->udp_servers, p);
p = strtok(NULL, ";");
}
}
@@ -1862,3 +1918,36 @@ void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
}
}
struct uwsgi_cache_item *uwsgi_cache_keys(struct uwsgi_cache *uc, uint64_t *pos, struct uwsgi_cache_item **uci) {
// security check
if (*pos >= uc->hashsize) return NULL;
// iterate hashtable
uint64_t orig_pos = *pos;
for(;*pos<uc->hashsize;(*pos)++) {
// get the cache slot
uint64_t slot = uc->hashtable[*pos];
if (*pos == orig_pos && *uci) {
slot = (*uci)->next;
}
if (slot == 0) continue;
*uci = cache_item(slot);
return *uci;
}
(*pos)++;
return NULL;
}
void uwsgi_cache_rlock(struct uwsgi_cache *uc) {
uwsgi_rlock(uc->lock);
}
void uwsgi_cache_rwunlock(struct uwsgi_cache *uc) {
uwsgi_rwunlock(uc->lock);
}
char *uwsgi_cache_item_key(struct uwsgi_cache_item *uci) {
return uci->key;
}
+162
View File
@@ -0,0 +1,162 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
Chunked input implementation
--chunked-input-limit <bytes> (default 1MB)
--chunked-input-timeout <s> (default --socket-timeout)
chunk = uwsgi.chunked_read([timeout])
timeout = -1 (wait forever)
timeout = 0 (default)
*/
static ssize_t uwsgi_chunked_input_recv(struct wsgi_request *wsgi_req, int timeout, int nb) {
if (timeout == 0) timeout = uwsgi.chunked_input_timeout;
if (timeout == 0) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
int ret = -1;
for(;;) {
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
if (rlen > 0) return rlen;
if (rlen == 0) return -1;
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
if (nb) return -1;
goto wait;
}
uwsgi_error("uwsgi_chunked_input_recv()");
return -1;
}
wait:
ret = uwsgi.wait_read_hook(wsgi_req->fd, timeout);
if (ret > 0) {
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
if (rlen > 0) return rlen;
if (rlen <= 0) return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_chunked_input_recv()");
}
return -1;
}
return -1;
}
static ssize_t uwsgi_chunked_readline(struct wsgi_request *wsgi_req) {
size_t i;
int found = 0;
for(i=0;i<wsgi_req->chunked_input_buf->pos;i++) {
if (found) {
if (wsgi_req->chunked_input_buf->buf[i] == '\n') {
// strtoul will stop at \r
size_t num = strtoul(wsgi_req->chunked_input_buf->buf, NULL, 16);
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, i+1)) return -1;
return num;
}
return -1;
}
if ((wsgi_req->chunked_input_buf->buf[i] >= '0' && wsgi_req->chunked_input_buf->buf[i] <= '9') ||
(wsgi_req->chunked_input_buf->buf[i] >= 'a' && wsgi_req->chunked_input_buf->buf[i] <= 'z') ||
(wsgi_req->chunked_input_buf->buf[i] >= 'A' && wsgi_req->chunked_input_buf->buf[i] <= 'Z')) continue;
if (wsgi_req->chunked_input_buf->buf[i] == '\r') { found = 1; continue; }
return -1;
}
return -2;
}
/*
0 -> waiting for \r\n
1 -> waiting for whole body
*/
char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) {
if (!wsgi_req->chunked_input_buf) {
wsgi_req->chunked_input_buf = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->chunked_input_buf->limit = uwsgi.chunked_input_limit;
}
// the whole chunk stream has been consumed
if (wsgi_req->chunked_input_complete) {
*len = 0;
return wsgi_req->chunked_input_buf->buf;
}
if (wsgi_req->chunked_input_decapitate > 0) {
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_decapitate)) return NULL;
wsgi_req->chunked_input_decapitate = 0;
}
for(;;) {
if (wsgi_req->chunked_input_need > 0 || wsgi_req->chunked_input_buf->pos == 0) {
if (uwsgi_buffer_ensure(wsgi_req->chunked_input_buf, UMAX((uint64_t)uwsgi.page_size, wsgi_req->chunked_input_need))) return NULL;
ssize_t rlen = uwsgi_chunked_input_recv(wsgi_req, timeout, nb);
if (rlen <= 0) return NULL;
// update buffer position
wsgi_req->chunked_input_buf->pos += rlen;
if (wsgi_req->chunked_input_need > 0) {
if ((size_t)rlen > wsgi_req->chunked_input_need) {
wsgi_req->chunked_input_need = 0;
}
else {
wsgi_req->chunked_input_need -= rlen;
}
}
}
if (wsgi_req->chunked_input_need > 0) continue;
// ok we have a frame, let's parse it
if (wsgi_req->chunked_input_buf->pos > 0) {
switch(wsgi_req->chunked_input_parser_status) {
case 0:
wsgi_req->chunked_input_chunk_len = uwsgi_chunked_readline(wsgi_req);
if (wsgi_req->chunked_input_chunk_len == -2) {
wsgi_req->chunked_input_need++;
break;
}
else if (wsgi_req->chunked_input_chunk_len < 0) {
return NULL;
}
else if (wsgi_req->chunked_input_chunk_len == 0) {
*len = 0;
wsgi_req->chunked_input_complete = 1;
return wsgi_req->chunked_input_buf->buf;
}
// if here the buffer has been already decapitated
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
wsgi_req->chunked_input_parser_status = 1;
break;
}
*len = wsgi_req->chunked_input_chunk_len;
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
return wsgi_req->chunked_input_buf->buf;
case 1:
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
break;
}
*len = wsgi_req->chunked_input_chunk_len;
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
wsgi_req->chunked_input_parser_status = 0;
return wsgi_req->chunked_input_buf->buf;
}
}
}
}
+1
View File
@@ -0,0 +1 @@
int main() {}
+602
View File
@@ -31,3 +31,605 @@ struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(
return uc;
}
int uwsgi_logic_opt_if_exists(char *key, char *value) {
if (uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
if (!uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_for(char *key, char *value) {
char *p, *ctx = NULL;
uwsgi_foreach_token(uwsgi.logic_opt_data, " ", p, ctx) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
}
return 1;
}
int uwsgi_logic_opt_for_glob(char *key, char *value) {
glob_t g;
int i;
if (glob(uwsgi.logic_opt_data, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("uwsgi_logic_opt_for_glob()");
return 0;
}
for (i = 0; i < (int) g.gl_pathc; i++) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", g.gl_pathv[i]), 0);
}
globfree(&g);
return 1;
}
int uwsgi_logic_opt_for_times(char *key, char *value) {
int num = atoi(uwsgi.logic_opt_data);
int i;
char str_num[11];
for (i = 1; i <= num; i++) {
int ret = uwsgi_num2str2(i, str_num);
// security check
if (ret < 0 || ret > 11) {
exit(1);
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
}
return 1;
}
int uwsgi_logic_opt_if_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_reload(char *key, char *value) {
if (uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_reload(char *key, char *value) {
if (!uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_file(char *key, char *value) {
if (uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_file(char *key, char *value) {
if (!uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_dir(char *key, char *value) {
if (uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_dir(char *key, char *value) {
if (!uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_plugin(char *key, char *value) {
if (plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_plugin(char *key, char *value) {
if (!plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_count_options(struct uwsgi_option *uopt) {
struct uwsgi_option *aopt;
int count = 0;
while ((aopt = uopt)) {
if (!aopt->name)
break;
count++;
uopt++;
}
return count;
}
int uwsgi_opt_exists(char *name) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) return 1;
op++;
}
return 0;
}
/*
avoid loops here !!!
*/
struct uwsgi_option *uwsgi_opt_get(char *name) {
struct uwsgi_option *op;
int round = 0;
retry:
round++;
if (round > 2) goto end;
op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) {
return op;
}
op++;
}
if (uwsgi.autoload) {
if (uwsgi_try_autoload(name)) goto retry;
}
end:
if (uwsgi.strict) {
uwsgi_log("[strict-mode] unknown config directive: %s\n", name);
exit(1);
}
return NULL;
}
void add_exported_option(char *key, char *value, int configured) {
add_exported_option_do(key, value, configured, 0);
}
void add_exported_option_do(char *key, char *value, int configured, int placeholder_only) {
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
struct uwsgi_string_list *whitelist = uwsgi.whitelist;
while (blacklist) {
if (!strcmp(key, blacklist->value)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
blacklist = blacklist->next;
}
if (whitelist) {
int allowed = 0;
while (whitelist) {
if (!strcmp(key, whitelist->value)) {
allowed = 1;
break;
}
whitelist = whitelist->next;
}
if (!allowed) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.blacklist_context) {
if (uwsgi_list_has_str(uwsgi.blacklist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
}
if (uwsgi.whitelist_context) {
if (!uwsgi_list_has_str(uwsgi.whitelist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.logic_opt_running)
goto add;
if (!strcmp(key, "end") || !strcmp(key, "endfor") || !strcmp(key, "endif")) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt = NULL;
uwsgi.logic_opt_arg = NULL;
uwsgi.logic_opt_cycles = 0;
uwsgi.logic_opt_data = NULL;
}
if (uwsgi.logic_opt) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt_data = uwsgi_str(uwsgi.logic_opt_arg);
uwsgi.logic_opt_cycles++;
uwsgi.logic_opt_running = 1;
uwsgi.logic_opt(key, value);
uwsgi.logic_opt_running = 0;
return;
}
add:
if (!uwsgi.exported_opts) {
uwsgi.exported_opts = uwsgi_malloc(sizeof(struct uwsgi_opt *));
}
else {
uwsgi.exported_opts = realloc(uwsgi.exported_opts, sizeof(struct uwsgi_opt *) * (uwsgi.exported_opts_cnt + 1));
if (!uwsgi.exported_opts) {
uwsgi_error("realloc()");
exit(1);
}
}
int id = uwsgi.exported_opts_cnt;
uwsgi.exported_opts[id] = uwsgi_malloc(sizeof(struct uwsgi_opt));
uwsgi.exported_opts[id]->key = key;
uwsgi.exported_opts[id]->value = value;
uwsgi.exported_opts[id]->configured = configured;
uwsgi.exported_opts_cnt++;
uwsgi.dirty_config = 1;
if (placeholder_only) {
if (uwsgi_opt_exists(key)) {
uwsgi_log("you cannot use %s as a placeholder, it is already available as an option\n");
exit(1);
}
uwsgi.exported_opts[id]->configured = 1;
return;
}
struct uwsgi_option *op = uwsgi_opt_get(key);
if (op) {
// requires master ?
if (op->flags & UWSGI_OPT_MASTER) {
uwsgi.master_process = 1;
}
// requires log_master ?
if (op->flags & UWSGI_OPT_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
}
if (op->flags & UWSGI_OPT_REQ_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
uwsgi.req_log_master = 1;
}
// requires threads ?
if (op->flags & UWSGI_OPT_THREADS) {
uwsgi.has_threads = 1;
}
// requires cheaper mode ?
if (op->flags & UWSGI_OPT_CHEAPER) {
uwsgi.cheaper = 1;
}
// requires virtualhosting ?
if (op->flags & UWSGI_OPT_VHOST) {
uwsgi.vhost = 1;
}
// requires memusage ?
if (op->flags & UWSGI_OPT_MEMORY) {
uwsgi.force_get_memusage = 1;
}
// requires auto procname ?
if (op->flags & UWSGI_OPT_PROCNAME) {
uwsgi.auto_procname = 1;
}
// requires lazy ?
if (op->flags & UWSGI_OPT_LAZY) {
uwsgi.lazy = 1;
}
// requires no_initial ?
if (op->flags & UWSGI_OPT_NO_INITIAL) {
uwsgi.no_initial_output = 1;
}
// requires no_server ?
if (op->flags & UWSGI_OPT_NO_SERVER) {
uwsgi.no_server = 1;
}
// requires post_buffering ?
if (op->flags & UWSGI_OPT_POST_BUFFERING) {
if (!uwsgi.post_buffering)
uwsgi.post_buffering = 4096;
}
// requires building mime dict ?
if (op->flags & UWSGI_OPT_MIME) {
uwsgi.build_mime_dict = 1;
}
// enable metrics ?
if (op->flags & UWSGI_OPT_METRICS) {
uwsgi.has_metrics = 1;
}
// immediate ?
if (op->flags & UWSGI_OPT_IMMEDIATE) {
op->func(key, value, op->data);
uwsgi.exported_opts[id]->configured = 1;
}
}
}
void uwsgi_fallback_config() {
if (uwsgi.fallback_config && uwsgi.last_exit_code == 1) {
uwsgi_log_verbose("!!! %s (pid: %d) exited with status %d !!!\n", uwsgi.binary_path, (int) getpid(), uwsgi.last_exit_code);
uwsgi_log_verbose("!!! Fallback config to %s !!!\n", uwsgi.fallback_config);
char *argv[3];
argv[0] = uwsgi.binary_path;
argv[1] = uwsgi.fallback_config;
argv[2] = NULL;
execvp(uwsgi.binary_path, argv);
uwsgi_error("execvp()");
// never here
}
}
int uwsgi_manage_opt(char *key, char *value) {
struct uwsgi_option *op = uwsgi_opt_get(key);
if (op) {
op->func(key, value, op->data);
return 1;
}
return 0;
}
void uwsgi_configure() {
int i;
// and now apply the remaining configs
restart:
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (uwsgi.exported_opts[i]->configured)
continue;
uwsgi.dirty_config = 0;
uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
// some option could cause a dirty config tree
if (uwsgi.dirty_config)
goto restart;
}
}
void uwsgi_opt_custom(char *key, char *value, void *data ) {
struct uwsgi_custom_option *uco = (struct uwsgi_custom_option *)data;
size_t i, count = 1;
size_t value_len = 0;
if (value)
value_len = strlen(value);
off_t pos = 0;
char **opt_argv;
char *tmp_val = NULL, *p = NULL;
// now count the number of args
for (i = 0; i < value_len; i++) {
if (value[i] == ' ') {
count++;
}
}
// allocate a tmp array
opt_argv = uwsgi_calloc(sizeof(char *) * count);
//make a copy of the value;
if (value_len > 0) {
tmp_val = uwsgi_str(value);
// fill the array of options
char *p, *ctx = NULL;
uwsgi_foreach_token(tmp_val, " ", p, ctx) {
opt_argv[pos] = p;
pos++;
}
}
else {
// no argument specified
opt_argv[0] = "";
}
#ifdef UWSGI_DEBUG
uwsgi_log("found custom option %s with %d args\n", key, count);
#endif
// now make a copy of the option template
char *tmp_opt = uwsgi_str(uco->value);
// split it
char *ctx = NULL;
uwsgi_foreach_token(tmp_opt, ";", p, ctx) {
char *equal = strchr(p, '=');
if (!equal)
goto clear;
*equal = '\0';
// build the key
char *new_key = uwsgi_str(p);
for (i = 0; i < count; i++) {
char *old_key = new_key;
char *tmp_num = uwsgi_num2str(i + 1);
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
free(tmp_num);
new_key = uwsgi_substitute(old_key, placeholder, opt_argv[i]);
if (new_key != old_key)
free(old_key);
free(placeholder);
}
// build the value
char *new_value = uwsgi_str(equal + 1);
for (i = 0; i < count; i++) {
char *old_value = new_value;
char *tmp_num = uwsgi_num2str(i + 1);
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
free(tmp_num);
new_value = uwsgi_substitute(old_value, placeholder, opt_argv[i]);
if (new_value != old_value)
free(old_value);
free(placeholder);
}
// ignore return value here
uwsgi_manage_opt(new_key, new_value);
}
clear:
free(tmp_val);
free(tmp_opt);
free(opt_argv);
}
+39 -22
View File
@@ -77,8 +77,14 @@ void uwsgi_daemons_smart_check() {
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);
if (!ud->has_daemonized) {
uwsgi_log_verbose("[uwsgi-daemons] \"%s\" (pid: %d) did not daemonize !!!\n", ud->command, (int) ud->pid);
ud->pidfile_checks = 0;
}
else {
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);
}
}
}
}
@@ -99,10 +105,20 @@ void uwsgi_daemons_smart_check() {
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);
ud->pid = -1;
return -1;
if (ud->pid == diedpid) {
if (!ud->pidfile) {
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
ud->pid = -1;
return -1;
}
else {
if (!ud->has_daemonized) {
ud->has_daemonized = 1;
}
else {
uwsgi_log("[uwsgi-daemons] BUG !!! daemon \"%s\" has already daemonized !!!\n", ud->command);
}
}
}
ud = ud->next;
}
@@ -123,6 +139,10 @@ int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
}
#endif
if (ud->pid == diedpid && !ud->pidfile) {
if (ud->control) {
gracefully_kill_them_all(0);
return 0;
}
uwsgi_spawn_daemon(ud);
return 1;
}
@@ -213,13 +233,15 @@ void uwsgi_detach_daemons() {
#endif
uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
// try to gracefully stop daemon, kill it if it won't die
// if mercy is not set than wait up to 3 seconds
// if mercy is not set then wait up to 3 seconds
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
int waitpid_status;
while (!kill(ud->pid, 0)) {
kill(-ud->pid, SIGTERM);
sleep(1);
waitpid(-ud->pid, &waitpid_status, WNOHANG);
if (uwsgi_now() >= timeout) {
uwsgi_log("[uwsgi-daemons] daemon did not died in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
kill(-ud->pid, SIGKILL);
break;
}
@@ -237,11 +259,12 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
// skip unregistered daemons
if (!ud->registered) return;
int devnull = -1;
int throttle = 0;
if (uwsgi.current_time - ud->last_spawn <= 3) {
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
// if ud->respawns == 0 then we can end up with throttle < 0
if (throttle <= 0) throttle = 1;
}
pid_t pid = uwsgi_fork("uWSGI external daemon");
@@ -251,6 +274,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
}
if (pid > 0) {
ud->has_daemonized = 0;
ud->pid = pid;
ud->status = 1;
ud->pidfile_checks = 0;
@@ -282,18 +306,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
if (!uwsgi.daemons_honour_stdin) {
// /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);
}
uwsgi_remap_fd(0, "/dev/null");
}
if (setsid() < 0) {
@@ -312,7 +325,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
if (throttle) {
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
sleep(throttle);
sleep((unsigned int) throttle);
}
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
@@ -395,6 +408,10 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
uwsgi_ud->last_spawn = 0;
uwsgi_ud->daemonize = daemonize;
uwsgi_ud->pidfile = pidfile;
uwsgi_ud->control = 0;
if (!strcmp(opt, "attach-control-daemon")) {
uwsgi_ud->control = 1;
}
#ifdef UWSGI_SSL
uwsgi_ud->legion = legion;
#endif
+493 -86
View File
@@ -234,11 +234,18 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
if (!uwsgi_emperor_is_valid(de->d_name))
continue;
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (uwsgi.emperor_nofollow) {
if (lstat(de->d_name, &st))
continue;
if (!S_ISLNK(st.st_mode) && !S_ISREG(st.st_mode))
continue;
}
else {
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
}
ui_current = emperor_get(de->d_name);
@@ -294,16 +301,30 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
else {
char *filename = uwsgi_calloc(0xff);
memcpy(filename, c_ui->name, colon - c_ui->name);
if (stat(filename, &st)) {
emperor_stop(c_ui);
if (uwsgi.emperor_nofollow) {
if (lstat(filename, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
}
free(filename);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
if (uwsgi.emperor_nofollow) {
if (lstat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
}
}
c_ui = c_ui->ui_next;
@@ -318,8 +339,13 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
struct stat st;
struct uwsgi_instance *ui_current;
if (chdir(uwsgi.cwd)) {
uwsgi_error("uwsgi_imperial_monitor_glob()/chdir()");
exit(1);
}
if (glob(ues->arg, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("glob()");
uwsgi_error("uwsgi_imperial_monitor_glob()/glob()");
return;
}
@@ -328,11 +354,18 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
if (!uwsgi_emperor_is_valid(g.gl_pathv[i]))
continue;
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (uwsgi.emperor_nofollow) {
if (lstat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
continue;
}
else {
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
}
ui_current = emperor_get(g.gl_pathv[i]);
@@ -389,16 +422,30 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
else {
char *filename = uwsgi_calloc(0xff);
memcpy(filename, c_ui->name, colon - c_ui->name);
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
if (uwsgi.emperor_nofollow) {
if (lstat(filename, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
}
free(filename);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
if (uwsgi.emperor_nofollow) {
if (lstat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
}
}
c_ui = c_ui->ui_next;
@@ -575,24 +622,38 @@ void emperor_del(struct uwsgi_instance *c_ui) {
}
void emperor_stop(struct uwsgi_instance *c_ui) {
if (c_ui->status == 1) return;
// remove uWSGI instance
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("write()");
uwsgi_error("emperor_stop()/write()");
}
c_ui->status = 1;
c_ui->cursed_at = uwsgi_now();
uwsgi_log("[emperor] stop the uwsgi instance %s\n", c_ui->name);
}
void emperor_curse(struct uwsgi_instance *c_ui) {
if (c_ui->status == 1) return;
// curse uWSGI instance
c_ui->status = 1;
c_ui->cursed_at = uwsgi_now();
uwsgi_log("[emperor] curse the uwsgi instance %s (pid: %d)\n", c_ui->name, (int) c_ui->pid);
}
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
struct uwsgi_header uh;
// reload the uWSGI instance
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
uwsgi_error("emperor_respawn/write()");
}
// push the config to the config pipe (if needed)
@@ -748,15 +809,10 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
}
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *);
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
int i;
char *colon = NULL;
int counter;
char **uenvs;
char *uef;
char **vassal_argv;
pid_t pid;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
@@ -780,9 +836,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
// TODO pre-start hook
// a new uWSGI instance will start
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
if (uwsgi.emperor_clone) {
char stack[PTHREAD_STACK_MIN];
pid = clone((int (*)(void *))uwsgi_emperor_spawn_vassal, stack + PTHREAD_STACK_MIN, SIGCHLD | uwsgi.emperor_clone, (void *) n_ui);
}
else {
#endif
pid = fork();
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
}
#endif
if (pid < 0) {
uwsgi_error("fork()")
uwsgi_error("uwsgi_emperor_spawn_vassal()/fork()")
}
else if (pid > 0) {
n_ui->pid = pid;
@@ -812,9 +878,141 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
}
// once the config is sent we can run hooks (they can fail)
// exec hooks have access to all of the currently defined vars + UWSGI_VASSAL_PID, UWSGI_VASSAL_UID, UWSGI_VASSAL_GID, UWSGI_VASSAL_CONFIG
uwsgi_hooks_run(uwsgi.hook_as_emperor, "as-emperor", 0);
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.mount_as_emperor) {
uwsgi_log("mounting \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
if (uwsgi_mount_hook(usl->value)) {
exit(1);
}
}
uwsgi_foreach(usl, uwsgi.umount_as_emperor) {
uwsgi_log("un-mounting \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
if (uwsgi_umount_hook(usl->value)) {
exit(1);
}
}
uwsgi_foreach(usl, uwsgi.exec_as_emperor) {
uwsgi_log("running \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
char *argv[4];
argv[0] = uwsgi_concat2("UWSGI_VASSAL_CONFIG=", n_ui->name);
char argv_pid[17+11]; snprintf(argv_pid, 17 + 11, "UWSGI_VASSAL_PID=%d", (int) n_ui->pid); argv[1] = argv_pid;
char argv_uid[17+11]; snprintf(argv_uid, 17 + 11, "UWSGI_VASSAL_UID=%d", (int) n_ui->uid); argv[2] = argv_uid;
char argv_gid[17+11]; snprintf(argv_gid, 17 + 11, "UWSGI_VASSAL_GID=%d", (int) n_ui->gid); argv[3] = argv_gid;
int ret = uwsgi_run_command_putenv_and_wait(NULL, usl->value, argv, 4);
uwsgi_log("command \"%s\" exited with code: %d\n", usl->value, ret);
free(argv[0]);
}
// 4 call hooks
// config / config + pid / config + pid + uid + gid
// call
uwsgi_foreach(usl, uwsgi.call_as_emperor) {
void (*func)(void) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func();
}
}
uwsgi_foreach(usl, uwsgi.call_as_emperor1) {
void (*func)(char *) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func(n_ui->name);
}
}
uwsgi_foreach(usl, uwsgi.call_as_emperor2) {
void (*func)(char *, pid_t) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func(n_ui->name, n_ui->pid);
}
}
uwsgi_foreach(usl, uwsgi.call_as_emperor4) {
void (*func)(char *, pid_t, uid_t, gid_t) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func(n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
}
}
return 0;
}
else {
uwsgi_emperor_spawn_vassal(n_ui);
}
return -1;
}
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#ifdef CLONE_NEWUSER
if (uwsgi.emperor_clone & CLONE_NEWUSER) {
if (setuid(0)) {
uwsgi_error("uwsgi_emperor_spawn_vassal()/setuid(0)");
exit(1);
}
}
#endif
#ifdef UWSGI_CAP
#if defined(CAP_LAST_CAP) && defined(PR_CAPBSET_READ) && defined(PR_CAPBSET_DROP)
if (uwsgi.emperor_cap && uwsgi.emperor_cap_count > 0) {
int i;
for(i=0;i<=CAP_LAST_CAP;i++) {
int has_cap = prctl(PR_CAPBSET_READ, i, 0, 0, 0);
if (has_cap == 1) {
if (i == CAP_SETPCAP) continue;
int j;int found = 0;
for(j=0;j<uwsgi.emperor_cap_count;j++) {
if (uwsgi.emperor_cap[j] == (int) i) {
found = 1; break;
}
}
if (found) continue;
if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0)) {
uwsgi_error("uwsgi_emperor_spawn_vassal()/prctl()");
uwsgi_log_verbose("unable to drop capability %lu\n", i);
exit(1);
}
}
}
// just for being paranoid
#ifdef SECBIT_KEEP_CAPS
if (prctl(SECBIT_KEEP_CAPS, 1, 0, 0, 0) < 0) {
uwsgi_error("prctl()");
exit(1);
}
#else
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
uwsgi_error("prctl()");
exit(1);
}
#endif
uwsgi_log("capabilities applied for vassal %s (pid: %d)\n", n_ui->name, (int) getpid());
}
#endif
#endif
#endif
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
@@ -837,7 +1035,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
unsetenv("UWSGI_RELOADS");
unsetenv("NOTIFY_SOCKET");
uef = uwsgi_num2str(n_ui->pipe[1]);
char *uef = uwsgi_num2str(n_ui->pipe[1]);
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
@@ -863,15 +1061,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
free(uef);
}
uenvs = environ;
char **uenvs = environ;
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
#ifdef UNSETENV_VOID
unsetenv(oe);
#else
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
free(oe);
break;
}
#endif
free(oe);
ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
@@ -896,17 +1098,40 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
close(n_ui->pipe_config[0]);
}
counter = 4;
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
while (uct) {
int counter = 4;
struct uwsgi_string_list *uct;
uwsgi_foreach(uct, uwsgi.vassals_templates_before) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_includes_before) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_set) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_templates) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_includes) counter += 2;
char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
vassal_argv[0] = uwsgi.emperor_wrapper ? uwsgi.emperor_wrapper: uwsgi.binary_path;
// reset counter
counter = 1;
uwsgi_foreach(uct, uwsgi.vassals_templates_before) {
vassal_argv[counter] = "--inherit";
vassal_argv[counter + 1] = uct->value;
counter += 2;
uct = uct->next;
}
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
vassal_argv[0] = uwsgi.binary_path;
uwsgi_foreach (uct, uwsgi.vassals_includes_before) {
vassal_argv[counter] = "--include";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
uwsgi_foreach (uct, uwsgi.vassals_set) {
vassal_argv[counter] = "--set";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
char *colon = NULL;
if (uwsgi.emperor_broodlord) {
colon = strchr(n_ui->name, ':');
if (colon) {
@@ -914,55 +1139,60 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
}
// initialize to a default value
vassal_argv[1] = "--inherit";
vassal_argv[counter] = "--inherit";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
vassal_argv[1] = "--xml";
vassal_argv[counter] = "--xml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
vassal_argv[1] = "--ini";
vassal_argv[counter] = "--ini";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
vassal_argv[1] = "--yaml";
vassal_argv[counter] = "--yaml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
vassal_argv[1] = "--yaml";
vassal_argv[counter] = "--yaml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
vassal_argv[1] = "--json";
vassal_argv[counter] = "--json";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
vassal_argv[1] = "--json";
vassal_argv[counter] = "--json";
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
while(usl) {
if (uwsgi_endswith(n_ui->name, usl->value)) {
vassal_argv[1] = "--config";
vassal_argv[counter] = "--config";
break;
}
usl = usl->next;
}
if (colon) colon[0] = ':';
if (colon) {
colon[0] = ':';
}
// start config filename...
counter++;
vassal_argv[2] = n_ui->name;
vassal_argv[counter] = n_ui->name;
if (uwsgi.emperor_magic_exec) {
if (!access(n_ui->name, R_OK | X_OK)) {
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
vassal_argv[counter] = uwsgi_concat2("exec://", n_ui->name);
}
}
if (n_ui->use_config) {
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
vassal_argv[counter] = uwsgi_concat2("emperor://", n_ui->name);
}
counter = 3;
uct = uwsgi.vassals_templates;
while (uct) {
// start templates,includes,inherit...
counter++;
uwsgi_foreach(uct, uwsgi.vassals_templates) {
vassal_argv[counter] = "--inherit";
vassal_argv[counter + 1] = uct->value;
counter += 2;
uct = uct->next;
}
uwsgi_foreach (uct, uwsgi.vassals_includes) {
vassal_argv[counter] = "--include";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
vassal_argv[counter] = NULL;
// disable stdin OR map it to the "on demand" socket
@@ -976,22 +1206,13 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
}
else {
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(stdin_fd);
}
uwsgi_remap_fd(0, "/dev/null");
}
// close all of the unneded fd
int i;
for (i = 3; i < (int) uwsgi.max_fd; i++) {
if (uwsgi_fd_is_safe(i)) continue;
if (n_ui->use_config) {
if (i == n_ui->pipe_config[1])
continue;
@@ -1001,6 +1222,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
}
// run start hook (can fail)
if (uwsgi.vassals_start_hook) {
uwsgi_log("[emperor] running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name);
if (uwsgi.emperor_absolute_dir) {
@@ -1012,6 +1234,60 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
uwsgi_log("[emperor] %s start-hook returned %d\n", n_ui->name, start_hook_ret);
}
uwsgi_hooks_run(uwsgi.hook_as_vassal, "as-vassal", 1);
uwsgi_foreach(usl, uwsgi.mount_as_vassal) {
uwsgi_log("mounting \"%s\" (as-vassal)...\n", usl->value);
if (uwsgi_mount_hook(usl->value)) {
exit(1);
}
}
uwsgi_foreach(usl, uwsgi.umount_as_vassal) {
uwsgi_log("un-mounting \"%s\" (as-vassal)...\n", usl->value);
if (uwsgi_umount_hook(usl->value)) {
exit(1);
}
}
// run exec hooks (cannot fail)
uwsgi_foreach(usl, uwsgi.exec_as_vassal) {
uwsgi_log("running \"%s\" (as-vassal)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
}
// run low-level hooks
uwsgi_foreach(usl, uwsgi.call_as_vassal) {
void (*func)(void) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
func();
}
uwsgi_foreach(usl, uwsgi.call_as_vassal1) {
void (*func)(char *) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
func(n_ui->name);
}
uwsgi_foreach(usl, uwsgi.call_as_vassal3) {
void (*func)(char *, uid_t, gid_t) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
func(n_ui->name, n_ui->uid, n_ui->gid);
}
// start !!!
if (execvp(vassal_argv[0], vassal_argv)) {
uwsgi_error("execvp()");
@@ -1019,9 +1295,6 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
uwsgi_log("[emperor] is the uwsgi binary in your system PATH ?\n");
// never here
exit(UWSGI_EXILE_CODE);
}
return -1;
}
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
@@ -1272,7 +1545,8 @@ void emperor_loop() {
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
emperor_del(ui_current);
event_queue_del_fd(uwsgi.emperor_queue, interesting_fd, event_queue_read());
emperor_curse(ui_current);
}
else {
if (byte == 17) {
@@ -1322,10 +1596,14 @@ void emperor_loop() {
while (ui_current) {
if (ui_current->last_heartbeat > 0) {
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);
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, brutally respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
// set last_heartbeat to 0 avoiding races
ui_current->last_heartbeat = 0;
emperor_respawn(ui_current, uwsgi_now());
if (ui_current->pid > 0) {
if (kill(ui_current->pid, SIGKILL)) {
uwsgi_error("[emperor] kill()");
}
}
}
}
ui_current = ui_current->ui_next;
@@ -1374,14 +1652,8 @@ void emperor_loop() {
ui_current = ui;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
if (ui_current->status == 1) {
if (ui_current->config)
free(ui_current->config);
// SAFE
emperor_del(ui_current);
break;
}
else if (ui_current->pid == diedpid) {
time_t now = uwsgi_now();
if (ui_current->pid == diedpid) {
if (ui_current->status == 0) {
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
@@ -1404,6 +1676,13 @@ void emperor_loop() {
break;
}
}
else if (ui_current->cursed_at > 0 && now - ui_current->cursed_at >= uwsgi.emperor_curse_tolerance) {
ui_current->cursed_at = now;
if (kill(ui_current->pid, SIGKILL)) {
uwsgi_error("[emperor] kill");
}
break;
}
}
@@ -1500,6 +1779,8 @@ void emperor_send_stats(int fd) {
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_run", (unsigned long long) c_ui->last_run))
goto end0;
if (uwsgi_stats_keylong_comma(us, "cursed", (unsigned long long) c_ui->cursed_at))
goto end0;
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
goto end0;
@@ -1643,6 +1924,46 @@ void uwsgi_emperor_start() {
}
void uwsgi_check_emperor() {
char *emperor_fd_pass = getenv("UWSGI_EMPEROR_PROXY");
if (emperor_fd_pass) {
for(;;) {
int proxy_fd = uwsgi_connect(emperor_fd_pass, 30, 0);
if (proxy_fd < 0) {
uwsgi_error("uwsgi_check_emperor()/uwsgi_connect()");
sleep(1);
continue;
}
int count = 2;
int *fds = uwsgi_attach_fd(proxy_fd, &count, "uwsgi-emperor", 13);
if (fds && count > 0) {
char *env_emperor_fd = uwsgi_num2str(fds[0]);
if (setenv("UWSGI_EMPEROR_FD", env_emperor_fd, 1)) {
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD)");
free(env_emperor_fd);
int i; for(i=0;i<count;i++) close(fds[i]);
goto next;
}
free(env_emperor_fd);
if (count > 1) {
char *env_emperor_fd_config = uwsgi_num2str(fds[1]);
if (setenv("UWSGI_EMPEROR_FD_CONFIG", env_emperor_fd_config, 1)) {
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD_CONFIG)");
free(env_emperor_fd_config);
int i; for(i=0;i<count;i++) close(fds[i]);
goto next;
}
free(env_emperor_fd_config);
}
break;
}
next:
if (fds) free(fds);
close(proxy_fd);
sleep(1);
}
unsetenv("UWSGI_EMPEROR_PROXY");
}
char *emperor_env = getenv("UWSGI_EMPEROR_FD");
if (emperor_env) {
uwsgi.has_emperor = 1;
@@ -1698,3 +2019,89 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
}
}
void uwsgi_master_manage_emperor() {
char byte;
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
if (rlen > 0) {
uwsgi_log_verbose("received message %d from emperor\n", byte);
// remove me
if (byte == 0) {
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
}
// reload me
else if (byte == 1) {
// un-lazy the stack to trigger a real reload
uwsgi.lazy = 0;
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
}
}
else {
uwsgi_log("lost connection with my emperor !!!\n");
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
sleep(2);
exit(1);
}
}
void uwsgi_master_manage_emperor_proxy() {
struct sockaddr_un epsun;
socklen_t epsun_len = sizeof(struct sockaddr_un);
int ep_client = accept(uwsgi.emperor_fd_proxy, (struct sockaddr *) &epsun, &epsun_len);
if (ep_client < 0) {
uwsgi_error("uwsgi_master_manage_emperor_proxy()/accept()");
return;
}
int num_fds = 1;
if (uwsgi.emperor_fd_config > -1) num_fds++;
struct msghdr ep_msg;
void *ep_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
struct iovec ep_iov[2];
struct cmsghdr *cmsg;
ep_iov[0].iov_base = "uwsgi-emperor";
ep_iov[0].iov_len = 13;
ep_iov[1].iov_base = &num_fds;
ep_iov[1].iov_len = sizeof(int);
ep_msg.msg_name = NULL;
ep_msg.msg_namelen = 0;
ep_msg.msg_iov = ep_iov;
ep_msg.msg_iovlen = 2;
ep_msg.msg_flags = 0;
ep_msg.msg_control = ep_msg_control;
ep_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
cmsg = CMSG_FIRSTHDR(&ep_msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
unsigned char *ep_fd_ptr = CMSG_DATA(cmsg);
memcpy(ep_fd_ptr, &uwsgi.emperor_fd, sizeof(int));
if (num_fds > 1) {
memcpy(ep_fd_ptr + sizeof(int), &uwsgi.emperor_fd_config, sizeof(int));
}
if (sendmsg(ep_client, &ep_msg, 0) < 0) {
uwsgi_error("uwsgi_master_manage_emperor_proxy()/sendmsg()");
}
free(ep_msg_control);
close(ep_client);
}
+122
View File
@@ -0,0 +1,122 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
the --master-fifo option create a unix named pipe (fifo) you can use to send management
commands to the master:
echo r > myfifo
*/
// this var can be accessed by plugins and hooks
void (*uwsgi_fifo_table[256])(int);
static char *uwsgi_fifo_by_slot() {
int count = 0;
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.master_fifo) {
if (count == uwsgi.master_fifo_slot) return usl->value;
count++;
}
return uwsgi.master_fifo->value;
}
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; }
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; }
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; }
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; }
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; }
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; }
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; }
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; }
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; }
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; }
/*
this is called as soon as possibile allowing plugins (or hooks) to override it
*/
void uwsgi_master_fifo_prepare() {
int i;
for(i=0;i<256;i++) {
uwsgi_fifo_table[i] = NULL;
}
uwsgi_fifo_table['0'] = uwsgi_fifo_set_slot_zero;
uwsgi_fifo_table['1'] = uwsgi_fifo_set_slot_one;
uwsgi_fifo_table['2'] = uwsgi_fifo_set_slot_two;
uwsgi_fifo_table['3'] = uwsgi_fifo_set_slot_three;
uwsgi_fifo_table['4'] = uwsgi_fifo_set_slot_four;
uwsgi_fifo_table['5'] = uwsgi_fifo_set_slot_five;
uwsgi_fifo_table['6'] = uwsgi_fifo_set_slot_six;
uwsgi_fifo_table['7'] = uwsgi_fifo_set_slot_seven;
uwsgi_fifo_table['8'] = uwsgi_fifo_set_slot_eight;
uwsgi_fifo_table['9'] = uwsgi_fifo_set_slot_nine;
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
uwsgi_fifo_table['c'] = uwsgi_chain_reload;
uwsgi_fifo_table['C'] = uwsgi_go_cheap;
uwsgi_fifo_table['f'] = uwsgi_refork_master;
uwsgi_fifo_table['l'] = uwsgi_log_reopen;
uwsgi_fifo_table['L'] = uwsgi_log_rotate;
uwsgi_fifo_table['p'] = suspend_resume_them_all;
uwsgi_fifo_table['P'] = uwsgi_update_pidfiles;
uwsgi_fifo_table['q'] = gracefully_kill_them_all;
uwsgi_fifo_table['Q'] = kill_them_all;
uwsgi_fifo_table['r'] = grace_them_all;
uwsgi_fifo_table['R'] = reap_them_all;
uwsgi_fifo_table['s'] = stats;
uwsgi_fifo_table['w'] = uwsgi_reload_workers;
uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
}
int uwsgi_master_fifo() {
char *path = uwsgi_fifo_by_slot();
unlink(path);
if (mkfifo(path, S_IRUSR|S_IWUSR)) {
uwsgi_error("uwsgi_master_fifo()/mkfifo()");
exit(1);
}
int fd = open(path, O_RDONLY|O_NONBLOCK);
if (fd < 0) {
uwsgi_error("uwsgi_master_fifo()/open()");
exit(1);
}
uwsgi_socket_nb(fd);
return fd;
}
int uwsgi_master_fifo_manage(int fd) {
unsigned char cmd;
ssize_t rlen = read(fd, &cmd, 1);
if (rlen < 0) {
if (uwsgi_is_again()) return 0;
uwsgi_error("uwsgi_master_fifo_manage()/read()");
exit(1);
}
// fifo destroyed, recreate it
else if (rlen == 0) {
close(fd);
uwsgi.master_fifo_fd = uwsgi_master_fifo();
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
return 0;
}
if (uwsgi_fifo_table[(int) cmd]) {
uwsgi_fifo_table[(int) cmd](0);
}
return 0;
}
+214
View File
@@ -0,0 +1,214 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
#include <sys/inotify.h>
#endif
#endif
void uwsgi_fsmon_setup() {
struct uwsgi_string_list *usl = uwsgi.fs_reload;
while(usl) {
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
char *copy = uwsgi_str(usl->value);
char *space = strchr(copy, ' ');
if (!space) {
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
free(copy);
goto next;
}
*space = 0;
usl->value = copy;
usl->len = strlen(copy);
usl->custom_ptr = space+1;
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
next:
usl = usl->next;
}
}
int uwsgi_register_fsmon(struct uwsgi_string_list *usl) {
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
static int inotify_fd = -1;
if (inotify_fd == -1) {
inotify_fd = inotify_init();
if (inotify_fd < 0) {
uwsgi_error("uwsgi_register_fsmon()/inotify_init()");
return -1;
}
if (event_queue_add_fd_read(uwsgi.master_queue, inotify_fd)) {
uwsgi_error("uwsgi_register_fsmon()/event_queue_add_fd_read()");
return -1;
}
}
int wd = inotify_add_watch(inotify_fd, usl->value, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
if (wd < 0) {
uwsgi_error("uwsgi_register_fsmon()/inotify_add_watch()");
return -1;
}
usl->custom = inotify_fd;
usl->custom2 = wd;
return 0;
#endif
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
struct kevent kev;
int fd = open(usl->value, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(usl->value);
uwsgi_error("uwsgi_register_fsmon()/open()");
return -1;
}
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_WRITE | NOTE_DELETE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, 0, 0);
if (kevent(uwsgi.master_queue, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("uwsgi_register_fsmon()/kevent()");
return -1;
}
usl->custom = fd;
usl->custom2 = fd;
return 0;
#endif
uwsgi_log("[uwsgi-fsmon] filesystem monitoring interface not available in this platform !!!\n");
return 1;
}
static struct uwsgi_string_list *uwsgi_fsmon_ack(int interesting_fd) {
int found_fd = -1;
struct uwsgi_string_list *usl = uwsgi.fs_reload;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
found:
if (found_fd == -1) return NULL;
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
unsigned int isize = 0;
if (ioctl(found_fd, FIONREAD, &isize) < 0) {
uwsgi_error("uwsgi_fsmon_ack()/ioctl()");
return 0;
}
if (isize == 0) return NULL;
struct inotify_event *ie = uwsgi_malloc(isize);
// read from the inotify descriptor
ssize_t len = read(found_fd, ie, isize);
if (len < 0) { free(ie); uwsgi_error("uwsgi_fsmon_ack()/read()"); return NULL;}
found_fd = ie->wd;
free(ie);
#endif
#endif
// search for the item id and print it
usl = uwsgi.fs_reload;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return uwsgi.fs_reload;
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return uwsgi.fs_brutal_reload;
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return usl;
}
usl = usl->next;
}
return NULL;
}
int uwsgi_fsmon_event(int interesting_fd) {
struct uwsgi_string_list *usl = uwsgi_fsmon_ack(interesting_fd);
if (!usl) return 0;
if (usl == uwsgi.fs_reload) {
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
return 1;
}
if (usl == uwsgi.fs_brutal_reload) {
if (uwsgi.die_on_term) {
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
else {
uwsgi_block_signal(SIGTERM);
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
return 1;
}
// fallback to signal
uwsgi_route_signal(atoi(usl->custom_ptr));
return 1;
}
+2 -1
View File
@@ -41,7 +41,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
if (!uwsgi.master_process)
if (!uwsgi.master_process && !uwsgi.force_gateway)
gateway_respawn(ushared->gateways_cnt);
ushared->gateways_cnt++;
@@ -70,6 +70,7 @@ void gateway_respawn(int id) {
if (gw_pid == 0) {
uwsgi_fixup_fds(0, 0, ug);
uwsgi_close_all_sockets();
if (uwsgi.master_as_root)
uwsgi_as_root();
#ifdef __linux__
+21 -1
View File
@@ -17,7 +17,7 @@ uint32_t djb33x_hash(char *key, uint64_t keylen) {
// Murmur2 hash Copyright (C) Austin Appleby
// adapted from nginx
uint32_t murmur2_hash(char *key, uint64_t keylen) {
static uint32_t murmur2_hash(char *key, uint64_t keylen) {
uint32_t h, k;
uint8_t *ukey = (uint8_t *) key;
@@ -56,6 +56,23 @@ uint32_t murmur2_hash(char *key, uint64_t keylen) {
return h;
}
static uint32_t random_hash(char *key, uint64_t keylen) {
return (uint32_t) rand();
}
/*
not atomic, avoid its use in multithreaded modes
*/
static uint32_t rr_hash(char *key, uint64_t keylen) {
static uint32_t rr = 0;
uint32_t max_value = uwsgi_str_num(key, keylen);
uint32_t ret = rr;
rr++;
if (rr > max_value) {
rr = 0;
}
return ret;
}
struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *name) {
struct uwsgi_hash_algo *uha = uwsgi.hash_algos;
@@ -90,4 +107,7 @@ void uwsgi_hash_algo_register(char *name, uint32_t (*func)(char *, uint64_t)) {
void uwsgi_hash_algo_register_all() {
uwsgi_hash_algo_register("djb33x", djb33x_hash);
uwsgi_hash_algo_register("murmur2", murmur2_hash);
uwsgi_hash_algo_register("random", random_hash);
uwsgi_hash_algo_register("rand", random_hash);
uwsgi_hash_algo_register("rr", rr_hash);
}
+217
View File
@@ -0,0 +1,217 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
advanced (pluggable) hooks
they are executed before the other hooks, and can be extended by plugins
if a plugin tries to register an hook with a name already available in the list, its function
will be overridden
*/
struct uwsgi_hook *uwsgi_hook_by_name(char *name) {
struct uwsgi_hook *uh = uwsgi.hooks;
while(uh) {
if (!strcmp(uh->name, name)) {
return uh;
}
uh = uh->next;
}
return NULL;
}
void uwsgi_register_hook(char *name, int (*func)(char *)) {
struct uwsgi_hook *old_uh = NULL, *uh = uwsgi.hooks;
while(uh) {
if (!strcmp(uh->name, name)) {
uh->func = func;
return;
}
old_uh = uh;
uh = uh->next;
}
uh = uwsgi_calloc(sizeof(struct uwsgi_hook));
uh->name = name;
uh->func = func;
if (old_uh) {
old_uh->next = uh;
}
else {
uwsgi.hooks = uh;
}
}
static int uwsgi_hook_chdir(char *arg) {
int ret = chdir(arg);
if (ret) {
uwsgi_error("uwsgi_hook_chdir()");
}
return ret;
}
static int uwsgi_hook_exec(char *arg) {
int ret = uwsgi_run_command_and_wait(NULL, arg);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", arg, ret);
}
return ret;
}
static int uwsgi_hook_exit(char *arg) {
int exit_code = 0;
if (strlen(arg) > 1) {
exit_code = atoi(arg);
}
exit(exit_code);
}
static int uwsgi_hook_print(char *arg) {
char *line = uwsgi_concat2(arg, "\n");
uwsgi_log(line);
free(line);
return 0;
}
static int uwsgi_hook_callint(char *arg) {
char *space = strchr(arg, ' ');
if (space) {
*space = 0;
int num = atoi(space+1);
void (*func)(int) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
*space = ' ';
return -1;
}
*space = ' ';
func(num);
}
else {
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", arg);
return -1;
}
func();
}
return 0;
}
static int uwsgi_hook_call(char *arg) {
char *space = strchr(arg, ' ');
if (space) {
*space = 0;
void (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
*space = ' ';
return -1;
}
*space = ' ';
func(space + 1);
}
else {
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", arg);
return -1;
}
func();
}
return 0;
}
static int uwsgi_hook_callintret(char *arg) {
char *space = strchr(arg, ' ');
if (space) {
*space = 0;
int num = atoi(space+1);
int (*func)(int) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
*space = ' ';
return -1;
}
*space = ' ';
return func(num);
}
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", arg);
return -1;
}
return func();
}
static int uwsgi_hook_callret(char *arg) {
char *space = strchr(arg, ' ');
if (space) {
*space = 0;
int (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
*space = ' ';
return -1;
}
*space = ' ';
return func(space + 1);
}
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", arg);
return -1;
}
return func();
}
void uwsgi_register_base_hooks() {
uwsgi_register_hook("cd", uwsgi_hook_chdir);
uwsgi_register_hook("exec", uwsgi_hook_exec);
uwsgi_register_hook("mount", uwsgi_mount_hook);
uwsgi_register_hook("umount", uwsgi_umount_hook);
uwsgi_register_hook("call", uwsgi_hook_call);
uwsgi_register_hook("callret", uwsgi_hook_callret);
uwsgi_register_hook("callint", uwsgi_hook_callint);
uwsgi_register_hook("callintret", uwsgi_hook_callintret);
// for testing
uwsgi_register_hook("exit", uwsgi_hook_exit);
uwsgi_register_hook("print", uwsgi_hook_print);
}
void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, l) {
char *colon = strchr(usl->value, ':');
if (!colon) {
uwsgi_log("invalid hook syntax, must be hook:args\n");
exit(1);
}
*colon = 0;
struct uwsgi_hook *uh = uwsgi_hook_by_name(usl->value);
if (!uh) {
uwsgi_log("hook not found: %s\n", usl->value);
exit(1);
}
*colon = ':';
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
int ret = uh->func(colon+1);
if (fatal && ret != 0) {
exit(1);
}
}
}
+38 -6
View File
@@ -51,6 +51,7 @@ struct http_status_codes hsc[] = {
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{"509", "Bandwidth Limit Exceeded"},
{"", NULL},
};
@@ -75,10 +76,12 @@ void uwsgi_init_default() {
uwsgi.original_log_fd = -1;
uwsgi.emperor_fd_config = -1;
uwsgi.emperor_fd_proxy = -1;
// default emperor scan frequency
uwsgi.emperor_freq = 3;
uwsgi.emperor_throttle = 1000;
uwsgi.emperor_heartbeat = 30;
uwsgi.emperor_curse_tolerance = 30;
// max 3 minutes throttling
uwsgi.emperor_max_throttle = 1000 * 180;
uwsgi.emperor_pid = -1;
@@ -169,6 +172,15 @@ void uwsgi_init_default() {
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
uwsgi_websockets_init();
// 1 MB default limit
uwsgi.chunked_input_limit = 1024*1024;
// clear reforked status
uwsgi.master_is_reforked = 0;
uwsgi.master_fifo_fd = -1;
uwsgi_master_fifo_prepare();
}
void uwsgi_setup_reload() {
@@ -213,21 +225,19 @@ void uwsgi_autoload_plugins_by_name(char *argv_zero) {
p = original_proc_name;
p = strstr(p, "uwsgi_");
if (p != NULL) {
plugins_requested = strtok(uwsgi_str(p + 6), "_");
while (plugins_requested) {
char *ctx = NULL;
uwsgi_foreach_token(uwsgi_str(p + 6), "_", plugins_requested, ctx) {
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) {
char *p, *ctx = NULL;
uwsgi_foreach_token(plugins_requested, ",", p, ctx) {
uwsgi_load_plugin(-1, p, NULL);
p = strtok(NULL, ",");
}
}
@@ -354,6 +364,7 @@ void uwsgi_setup_workers() {
#ifdef UWSGI_ROUTING
uwsgi_fixup_routes(uwsgi.routes);
uwsgi_fixup_routes(uwsgi.error_routes);
uwsgi_fixup_routes(uwsgi.response_routes);
uwsgi_fixup_routes(uwsgi.final_routes);
#endif
@@ -384,6 +395,8 @@ pid_t uwsgi_daemonize2() {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
if (uwsgi.log_master) uwsgi_setup_log_master();
return uwsgi.mypid;
}
@@ -446,6 +459,25 @@ void sanitize_args() {
exit(1);
}
if (uwsgi.cheaper_rss_limit_soft && uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] != 1 && uwsgi.force_get_memusage != 1) {
uwsgi_log("enabling cheaper-rss-limit-soft requires enabling also memory-report\n");
exit(1);
}
if (uwsgi.cheaper_rss_limit_hard && !uwsgi.cheaper_rss_limit_soft) {
uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
exit(1);
}
if ( uwsgi.cheaper_rss_limit_hard && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
uwsgi_log("cheaper-rss-limit-hard value must be higher than cheaper-rss-limit-soft value\n");
exit(1);
}
/* here we try to choose if thunder lock is a good thing */
#ifdef UNBIT
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
uwsgi.use_thunder_lock = 1;
}
#endif
}
const char *uwsgi_http_status_msg(char *status, uint16_t *len) {
+322 -189
View File
@@ -116,48 +116,31 @@ end:
}
/*
extremely complex function for reading resources (files, url...)
need a lot of refactoring...
*/
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
static char *uwsgi_scheme_fd(char *url, size_t *size, int add_zero) {
int fd = atoi(url);
return uwsgi_read_fd(fd, size, add_zero);
}
int fd;
struct stat sb;
char *buffer = NULL;
static char *uwsgi_scheme_exec(char *url, size_t *size, int add_zero) {
int cpipe[2];
if (pipe(cpipe)) {
uwsgi_error("pipe()");
exit(1);
}
uwsgi_run_command(url, NULL, cpipe[1]);
char *buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
close(cpipe[0]);
close(cpipe[1]);
return buffer;
}
static char *uwsgi_scheme_http(char *url, size_t *size, int add_zero) {
char byte;
ssize_t len;
char *uri, *colon;
char *domain;
char *ip;
int body = 0;
char *magic_buf;
int body = 0;
char *buffer = NULL;
// stdin ?
if (!strcmp(url, "-")) {
buffer = uwsgi_read_fd(0, size, add_zero);
}
// fd ?
else if (!strncmp("fd://", url, 5)) {
fd = atoi(url + 5);
buffer = uwsgi_read_fd(fd, size, add_zero);
}
// exec ?
else if (!strncmp("exec://", url, 5)) {
int cpipe[2];
if (pipe(cpipe)) {
uwsgi_error("pipe()");
exit(1);
}
uwsgi_run_command(url + 7, NULL, cpipe[1]);
buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
close(cpipe[0]);
close(cpipe[1]);
}
// http url ?
else if (!strncmp("http://", url, 7)) {
domain = url + 7;
uri = strchr(domain, '/');
char *domain = url;
char *uri = strchr(domain, '/');
if (!uri) {
uwsgi_log("invalid http url\n");
exit(1);
@@ -165,14 +148,14 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
uri[0] = 0;
uwsgi_log("domain: %s\n", domain);
colon = uwsgi_get_last_char(domain, ':');
char *colon = uwsgi_get_last_char(domain, ':');
if (colon) {
colon[0] = 0;
}
ip = uwsgi_resolve_ip(domain);
char *ip = uwsgi_resolve_ip(domain);
if (!ip) {
uwsgi_log("unable to resolve address %s\n", domain);
exit(1);
@@ -186,9 +169,10 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
ip = uwsgi_concat2(ip, ":80");
}
fd = uwsgi_connect(ip, 0, 0);
int fd = uwsgi_connect(ip, 0, 0);
if (fd < 0) {
uwsgi_error("uwsgi_scheme_http()/connect()");
exit(1);
}
@@ -196,18 +180,18 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
uri[0] = '/';
len = write(fd, "GET ", 4);
len = write(fd, uri, strlen(uri));
len = write(fd, " HTTP/1.0\r\n", 11);
len = write(fd, "Host: ", 6);
if (write(fd, "GET ", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, uri, strlen(uri)) != (ssize_t) strlen(uri)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, " HTTP/1.0\r\n", 11) != 11) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, "Host: ", 6) != 6) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
uri[0] = 0;
len = write(fd, domain, strlen(domain));
if (write(fd, domain, strlen(domain)) != (ssize_t) strlen(domain)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
uri[0] = '/';
len = write(fd, "\r\nUser-Agent: uWSGI on ", 23);
len = write(fd, uwsgi.hostname, uwsgi.hostname_len);
len = write(fd, "\r\n\r\n", 4);
if (write(fd, "\r\nUser-Agent: uWSGI on ", 23) != 23) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, uwsgi.hostname, uwsgi.hostname_len) != uwsgi.hostname_len) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, "\r\n\r\n", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
int http_status_code_ptr = 0;
@@ -264,57 +248,233 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
buffer[*size - 1] = 0;
}
return buffer;
}
static char *uwsgi_scheme_emperor(char *url, size_t *size, int add_zero) {
if (uwsgi.emperor_fd_config < 0) {
uwsgi_log("this is not a vassal instance\n");
exit(1);
}
else if (!strncmp("emperor://", url, 10)) {
if (uwsgi.emperor_fd_config < 0) {
uwsgi_log("this is not a vassal instance\n");
ssize_t rlen;
struct uwsgi_header uh;
size_t remains = 4;
char *ptr = (char *) &uh;
while(remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
exit(1);
}
ssize_t rlen;
*size = 0;
struct uwsgi_header uh;
size_t remains = 4;
char *ptr = (char *) &uh;
while(remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
exit(1);
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config header from %s !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
}
remains = uh.pktsize;
if (!remains) {
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
remains = uh.pktsize;
if (!remains) {
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
exit(1);
}
char *buffer = uwsgi_calloc(remains + add_zero);
ptr = buffer;
while (remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
exit(1);
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config from %s !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
}
*size = uh.pktsize + add_zero;
return buffer;
}
static char *uwsgi_scheme_data(char *url, size_t *size, int add_zero) {
char *buffer = NULL;
int fd = open(uwsgi.binary_path, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(uwsgi.binary_path);
exit(1);
}
int slot = atoi(url);
if (slot < 0) {
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
uwsgi_log("requesting binary data slot %d\n", slot);
off_t fo = lseek(fd, 0, SEEK_END);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
int i = 0;
uint64_t datasize = 0;
for (i = 0; i <= slot; i++) {
fo = lseek(fd, -8, SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
ssize_t len = read(fd, &datasize, 8);
if (len != 8) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
if (datasize == 0) {
uwsgi_log("0 size binary data !!!\n");
exit(1);
}
fo = lseek(fd, -(datasize + 8), SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
buffer = uwsgi_calloc(remains + add_zero);
ptr = buffer;
while (remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
exit(1);
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
if (i == slot) {
*size = datasize;
if (add_zero) {
*size += 1;
}
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
len = read(fd, buffer, datasize);
if (len != (ssize_t) datasize) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
}
*size = uh.pktsize + add_zero;
}
close(fd);
return buffer;
}
static char *uwsgi_scheme_call(char *url, size_t *size, int add_zero) {
char *(*func)(void) = dlsym(RTLD_DEFAULT, url);
if (!func) {
uwsgi_log("unable to find symbol %s\n", url);
exit(1);
}
char *s = func();
if (!s) {
uwsgi_log("called symbol %s did not return a string\n", url);
exit(1);
}
*size = strlen(s);
if (add_zero) {
*size += 1;
}
char *buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, s, strlen(s));
return buffer;
}
static char *uwsgi_scheme_sym(char *url, size_t *size, int add_zero) {
void *sym_start_ptr = NULL, *sym_end_ptr = NULL;
char **raw_symbol = dlsym(RTLD_DEFAULT, url);
if (raw_symbol) {
sym_start_ptr = *raw_symbol;
sym_end_ptr = sym_start_ptr + strlen(sym_start_ptr);
goto found;
}
char *symbol = uwsgi_concat3("_binary_", url, "_start");
sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_start_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
symbol = uwsgi_concat3("_binary_", url, "_end");
sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_end_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
found:
*size = sym_end_ptr - sym_start_ptr;
if (add_zero) {
*size += 1;
}
char *buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
return buffer;
}
static char *uwsgi_scheme_section(char *url, size_t *size, int add_zero) {
#ifdef UWSGI_ELF
size_t s_len = 0;
char *buffer = uwsgi_elf_section(uwsgi.binary_path, url, &s_len);
if (!buffer) {
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
exit(1);
}
*size = s_len;
if (add_zero)
*size += 1;
return buffer;
#else
uwsgi_log("section:// scheme not supported on this platform\n");
exit(1);
#endif
}
struct uwsgi_string_list *uwsgi_register_scheme(char *name, char * (*func)(char *, size_t *, int)) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.schemes) {
if (!strcmp(usl->value, name)) goto found;
}
usl = uwsgi_string_new_list(&uwsgi.schemes, name);
found:
usl->custom_ptr = func;
return usl;
}
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
struct stat sb;
char *buffer = NULL;
ssize_t len;
char *magic_buf;
int fd;
*size = 0;
// stdin ?
if (!strcmp(url, "-")) {
buffer = uwsgi_read_fd(0, size, add_zero);
goto end;
}
#ifdef UWSGI_EMBED_CONFIG
else if (url[0] == 0) {
*size = &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG;
@@ -324,108 +484,22 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, &UWSGI_EMBED_CONFIG, &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG);
goto end;
}
#endif
else if (!strncmp("data://", url, 7)) {
fd = open(uwsgi.binary_path, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(uwsgi.binary_path);
exit(1);
}
int slot = atoi(url + 7);
if (slot < 0) {
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
uwsgi_log("requesting binary data slot %d\n", slot);
off_t fo = lseek(fd, 0, SEEK_END);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
int i = 0;
uint64_t datasize = 0;
for (i = 0; i <= slot; i++) {
fo = lseek(fd, -9, SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
ssize_t len = read(fd, &datasize, 8);
if (len != 8) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
if (datasize == 0) {
uwsgi_log("0 size binary data !!!\n");
exit(1);
}
fo = lseek(fd, -(datasize + 9), SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
if (i == slot) {
*size = datasize;
if (add_zero) {
*size += 1;
}
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
len = read(fd, buffer, datasize);
if (len != (ssize_t) datasize) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
}
}
}
else if (!strncmp("sym://", url, 6)) {
char *symbol = uwsgi_concat3("_binary_", url + 6, "_start");
void *sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_start_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
symbol = uwsgi_concat3("_binary_", url + 6, "_end");
void *sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_end_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
struct uwsgi_string_list *usl = uwsgi_check_scheme(url);
if (!usl) goto fallback;
*size = sym_end_ptr - sym_start_ptr;
if (add_zero) {
*size += 1;
}
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
}
#ifdef UWSGI_ELF
else if (!strncmp("section://", url, 10)) {
size_t s_len = 0;
buffer = uwsgi_elf_section(uwsgi.binary_path, url + 10, &s_len);
if (!buffer) {
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
exit(1);
}
*size = s_len;
if (add_zero)
*size += 1;
}
#endif
char *(*func)(char *, size_t *, int) = (char *(*)(char *, size_t *, int)) usl->custom_ptr;
buffer = func(url + usl->len + 3, size, add_zero);
if (buffer) goto end;
// never here !!!
uwsgi_log("unable to parse config file %s\n", url);
exit(1);
// fallback to file
else {
fallback:
fd = open(url, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(url);
@@ -457,7 +531,6 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
if (add_zero)
buffer[sb.st_size] = 0;
}
end:
@@ -1078,3 +1151,63 @@ void uwsgi_add_safe_fd(int fd) {
uwsgi.safe_fds[uwsgi.safe_fds_cnt] = fd;
uwsgi.safe_fds_cnt++;
}
int uwsgi_is_again() {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
return 1;
}
return 0;
}
void uwsgi_disconnect(struct wsgi_request *wsgi_req) {
if (wsgi_req->socket) {
wsgi_req->socket->proto_close(wsgi_req);
}
wsgi_req->fd_closed = 1;
}
int uwsgi_ready_fd(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_ready_fd) return wsgi_req->async_last_ready_fd;
return -1;
}
void uwsgi_setup_schemes() {
uwsgi_register_scheme("emperor", uwsgi_scheme_emperor);
uwsgi_register_scheme("http", uwsgi_scheme_http);
uwsgi_register_scheme("data", uwsgi_scheme_data);
uwsgi_register_scheme("sym", uwsgi_scheme_sym);
uwsgi_register_scheme("section", uwsgi_scheme_section);
uwsgi_register_scheme("fd", uwsgi_scheme_fd);
uwsgi_register_scheme("exec", uwsgi_scheme_exec);
uwsgi_register_scheme("call", uwsgi_scheme_call);
}
struct uwsgi_string_list *uwsgi_check_scheme(char *file) {
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.schemes) {
char *url = uwsgi_concat2(usl->value, "://");
int ret = uwsgi_startswith(file, url, strlen(url));
free(url);
if (!ret) return usl;
}
return NULL;
}
void uwsgi_remap_fd(int fd, char *filename) {
int fdin = open(filename, O_RDWR);
if (fdin < 0) {
uwsgi_error_open(filename);
exit(1);
}
/* stdin */
if (fdin != fd) {
if (dup2(fdin, fd) < 0) {
uwsgi_error("uwsgi_remap_fd()/dup2()");
exit(1);
}
close(fdin);
}
}
+2
View File
@@ -106,6 +106,8 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
config_iter = json_object_iter_next(config, config_iter);
}
if (colon) colon[0] = ':';
}
#endif
+25 -2
View File
@@ -79,6 +79,9 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen
ul->scroll = value;
ul->scroll_len = vallen;
}
else if (!uwsgi_strncmp(key, keylen, "dead", 4)) {
ul->dead = 1;
}
}
// this function is called when a node is added or removed (heavy locking is needed)
@@ -611,6 +614,14 @@ static void *legion_loop(void *foobar) {
usl = usl->next;
}
}
// remove node announcing death
else if (legion_msg.dead) {
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s announced its death to Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
uwsgi_wlock(ul->lock);
uwsgi_legion_remove_node(ul, node);
uwsgi_rwunlock(ul->lock);
continue;
}
node->last_seen = uwsgi_now();
node->lord_valor = legion_msg.lord_valor;
@@ -752,8 +763,11 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
if (uwsgi_buffer_append_keyval(ub, "scroll", 6, ul->scroll, ul->scroll_len))
goto err;
}
#ifdef UWSGI_UUID
#endif
if (ul->dead) {
if (uwsgi_buffer_append_keyval(ub, "dead", 4, "1", 1))
goto err;
}
unsigned char *encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
if (EVP_EncryptInit_ex(ul->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
@@ -1122,6 +1136,14 @@ void uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *
}
}
void uwsgi_legion_announce_death(void) {
struct uwsgi_legion *legion = uwsgi.legions;
while (legion) {
legion->dead = 1;
uwsgi_legion_announce(legion);
legion = legion->next;
}
}
void uwsgi_legion_atexit(void) {
struct uwsgi_legion *legion = uwsgi.legions;
@@ -1140,6 +1162,7 @@ next:
legion = legion->next;
}
uwsgi_legion_announce_death();
}
int uwsgi_legion_i_am_the_lord(char *name) {
+69 -6
View File
@@ -493,7 +493,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
if (uwsgi.ftok) {
myKey = ftok(uwsgi.ftok, counter);
if (myKey < 0) {
uwsgi_error("ftok()");
uwsgi_error("uwsgi_lock_ipcsem_init()/ftok()");
exit(1);
}
counter++;
@@ -504,7 +504,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
}
if (semid < 0) {
uwsgi_error("semget()");
uwsgi_error("uwsgi_lock_ipcsem_init()/semget()");
exit(1);
}
// do this now, to allows triggering of atexit hook in case of problems
@@ -512,7 +512,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
semu.val = 1;
if (semctl(semid, 0, SETVAL, semu)) {
uwsgi_error("semctl()");
uwsgi_error("uwsgi_lock_ipcsem_init()/semctl()");
exit(1);
}
@@ -532,7 +532,13 @@ void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
retry:
if (semop(semid, &sb, 1)) {
if (errno == EINTR) goto retry;
uwsgi_error("semop()");
uwsgi_error("uwsgi_lock_ipcsem()/semop()");
#ifdef EIDRM
if (errno == EIDRM) {
exit(UWSGI_BRUTAL_RELOAD_CODE);
}
#endif
exit(1);
}
}
@@ -549,7 +555,13 @@ void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
retry:
if (semop(semid, &sb, 1)) {
if (errno == EINTR) goto retry;
uwsgi_error("semop()");
uwsgi_error("uwsgi_unlock_ipcsem()/semop()");
#ifdef EIDRM
if (errno == EIDRM) {
exit(UWSGI_BRUTAL_RELOAD_CODE);
}
#endif
exit(1);
}
}
@@ -574,6 +586,8 @@ pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
void uwsgi_ipcsem_clear(void) {
if (uwsgi.persistent_ipcsem) return;
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uwsgi.workers)
@@ -594,12 +608,27 @@ clear:
#ifdef UWSGI_DEBUG
uwsgi_log("removing sysvipc semaphores...\n");
#endif
#ifdef GETPID
while (uli) {
int semid = 0;
memcpy(&semid, uli->lock_ptr, sizeof(int));
int ret = semctl(semid, 0, GETPID);
if (ret > 0) {
if (ret != (int) getpid() && !kill((pid_t) ret, 0)) {
uwsgi_log("found ipcsem mapped to alive pid %d. skipping ipcsem removal.\n", ret);
return;
}
}
uli = uli->next;
}
uli = uwsgi.registered_locks;
#endif
while (uli) {
int semid = 0;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semctl(semid, 0, IPC_RMID)) {
uwsgi_error("semctl()");
uwsgi_error("uwsgi_ipcsem_clear()/semctl()");
}
uli = uli->next;
}
@@ -610,6 +639,32 @@ pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) {
return uwsgi_lock_ipcsem_check(uli);
}
#ifdef UNBIT
/*
Unbit-specific workaround for robust-mutexes
*/
void *uwsgi_robust_mutexes_watchdog_loop(void *arg) {
for(;;) {
uwsgi_lock(uwsgi.the_thunder_lock);
uwsgi_unlock(uwsgi.the_thunder_lock);
}
return NULL;
}
void uwsgi_robust_mutexes_watchdog() {
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// 32K should be more than enough...
pthread_attr_setstacksize(&attr, 32 * 1024);
if (pthread_create(&tid, &attr, uwsgi_robust_mutexes_watchdog_loop, NULL)) {
uwsgi_error("uwsgi_robust_mutexes_watchdog()/pthread_create()");
exit(1);
}
}
#endif
void uwsgi_setup_locking() {
@@ -689,6 +744,14 @@ ready:
if (uwsgi.use_thunder_lock) {
// process shared thunder lock
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
#ifdef UNBIT
// we have a serious bug on Unbit (and very probably on older libc)
// when all of the workers die in the same moment the pthread robust mutes is left
// in inconsistent state and we have no way to recover
// we span a thread in the master constantly ensuring the lock is ok
// for now we apply it only for Unbit (where thunder-lock is automatically enabled)
uwsgi_robust_mutexes_watchdog();
#endif
}
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
+577 -79
View File
@@ -45,7 +45,7 @@ void uwsgi_log(const char *fmt, ...) {
}
else {
gettimeofday(&tv, NULL);
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
@@ -97,7 +97,7 @@ void uwsgi_log_verbose(const char *fmt, ...) {
}
else {
gettimeofday(&tv, NULL);
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
@@ -120,17 +120,54 @@ void uwsgi_log_verbose(const char *fmt, ...) {
static void fix_logpipe_buf(int *fd) {
int so_bufsize;
socklen_t so_bufsize_len = sizeof(int);
if (getsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("fix_logpipe_buf()/getsockopt()");
return;
}
if ((size_t)so_bufsize < uwsgi.log_master_bufsize) {
so_bufsize = uwsgi.log_master_bufsize;
if (setsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &so_bufsize, so_bufsize_len)) {
uwsgi_error("fix_logpipe_buf()/setsockopt()");
}
}
if (getsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("fix_logpipe_buf()/getsockopt()");
return;
}
if ((size_t)so_bufsize < uwsgi.log_master_bufsize) {
so_bufsize = uwsgi.log_master_bufsize;
if (setsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &so_bufsize, so_bufsize_len)) {
uwsgi_error("fix_logpipe_buf()/setsockopt()");
}
}
}
// create the logpipe
void create_logpipe(void) {
if (uwsgi.log_master_stream) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->worker_log_pipe)) {
uwsgi_error("create_logpipe()/socketpair()\n");
exit(1);
}
}
else {
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) {
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
#endif
uwsgi_error("socketpair()\n");
exit(1);
uwsgi_error("create_logpipe()/socketpair()\n");
exit(1);
}
fix_logpipe_buf(uwsgi.shared->worker_log_pipe);
}
uwsgi_socket_nb(uwsgi.shared->worker_log_pipe[0]);
@@ -149,13 +186,22 @@ void create_logpipe(void) {
}
if (uwsgi.req_log_master) {
if (uwsgi.log_master_req_stream) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->worker_req_log_pipe)) {
uwsgi_error("create_logpipe()/socketpair()\n");
exit(1);
}
}
else {
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_req_log_pipe)) {
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_req_log_pipe)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_req_log_pipe)) {
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_req_log_pipe)) {
#endif
uwsgi_error("socketpair()\n");
exit(1);
uwsgi_error("create_logpipe()/socketpair()\n");
exit(1);
}
fix_logpipe_buf(uwsgi.shared->worker_req_log_pipe);
}
uwsgi_socket_nb(uwsgi.shared->worker_req_log_pipe[0]);
@@ -287,6 +333,8 @@ void logto(char *logfile) {
void uwsgi_setup_log() {
uwsgi_setup_log_encoders();
if (uwsgi.daemonize) {
if (uwsgi.has_emperor) {
@@ -440,7 +488,6 @@ void uwsgi_logvar_add(struct wsgi_request *wsgi_req, char *key, uint8_t keylen,
void uwsgi_check_logrotate(void) {
char message[1024];
int need_rotation = 0;
int need_reopen = 0;
@@ -451,7 +498,7 @@ void uwsgi_check_logrotate(void) {
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
}
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
if (uwsgi.log_maxsize > 0 && (uint64_t) uwsgi.shared->logsize > uwsgi.log_maxsize) {
need_rotation = 1;
}
@@ -464,70 +511,81 @@ void uwsgi_check_logrotate(void) {
}
if (need_rotation) {
char *rot_name = uwsgi.log_backupname;
int need_free = 0;
if (rot_name == NULL) {
char *ts_str = uwsgi_num2str((int) uwsgi_now());
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
free(ts_str);
need_free = 1;
}
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
if (rename(uwsgi.logfile, rot_name) == 0) {
// reopen logfile dup'it and eventually gracefully reload workers;
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
else {
if (dup2(fd, uwsgi.original_log_fd) < 0) {
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
}
}
else {
uwsgi_error("unable to rotate log: rename()");
}
if (need_free)
free(rot_name);
uwsgi_log_rotate();
}
else if (need_reopen) {
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
// reopen logfile;
close(uwsgi.original_log_fd);
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
uwsgi_log_reopen();
}
}
void uwsgi_log_rotate() {
char message[1024];
if (!uwsgi.logfile) return;
char *rot_name = uwsgi.log_backupname;
int need_free = 0;
if (rot_name == NULL) {
char *ts_str = uwsgi_num2str((int) uwsgi_now());
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
free(ts_str);
need_free = 1;
}
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
if (rename(uwsgi.logfile, rot_name) == 0) {
// reopen logfile dup'it and eventually gracefully reload workers;
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
else {
if (dup2(fd, uwsgi.original_log_fd) < 0) {
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
}
}
else {
uwsgi_error("unable to rotate log: rename()");
}
if (need_free)
free(rot_name);
}
void uwsgi_log_reopen() {
char message[1024];
if (!uwsgi.logfile) return;
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
// reopen logfile;
close(uwsgi.original_log_fd);
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
}
void log_request(struct wsgi_request *wsgi_req) {
@@ -616,7 +674,7 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
break;
}
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, time_request, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, time_request);
@@ -922,6 +980,12 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 0;
}
}
// metric
else if (logchunk->type == 4) {
int64_t metric = uwsgi_metric_get(logchunk->ptr, NULL);
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = uwsgi_64bit2str(metric);
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = strlen(uwsgi.logvectors[wsgi_req->async_id][pos].iov_base);
}
if (uwsgi.logvectors[wsgi_req->async_id][pos].iov_len == 0 && logchunk->type != 0) {
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = (char *) empty_var;
@@ -1035,7 +1099,7 @@ static ssize_t uwsgi_lf_epoch(struct wsgi_request * wsgi_req, char **buf) {
static ssize_t uwsgi_lf_ctime(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_malloc(26);
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf);
@@ -1060,6 +1124,19 @@ static ssize_t uwsgi_lf_ltime(struct wsgi_request * wsgi_req, char **buf) {
return ret;
}
static ssize_t uwsgi_lf_ftime(struct wsgi_request * wsgi_req, char **buf) {
if (!uwsgi.log_strftime) {
return uwsgi_lf_ltime(wsgi_req, buf);
}
*buf = uwsgi_malloc(64);
time_t now = wsgi_req->start_of_request / 1000000;
size_t ret = strftime(*buf, 64, uwsgi.log_strftime, localtime(&now));
if (ret == 0) {
*buf[0] = 0;
return 0;
}
return ret;
}
static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
@@ -1160,6 +1237,7 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
1 -> offsetof variable
2 -> logvar
3 -> func
4 -> metric
*/
logchunk->type = variable;
@@ -1246,6 +1324,11 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->func = uwsgi_lf_ltime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ftime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ftime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ctime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ctime;
@@ -1321,6 +1404,11 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->func = uwsgi_lf_headers;
logchunk->free = 1;
}
else if (!uwsgi_starts_with(ptr, len, "metric.", 7)) {
logchunk->type = 4;
logchunk->ptr = uwsgi_concat2n(ptr+7, len - 7, "", 0);
logchunk->free = 1;
}
// logvar
else {
logchunk->type = 2;
@@ -1328,6 +1416,45 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
}
}
static void uwsgi_log_func_do(struct uwsgi_string_list *encoders, struct uwsgi_logger *ul, char *msg, size_t len) {
struct uwsgi_string_list *usl = encoders;
// note: msg must not be freed !!!
char *new_msg = msg;
size_t new_msg_len = len;
while(usl) {
struct uwsgi_log_encoder *ule = (struct uwsgi_log_encoder *) usl->custom_ptr;
if (ule->use_for) {
if (ul && ul->id) {
if (strcmp(ule->use_for, ul->id)) {
goto next;
}
}
else {
goto next;
}
}
size_t rlen = 0;
char *buf = ule->func(ule, new_msg, new_msg_len, &rlen);
if (new_msg != msg) {
free(new_msg);
}
new_msg = buf;
new_msg_len = rlen;
next:
usl = usl->next;
}
if (ul) {
ul->func(ul, new_msg, new_msg_len);
}
else {
new_msg_len = (size_t) write(uwsgi.original_log_fd, new_msg, new_msg_len);
}
if (new_msg != msg) {
free(new_msg);
}
}
int uwsgi_master_log(void) {
ssize_t rlen = read(uwsgi.shared->worker_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
@@ -1361,7 +1488,7 @@ int uwsgi_master_log(void) {
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);
uwsgi_log_func_do(uwsgi.requested_log_encoders, ul_route, uwsgi.log_master_buf, rlen);
finish = 1;
}
}
@@ -1379,14 +1506,14 @@ int uwsgi_master_log(void) {
if (ul->id) {
goto next;
}
ul->func(ul, uwsgi.log_master_buf, rlen);
uwsgi_log_func_do(uwsgi.requested_log_encoders, 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);
uwsgi_log_func_do(uwsgi.requested_log_encoders, NULL, uwsgi.log_master_buf, rlen);
}
return 0;
}
@@ -1405,7 +1532,7 @@ int uwsgi_master_req_log(void) {
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);
uwsgi_log_func_do(uwsgi.requested_log_req_encoders, ul_route, uwsgi.log_master_buf, rlen);
finish = 1;
}
}
@@ -1423,14 +1550,14 @@ int uwsgi_master_req_log(void) {
if (ul->id) {
goto next;
}
ul->func(ul, uwsgi.log_master_buf, rlen);
uwsgi_log_func_do(uwsgi.requested_log_req_encoders, 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);
uwsgi_log_func_do(uwsgi.requested_log_req_encoders, NULL, uwsgi.log_master_buf, rlen);
}
return 0;
}
@@ -1493,3 +1620,374 @@ void uwsgi_threaded_logger_spawn() {
}
}
void uwsgi_register_log_encoder(char *name, char *(*func)(struct uwsgi_log_encoder *, char *, size_t, size_t *)) {
struct uwsgi_log_encoder *old_ule = NULL, *ule = uwsgi.log_encoders;
while(ule) {
if (!strcmp(ule->name, name)) {
ule->func = func;
return;
}
old_ule = ule;
ule = ule->next;
}
ule = uwsgi_calloc(sizeof(struct uwsgi_log_encoder));
ule->name = name;
ule->func = func;
if (old_ule) {
old_ule->next = ule;
}
else {
uwsgi.log_encoders = ule;
}
}
struct uwsgi_log_encoder *uwsgi_log_encoder_by_name(char *name) {
struct uwsgi_log_encoder *ule = uwsgi.log_encoders;
while(ule) {
if (!strcmp(name, ule->name)) return ule;
ule = ule->next;
}
return NULL;
}
void uwsgi_setup_log_encoders() {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.requested_log_encoders) {
char *space = strchr(usl->value, ' ');
if (space) *space = 0;
char *use_for = strchr(usl->value, ':');
if (use_for) *use_for = 0;
struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
if (!ule) {
uwsgi_log("log encoder \"%s\" not found\n", usl->value);
exit(1);
}
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
if (use_for) {
ule2->use_for = uwsgi_str(use_for+1);
*use_for = ':';
}
// we use a copy
if (space) {
*space = ' ';
ule2->args = uwsgi_str(space+1);
}
else {
ule2->args = uwsgi_str("");
}
usl->custom_ptr = ule2;
uwsgi_log("[log-encoder] registered %s\n", usl->value);
}
uwsgi_foreach(usl, uwsgi.requested_log_req_encoders) {
char *space = strchr(usl->value, ' ');
if (space) *space = 0;
char *use_for = strchr(usl->value, ':');
if (use_for) *use_for = 0;
struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
if (!ule) {
uwsgi_log("log encoder \"%s\" not found\n", usl->value);
exit(1);
}
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
if (use_for) {
ule2->use_for = uwsgi_str(use_for+1);
*use_for = ':';
}
// we use a copy
if (space) {
*space = ' ';
ule2->args = uwsgi_str(space+1);
}
else {
ule2->args = uwsgi_str("");
}
usl->custom_ptr = ule2;
uwsgi_log("[log-req-encoder] registered %s\n", usl->value);
}
}
#ifdef UWSGI_ZLIB
static char *uwsgi_log_encoder_gzip(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
struct uwsgi_buffer *ub = uwsgi_gzip(msg, len);
if (!ub) return NULL;
*rlen = ub->pos;
// avoid destruction
char *buf = ub->buf;
ub->buf = NULL;
uwsgi_buffer_destroy(ub);
return buf;
}
static char *uwsgi_log_encoder_compress(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
size_t c_len = (size_t) compressBound(len);
uLongf destLen = c_len;
char *buf = uwsgi_malloc(c_len);
if (compress((Bytef *) buf, &destLen, (Bytef *)msg, (uLong) len) == Z_OK) {
*rlen = destLen;
return buf;
}
free(buf);
return NULL;
}
#endif
/*
really fast encoder adding only a prefix
*/
static char *uwsgi_log_encoder_prefix(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
char *buf = NULL;
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + strlen(ule->args));
if (uwsgi_buffer_append(ub, ule->args, strlen(ule->args))) goto end;
if (uwsgi_buffer_append(ub, msg, len)) goto end;
*rlen = ub->pos;
buf = ub->buf;
ub->buf = NULL;
end:
uwsgi_buffer_destroy(ub);
return buf;
}
/*
really fast encoder adding only a newline
*/
static char *uwsgi_log_encoder_nl(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
char *buf = NULL;
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + 1);
if (uwsgi_buffer_append(ub, msg, len)) goto end;
if (uwsgi_buffer_byte(ub, '\n')) goto end;
*rlen = ub->pos;
buf = ub->buf;
ub->buf = NULL;
end:
uwsgi_buffer_destroy(ub);
return buf;
}
/*
really fast encoder adding only a suffix
*/
static char *uwsgi_log_encoder_suffix(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
char *buf = NULL;
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + strlen(ule->args));
if (uwsgi_buffer_append(ub, msg, len)) goto end;
if (uwsgi_buffer_append(ub, ule->args, strlen(ule->args))) goto end;
*rlen = ub->pos;
buf = ub->buf;
ub->buf = NULL;
end:
uwsgi_buffer_destroy(ub);
return buf;
}
void uwsgi_log_encoder_parse_vars(struct uwsgi_log_encoder *ule) {
char *ptr = ule->args;
size_t remains = strlen(ptr);
char *base = ptr;
size_t base_len = 0;
char *var = NULL;
size_t var_len = 0;
int status = 0; // 1 -> $ 2-> { end -> }
while(remains--) {
char b = *ptr++;
if (status == 1) {
if (b == '{') {
status = 2;
continue;
}
base_len+=2;
status = 0;
continue;
}
else if (status == 2) {
if (b == '}') {
status = 0;
uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(base, base_len, "", 0));
struct uwsgi_string_list *usl = uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(var, var_len, "", 0));
usl->custom = 1;
var = NULL;
var_len = 0;
base = NULL;
base_len = 0;
continue;
}
if (!var) var = (ptr-1);
var_len++;
continue;
}
// status == 0
if (b == '$') {
status = 1;
}
else {
if (!base) base = (ptr-1);
base_len++;
}
}
if (base) {
if (status == 1) {
base_len+=2;
}
else if (status == 2) {
base_len+=3;
}
uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(base, base_len, "", 0));
}
}
/*
// format: foo ${var} bar
msg (the logline)
msgnl (the logline with newline)
unix (the time_t value)
micros (current microseconds)
strftime (strftime)
*/
static char *uwsgi_log_encoder_format(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
if (!ule->configured) {
uwsgi_log_encoder_parse_vars(ule);
ule->configured = 1;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(strlen(ule->args) + len);
struct uwsgi_string_list *usl = (struct uwsgi_string_list *) ule->data;
char *buf = NULL;
while(usl) {
if (usl->custom) {
if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
if (msg[len-1] == '\n') {
if (uwsgi_buffer_append(ub, msg, len-1)) goto end;
}
else {
if (uwsgi_buffer_append(ub, msg, len)) goto end;
}
}
else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
if (uwsgi_buffer_append(ub, msg, len)) goto end;
}
else if (!uwsgi_strncmp(usl->value, usl->len, "unix", 4)) {
if (uwsgi_buffer_num64(ub, uwsgi_now())) goto end;
}
else if (!uwsgi_strncmp(usl->value, usl->len, "micros", 6)) {
if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto end;
}
else if (!uwsgi_starts_with(usl->value, usl->len, "strftime:", 9)) {
char sftime[64];
time_t now = uwsgi_now();
char *buf = uwsgi_concat2n(usl->value+9, usl->len-9,"", 0);
int strftime_len = strftime(sftime, 64, buf, localtime(&now));
free(buf);
if (strftime_len > 0) {
if (uwsgi_buffer_append(ub, sftime, strftime_len)) goto end;
}
}
}
else {
if (uwsgi_buffer_append(ub, usl->value, usl->len)) goto end;
}
usl = usl->next;
}
buf = ub->buf;
*rlen = ub->pos;
ub->buf = NULL;
end:
uwsgi_buffer_destroy(ub);
return buf;
}
static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
if (!ule->configured) {
uwsgi_log_encoder_parse_vars(ule);
ule->configured = 1;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(strlen(ule->args) + len);
struct uwsgi_string_list *usl = (struct uwsgi_string_list *) ule->data;
char *buf = NULL;
while(usl) {
if (usl->custom) {
if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
size_t msg_len = len;
if (msg[len-1] == '\n') msg_len--;
char *e_json = uwsgi_malloc(msg_len * 2);
escape_json(msg, msg_len, e_json);
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
free(e_json);
goto end;
}
free(e_json);
}
else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
char *e_json = uwsgi_malloc(len * 2);
escape_json(msg, len, e_json);
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
free(e_json);
goto end;
}
free(e_json);
}
else if (!uwsgi_strncmp(usl->value, usl->len, "unix", 4)) {
if (uwsgi_buffer_num64(ub, uwsgi_now())) goto end;
}
else if (!uwsgi_strncmp(usl->value, usl->len, "micros", 6)) {
if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto end;
}
else if (!uwsgi_starts_with(usl->value, usl->len, "strftime:", 9)) {
char sftime[64];
time_t now = uwsgi_now();
char *buf = uwsgi_concat2n(usl->value+9, usl->len-9, "", 0);
int strftime_len = strftime(sftime, 64, buf, localtime(&now));
free(buf);
if (strftime_len > 0) {
char *e_json = uwsgi_malloc(strftime_len * 2);
escape_json(sftime, strftime_len, e_json);
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
free(e_json);
goto end;
}
free(e_json);
}
}
}
else {
if (uwsgi_buffer_append(ub, usl->value, usl->len)) goto end;
}
usl = usl->next;
}
buf = ub->buf;
*rlen = ub->pos;
ub->buf = NULL;
end:
uwsgi_buffer_destroy(ub);
return buf;
}
void uwsgi_log_encoders_register_embedded() {
uwsgi_register_log_encoder("prefix", uwsgi_log_encoder_prefix);
uwsgi_register_log_encoder("suffix", uwsgi_log_encoder_suffix);
uwsgi_register_log_encoder("nl", uwsgi_log_encoder_nl);
uwsgi_register_log_encoder("format", uwsgi_log_encoder_format);
uwsgi_register_log_encoder("json", uwsgi_log_encoder_json);
#ifdef UWSGI_ZLIB
uwsgi_register_log_encoder("gzip", uwsgi_log_encoder_gzip);
uwsgi_register_log_encoder("compress", uwsgi_log_encoder_compress);
#endif
}
+165 -79
View File
@@ -2,6 +2,32 @@
extern struct uwsgi_server uwsgi;
void uwsgi_update_load_counters() {
int i;
uint64_t busy_workers = 0;
uint64_t idle_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
if (uwsgi_worker_is_busy(i) == 0) {
idle_workers++;
}
else {
busy_workers++;
}
}
}
if (busy_workers >= (uint64_t) uwsgi.numproc) {
ushared->overloaded++;
}
ushared->busy_workers = busy_workers;
ushared->idle_workers = idle_workers;
}
void uwsgi_restore_auto_snapshot(int signum) {
if (uwsgi.workers[1].snapshot > 0) {
@@ -32,24 +58,25 @@ void uwsgi_unblock_signal(int signum) {
}
void uwsgi_master_manage_udp(int udp_fd) {
char buf[4096];
struct sockaddr_in udp_client;
char udp_client_addr[16];
int i;
socklen_t udp_len = sizeof(udp_client);
ssize_t rlen = recvfrom(udp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
ssize_t rlen = recvfrom(udp_fd, buf, 4096, 0, (struct sockaddr *) &udp_client, &udp_len);
if (rlen < 0) {
uwsgi_error("recvfrom()");
uwsgi_error("uwsgi_master_manage_udp()/recvfrom()");
}
else if (rlen > 0) {
memset(udp_client_addr, 0, 16);
if (inet_ntop(AF_INET, &udp_client.sin_addr.s_addr, udp_client_addr, 16)) {
if (uwsgi.wsgi_req->buffer[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
if (buf[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
}
else if (uwsgi.wsgi_req->buffer[0] == 0x30 && uwsgi.snmp) {
manage_snmp(udp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
else if (buf[0] == 0x30 && uwsgi.snmp) {
manage_snmp(udp_fd, (uint8_t *) buf, rlen, &udp_client);
}
else {
@@ -57,7 +84,7 @@ void uwsgi_master_manage_udp(int udp_fd) {
int udp_managed = 0;
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->manage_udp) {
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, uwsgi.wsgi_req->buffer, rlen)) {
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, buf, rlen)) {
udp_managed = 1;
break;
}
@@ -66,49 +93,17 @@ void uwsgi_master_manage_udp(int udp_fd) {
// else a simple udp logger
if (!udp_managed) {
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, uwsgi.wsgi_req->buffer);
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, buf);
}
}
}
else {
uwsgi_error("inet_ntop()");
uwsgi_error("uwsgi_master_manage_udp()/inet_ntop()");
}
}
}
void uwsgi_master_manage_emperor() {
char byte;
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
if (rlen > 0) {
uwsgi_log_verbose("received message %d from emperor\n", byte);
// remove me
if (byte == 0) {
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
}
// reload me
else if (byte == 1) {
// un-lazy the stack to trigger a real reload
uwsgi.lazy = 0;
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
}
}
else {
uwsgi_log("lost connection with my emperor !!!\n");
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
sleep(2);
exit(1);
}
}
void uwsgi_master_restore_snapshot() {
int i, waitpid_status;
uwsgi_log("[snapshot] restoring workers...\n");
@@ -222,8 +217,8 @@ int uwsgi_get_tcp_info(int fd) {
#elif defined(__FreeBSD__)
if (!uwsgi.shared->ti.__tcpi_sacked) {
#endif
return 0;
}
return 0;
}
#if defined(__linux__)
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.tcpi_unacked;
@@ -242,12 +237,12 @@ int uwsgi_get_tcp_info(int fd) {
uwsgi_error("write()");
}
else {
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long ) uwsgi.shared->load);
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->load);
}
}
}
if (uwsgi.shared->load >= uwsgi.shared->max_load) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long ) uwsgi.shared->load, (unsigned long long ) uwsgi.shared->max_load);
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long) uwsgi.shared->load, (unsigned long long) uwsgi.shared->max_load);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
@@ -306,7 +301,6 @@ int master_loop(char **argv, char **environ) {
struct uwsgi_rb_timer *min_timeout;
struct uwsgi_rbtree *rb_timers = uwsgi_init_rb_timer();
if (uwsgi.procname_master) {
uwsgi_set_processname(uwsgi.procname_master);
}
@@ -346,6 +340,11 @@ int master_loop(char **argv, char **environ) {
#endif
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]);
if (uwsgi.master_fifo) {
uwsgi.master_fifo_fd = uwsgi_master_fifo();
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
}
if (uwsgi.spoolers) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
}
@@ -374,6 +373,9 @@ int master_loop(char **argv, char **environ) {
#ifdef UWSGI_SSL
uwsgi_start_legions();
#endif
uwsgi_metrics_start_collector();
uwsgi_add_reload_fds();
uwsgi_cache_start_sweepers();
uwsgi_cache_start_sync_servers();
@@ -381,7 +383,18 @@ int master_loop(char **argv, char **environ) {
uwsgi.wsgi_req->buffer = uwsgi.workers[0].cores[0].buffer;
if (uwsgi.has_emperor) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
if (uwsgi.emperor_proxy) {
uwsgi.emperor_fd_proxy = bind_to_unix(uwsgi.emperor_proxy, uwsgi.listen_queue, 0, 0);
if (uwsgi.emperor_fd_proxy < 0) exit(1);
if (chmod(uwsgi.emperor_proxy, S_IRUSR|S_IWUSR)) {
uwsgi_error("[emperor-proxy] chmod()");
exit(1);
}
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd_proxy);
}
else {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
}
}
if (uwsgi.zerg_server) {
@@ -391,7 +404,7 @@ int master_loop(char **argv, char **environ) {
}
if (uwsgi.stats) {
char *tcp_port = strchr(uwsgi.stats, ':');
char *tcp_port = strrchr(uwsgi.stats, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
@@ -475,7 +488,7 @@ int master_loop(char **argv, char **environ) {
uwsgi_check_touches(uwsgi.touch_gracefully_stop);
// update exec touches
struct uwsgi_string_list *usl = uwsgi.touch_exec;
while(usl) {
while (usl) {
char *space = strchr(usl->value, ' ');
if (space) {
*space = 0;
@@ -485,6 +498,21 @@ int master_loop(char **argv, char **environ) {
usl = usl->next;
}
uwsgi_check_touches(uwsgi.touch_exec);
// update signal touches
usl = uwsgi.touch_signal;
while (usl) {
char *space = strchr(usl->value, ' ');
if (space) {
*space = 0;
usl->len = strlen(usl->value);
usl->custom_ptr = space + 1;
}
usl = usl->next;
}
uwsgi_check_touches(uwsgi.touch_signal);
// fsmon
uwsgi_fsmon_setup();
// setup cheaper algos (can be stacked)
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
@@ -583,8 +611,10 @@ int master_loop(char **argv, char **environ) {
/* all processes ok, doing status scan after N seconds */
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!check_interval)
if (!check_interval) {
check_interval = 1;
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = 1;
}
// add unregistered file monitors
@@ -619,14 +649,14 @@ int master_loop(char **argv, char **environ) {
if (ushared->rb_timers_cnt > 0) {
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->value - uwsgi_now();
if (check_interval <= 0) {
if (min_timeout) {
int delta = min_timeout->value - uwsgi_now();
if (delta <= 0) {
expire_rb_timeouts(rb_timers);
check_interval = 0;
}
// if the timer expires before the check_interval, override it
else if (delta < check_interval) {
check_interval = delta;
}
}
}
@@ -640,6 +670,9 @@ int master_loop(char **argv, char **environ) {
}
}
// update load counter
uwsgi_update_load_counters();
// check uwsgi-cron table
if (ushared->cron_cnt) {
@@ -680,12 +713,15 @@ int master_loop(char **argv, char **environ) {
uwsgi_master_check_idle();
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!check_interval)
if (!check_interval) {
check_interval = 1;
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = 1;
}
// get listen_queue status
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
int tmp_queue = 0;
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_INET) {
uwsgi_sock->queue = uwsgi_get_tcp_info(uwsgi_sock->fd);
@@ -697,8 +733,14 @@ int master_loop(char **argv, char **environ) {
}
#endif
#endif
if (uwsgi_sock->queue > tmp_queue) {
tmp_queue = uwsgi_sock->queue;
}
uwsgi_sock = uwsgi_sock->next;
}
// fix queue size on multiple sockets
uwsgi.shared->load = tmp_queue;
// check if some worker has to die (harakiri, evil checks...)
uwsgi_master_check_workers_deadline();
@@ -707,6 +749,7 @@ int master_loop(char **argv, char **environ) {
uwsgi_master_check_mules_deadline();
uwsgi_master_check_spoolers_deadline();
uwsgi_master_check_crons_deadline();
uwsgi_master_check_mountpoints();
#ifdef __linux__
#ifdef MADV_MERGEABLE
@@ -717,7 +760,7 @@ int master_loop(char **argv, char **environ) {
#endif
// resubscribe every 10 cycles by default
if (( (uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
if (((uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
uwsgi_subscribe_all(0, 0);
}
@@ -741,34 +784,34 @@ int master_loop(char **argv, char **environ) {
}
touched = uwsgi_check_touches(uwsgi.touch_workers_reload);
if (touched) {
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
uwsgi_block_signal(SIGHUP);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_curse(i, SIGHUP);
}
}
uwsgi_unblock_signal(SIGHUP);
continue;
}
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
uwsgi_reload_workers();
continue;
}
touched = uwsgi_check_touches(uwsgi.touch_chain_reload);
if (touched) {
if (uwsgi.status.chain_reloading == 0) {
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
uwsgi.status.chain_reloading = 1;
}
else {
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
}
}
// be sure to run it as the last touch check
touched = uwsgi_check_touches(uwsgi.touch_exec);
if (touched) {
if (uwsgi_run_command( touched , NULL, -1) >= 0) {
if (uwsgi_run_command(touched, NULL, -1) >= 0) {
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
}
}
touched = uwsgi_check_touches(uwsgi.touch_signal);
if (touched) {
uint8_t signum = atoi(touched);
uwsgi_route_signal(signum);
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
}
}
continue;
@@ -785,12 +828,18 @@ int master_loop(char **argv, char **environ) {
// reload gateways and daemons only on normal workflow (+outworld status)
if (!uwsgi_instance_is_reloading && !uwsgi_instance_is_dying) {
if (uwsgi_master_check_emperor_death(diedpid)) continue;
if (uwsgi_master_check_spoolers_death(diedpid)) continue;
if (uwsgi_master_check_mules_death(diedpid)) continue;
if (uwsgi_master_check_gateways_death(diedpid)) continue;
if (uwsgi_master_check_daemons_death(diedpid)) continue;
if (uwsgi_master_check_cron_death(diedpid)) continue;
if (uwsgi_master_check_emperor_death(diedpid))
continue;
if (uwsgi_master_check_spoolers_death(diedpid))
continue;
if (uwsgi_master_check_mules_death(diedpid))
continue;
if (uwsgi_master_check_gateways_death(diedpid))
continue;
if (uwsgi_master_check_daemons_death(diedpid))
continue;
if (uwsgi_master_check_cron_death(diedpid))
continue;
}
@@ -855,8 +904,9 @@ next:
// ok, if we are reloading or dying, just continue the master loop
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
if (!uwsgi.workers[thewid].cursed_at) uwsgi.workers[thewid].cursed_at = uwsgi_now();
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
if (!uwsgi.workers[thewid].cursed_at)
uwsgi.workers[thewid].cursed_at = uwsgi_now();
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now() - uwsgi.workers[thewid].cursed_at));
uwsgi.workers[thewid].cursed_at = 0;
continue;
}
@@ -875,6 +925,11 @@ next:
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
// noop
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_BRUTAL_RELOAD_CODE) {
uwsgi_log("!!! inconsistent state reported by worker %d (pid: %d) !!!\n", thewid, (int) diedpid);
reap_them_all(0);
continue;
}
else if (uwsgi.workers[thewid].manage_next_request) {
if (WIFSIGNALED(waitpid_status)) {
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
@@ -929,3 +984,34 @@ next:
// never here
}
void uwsgi_reload_workers() {
int i;
uwsgi_block_signal(SIGHUP);
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_curse(i, SIGHUP);
}
}
uwsgi_unblock_signal(SIGHUP);
}
void uwsgi_chain_reload() {
if (!uwsgi.status.chain_reloading) {
uwsgi_log_verbose("chain reload starting...\n");
uwsgi.status.chain_reloading = 1;
}
else {
uwsgi_log_verbose("chain reload already running...\n");
}
}
void uwsgi_brutally_reload_workers() {
int i;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_log_verbose("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
uwsgi_curse(i, SIGINT);
}
}
}
+35 -2
View File
@@ -35,11 +35,17 @@ int uwsgi_master_check_reload(char **argv) {
// check for chain reload
void uwsgi_master_check_chain() {
if (!uwsgi.status.chain_reloading) return;
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
int i;
int needed_procs = 0;
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0) {
needed_procs++;
}
}
if (uwsgi.status.chain_reloading > needed_procs) {
uwsgi.status.chain_reloading = 0;
uwsgi_log_verbose("chain reloading complete\n");
}
int i;
uwsgi_block_signal(SIGHUP);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
@@ -112,6 +118,9 @@ void uwsgi_master_check_idle() {
if (errno != ECHILD)
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
}
else {
uwsgi.workers[i].pid = 0;
}
}
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
@@ -197,6 +206,14 @@ void uwsgi_master_check_mules_deadline() {
uwsgi.mules[i].harakiri = 0;
}
}
// user harakiri
if (uwsgi.mules[i].user_harakiri > 0) {
if (uwsgi.mules[i].user_harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON MULE %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].pid);
kill(uwsgi.mules[i].pid, SIGKILL);
uwsgi.mules[i].user_harakiri = 0;
}
}
}
}
@@ -208,6 +225,11 @@ void uwsgi_master_check_spoolers_deadline() {
kill(uspool->pid, SIGKILL);
uspool->harakiri = 0;
}
if (uspool->user_harakiri > 0 && uspool->user_harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
kill(uspool->pid, SIGKILL);
uspool->user_harakiri = 0;
}
uspool = uspool->next;
}
}
@@ -303,3 +325,14 @@ void uwsgi_master_check_crons_deadline() {
}
}
void uwsgi_master_check_mountpoints() {
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.mountpoints_check) {
if (uwsgi_check_mountpoint(usl->value)) {
uwsgi_log_verbose("mountpoint %s failed, triggering detonation...\n", usl->value);
uwsgi_nuclear_blast();
//never here
exit(1);
}
}
}
+82
View File
@@ -18,6 +18,10 @@ int uwsgi_master_manage_events(int interesting_fd) {
}
}
if (uwsgi.master_fifo_fd > -1 && interesting_fd == uwsgi.master_fifo_fd) {
return uwsgi_master_fifo_manage(uwsgi.master_fifo_fd);
}
// stats server ?
if (uwsgi.stats && uwsgi.stats_fd > -1) {
if (interesting_fd == uwsgi.stats_fd) {
@@ -36,12 +40,90 @@ int uwsgi_master_manage_events(int interesting_fd) {
// emperor event ?
if (uwsgi.has_emperor) {
if (uwsgi.emperor_fd_proxy > -1 && interesting_fd == uwsgi.emperor_fd_proxy) {
uwsgi_master_manage_emperor_proxy();
return 0;
}
if (interesting_fd == uwsgi.emperor_fd) {
uwsgi_master_manage_emperor();
return 0;
}
}
if (uwsgi_fsmon_event(interesting_fd)) {
return 0;
}
// reload on fd
if (uwsgi.reload_on_fd) {
// custom -> fd
// custom2 -> len (optional, default 1)
// custom_ptr -> log message (optional)
struct uwsgi_string_list *usl = uwsgi.reload_on_fd;
while(usl) {
if (interesting_fd == (int) usl->custom) {
char stack_tmp[8];
char *tmp = stack_tmp;
if (usl->custom2 > 8) {
tmp = uwsgi_malloc(usl->custom2);
}
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
uwsgi_error("[reload-on-fd] read()");
}
if (usl->custom_ptr) {
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
}
else {
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
}
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
return 0;
}
usl = usl->next;
}
}
// brutal reload on fd
if (uwsgi.brutal_reload_on_fd) {
// custom -> fd
// custom2 -> len (optional, default 1)
// custom_ptr -> log message (optional)
struct uwsgi_string_list *usl = uwsgi.brutal_reload_on_fd;
while(usl) {
if (interesting_fd == (int) usl->custom) {
char stack_tmp[8];
char *tmp = stack_tmp;
if (usl->custom2 > 8) {
tmp = uwsgi_malloc(usl->custom2);
}
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
uwsgi_error("[brutal-reload-on-fd] read()");
}
if (usl->custom_ptr) {
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
}
else {
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
}
if (uwsgi.die_on_term) {
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
else {
uwsgi_block_signal(SIGTERM);
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
return 0;
}
usl = usl->next;
}
}
// wakeup from cheap mode ?
if (uwsgi.status.is_cheap) {
+228 -23
View File
@@ -115,7 +115,49 @@ int uwsgi_calc_cheaper(void) {
last_check = now;
int needed_workers = uwsgi.cheaper_algo();
int ignore_algo = 0;
int needed_workers = 0;
// first check if memory usage is not exceeded
if (uwsgi.cheaper_rss_limit_soft) {
unsigned long long total_rss = 0;
int i;
int active_workers = 0;
for(i=1;i<=uwsgi.numproc;i++) {
if (!uwsgi.workers[i].cheaped) {
total_rss += uwsgi.workers[i].rss_size;
active_workers++;
}
}
if (uwsgi.cheaper_rss_limit_hard && active_workers > 1 && total_rss >= uwsgi.cheaper_rss_limit_hard) {
uwsgi_log("cheaper hard rss memory limit exceeded, cheap one of %d workers\n", active_workers);
needed_workers = -1;
ignore_algo = 1;
}
else if (total_rss >= uwsgi.cheaper_rss_limit_soft) {
#ifdef UWSGI_DEBUG
uwsgi_log("cheaper soft rss memory limit exceeded, can't spawn more workers\n");
#endif
ignore_algo = 1;
}
}
// then check for fifo
if (uwsgi.cheaper_fifo_delta != 0) {
if (!ignore_algo) {
needed_workers = uwsgi.cheaper_fifo_delta;
ignore_algo = 1;
}
uwsgi.cheaper_fifo_delta = 0;
}
// if cheaper limits wants to change worker count, then skip cheaper algo
if (!needed_workers) needed_workers = uwsgi.cheaper_algo(!ignore_algo);
// safe check to verify if cheaper algo obeyed ignore_algo value
if (ignore_algo && needed_workers > 0) {
uwsgi_log("BUG! cheaper algo returned %d but it cannot spawn any worker at this time!\n", needed_workers);
needed_workers = 0;
}
if (needed_workers > 0) {
for (i = 1; i <= uwsgi.numproc; i++) {
@@ -152,6 +194,11 @@ int uwsgi_calc_cheaper(void) {
return 1;
}
// fake algo to allow control with the fifo
int uwsgi_cheaper_algo_manual(int can_spawn) {
return 0;
}
/*
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
@@ -187,7 +234,7 @@ int uwsgi_calc_cheaper(void) {
*/
int uwsgi_cheaper_algo_spare(void) {
int uwsgi_cheaper_algo_spare(int can_spawn) {
int i;
static uint64_t overload_count = 0;
@@ -211,7 +258,7 @@ int uwsgi_cheaper_algo_spare(void) {
healthy:
// are we overloaded ?
if (overload_count > uwsgi.cheaper_overload) {
if (can_spawn && overload_count > uwsgi.cheaper_overload) {
#ifdef UWSGI_DEBUG
uwsgi_log("overloaded !!!\n");
@@ -279,7 +326,7 @@ healthy:
*/
int uwsgi_cheaper_algo_backlog(void) {
int uwsgi_cheaper_algo_backlog(int can_spawn) {
int i;
#ifdef __linux__
@@ -288,7 +335,7 @@ int uwsgi_cheaper_algo_backlog(void) {
int backlog = 0;
#endif
if (backlog > (int) uwsgi.cheaper_overload) {
if (can_spawn && backlog > (int) uwsgi.cheaper_overload) {
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
@@ -326,23 +373,30 @@ void uwsgi_reload(char **argv) {
int i;
int waitpid_status;
// 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++) {
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
if (!uwsgi.master_is_reforked) {
// 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++) {
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
// call master cleanup hooks
uwsgi_master_cleanup_hooks();
// call atexit user exec
uwsgi_exec_atexit();
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
}
uwsgi_log("binary reloading uWSGI...\n");
}
else {
uwsgi_log("fork()'ing uWSGI...\n");
}
// call master cleanup hooks
uwsgi_master_cleanup_hooks();
// call atexit user exec
uwsgi_exec_atexit();
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
}
uwsgi_log("binary reloading uWSGI...\n");
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
if (chdir(uwsgi.cwd)) {
uwsgi_error("chdir()");
@@ -529,6 +583,7 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
}
}
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
}
@@ -696,8 +751,17 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
while (ud) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyval_comma(us, "cmd", ud->command))
// allocate 2x the size of original command
// in case we need to escape all chars
char *cmd = uwsgi_malloc(strlen(ud->command)*2);
escape_json(ud->command, strlen(ud->command), cmd);
if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
free(cmd);
goto end;
}
free(cmd);
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) (ud->pid < 0) ? 0 : ud->pid))
goto end;
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns))
@@ -807,6 +871,65 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
}
if (uwsgi.has_metrics) {
if (uwsgi_stats_key(us, "metrics"))
goto end;
if (uwsgi_stats_object_open(us))
goto end;
uwsgi_rlock(uwsgi.metrics_lock);
struct uwsgi_metric *um = uwsgi.metrics;
while(um) {
int64_t um_val = *um->value;
if (uwsgi_stats_key(us, um->name)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_object_open(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_keylong(us, "type", (long long) um->type)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_comma(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_keyslong(us, "value", (long long) um_val)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_object_close(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
um = um->next;
if (um) {
if (uwsgi_stats_comma(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
}
}
uwsgi_rwunlock(uwsgi.metrics_lock);
if (uwsgi_stats_object_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
}
if (uwsgi_stats_key(us, "sockets"))
goto end;
@@ -1106,8 +1229,13 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
goto end;
if (uwsgi_stats_keyval_comma(us, "command", ucron->command))
char *cmd = uwsgi_malloc(strlen(ucron->command)*2);
escape_json(ucron->command, strlen(ucron->command), cmd);
if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
free(cmd);
goto end;
}
free(cmd);
if (uwsgi_stats_keylong_comma(us, "unique", (unsigned long long) ucron->unique))
goto end;
@@ -1282,7 +1410,7 @@ end:
return NULL;
}
void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
void uwsgi_register_cheaper_algo(char *name, int (*func) (int)) {
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
@@ -1444,3 +1572,80 @@ int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int
}
static void add_reload_fds(struct uwsgi_string_list *list, char *type) {
struct uwsgi_string_list *usl = list;
while(usl) {
char *strc = uwsgi_str(usl->value);
char *space = strchr(strc, ' ');
if (space) {
*space = 0;
usl->custom_ptr = space+1;
}
char *colon = strchr(strc, ':');
if (colon) {
*colon = 0;
usl->custom2 = strtoul(colon+1, NULL, 10);
}
usl->custom = strtoul(strc, NULL, 10);
if (!usl->custom2) usl->custom2 = 1;
event_queue_add_fd_read(uwsgi.master_queue, usl->custom);
uwsgi_add_safe_fd(usl->custom);
uwsgi_log("added %s reload monitor for fd %d (read size: %llu)\n", type, (int) usl->custom, usl->custom2);
usl = usl->next;
}
}
void uwsgi_add_reload_fds() {
add_reload_fds(uwsgi.reload_on_fd, "graceful");
add_reload_fds(uwsgi.brutal_reload_on_fd, "brutal");
}
void uwsgi_refork_master() {
pid_t pid = fork();
if (pid < 0) {
uwsgi_error("uwsgi_refork_master()/fork()");
return;
}
if (pid > 0) {
uwsgi_log_verbose("new master copy spawned with pid %d\n", (int) pid);
return;
}
// detach from the old master
setsid();
uwsgi.master_is_reforked = 1;
uwsgi_reload(uwsgi.argv);
// never here
exit(1);
}
void uwsgi_cheaper_increase() {
uwsgi.cheaper_fifo_delta++;
}
void uwsgi_cheaper_decrease() {
uwsgi.cheaper_fifo_delta--;
}
void uwsgi_go_cheap() {
int i;
int waitpid_status;
if (uwsgi.status.is_cheap) return;
uwsgi_log_verbose("going cheap...\n");
uwsgi.status.is_cheap = 1;
for (i = 1; i <= uwsgi.numproc; i++) {
uwsgi.workers[i].cheaped = 1;
if (uwsgi.workers[i].pid == 0)
continue;
uwsgi_log("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
if (errno != ECHILD)
uwsgi_error("uwsgi_go_cheap()/waitpid()");
}
}
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
}
+913 -63
View File
File diff suppressed because it is too large Load Diff
+254
View File
@@ -0,0 +1,254 @@
#include <uwsgi.h>
/*
jail systems (Linux namespaces, FreeBSD jails...) heavily rely on mount/umount
to simplify setups (expecially because the mount command could not be available in
the initial phase of jailing, we need an api to mount/umount filesystems
int uwsgi_mount(char *fs, char *what, char *where, int flags);
int uwsgi_umount(char *where, int flags);
*/
#ifdef __linux__
#ifndef MS_REC
#define MS_REC 16384
#endif
#include <sys/statfs.h>
#endif
struct uwsgi_mount_flag {
char *key;
uint64_t value;
};
static struct uwsgi_mount_flag umflags[] = {
#ifdef MS_BIND
{"bind", MS_BIND},
#endif
#ifdef MS_DIRSYNC
{"dirsync", MS_DIRSYNC},
#endif
#ifdef MS_MANDLOCK
{"mandlock", MS_MANDLOCK},
#endif
#ifdef MS_MOVE
{"move", MS_MOVE},
#endif
#ifdef MS_NOATIME
{"noatime", MS_NOATIME},
#endif
#ifdef MS_NODEV
{"nodev", MS_NODEV},
#endif
#ifdef MS_NOEXEC
{"noexec", MS_NOEXEC},
#endif
#ifdef MS_RDONLY
{"rdonly", MS_RDONLY},
{"readonly", MS_RDONLY},
{"ro", MS_RDONLY},
#endif
#ifdef MS_REMOUNT
{"remount", MS_REMOUNT},
#endif
#ifdef MS_SYNCHRONOUS
{"sync", MS_SYNCHRONOUS},
#endif
#ifdef MNT_FORCE
{"force", MNT_FORCE},
#endif
#ifdef MNT_DETACH
{"detach", MNT_DETACH},
#endif
#ifdef MS_REC
{"rec", MS_REC},
{"recursive", MS_REC},
#endif
#ifdef MS_PRIVATE
{"private", MS_PRIVATE},
#endif
#ifdef MS_SHARED
{"shared", MS_SHARED},
#endif
#ifdef MNT_RDONLY
{"rdonly", MNT_RDONLY},
{"readonly", MNT_RDONLY},
{"ro", MNT_RDONLY},
#endif
#ifdef MNT_NOEXEC
{"noexec", MNT_NOEXEC},
#endif
#ifdef MNT_NOSUID
{"nosuid", MNT_NOSUID},
#endif
#ifdef MNT_NOATIME
{"noatime", MNT_NOATIME},
#endif
#ifdef MNT_SNAPSHOT
{"snapshot", MNT_SNAPSHOT},
#endif
{NULL, 0},
};
uint64_t uwsgi_mount_flag(char *mflag) {
struct uwsgi_mount_flag *umf = umflags;
while(umf->key) {
if (!strcmp(umf->key, mflag)) return umf->value;
umf++;
}
return 0;
}
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
struct iovec iov[6];
#endif
unsigned long mountflags = 0;
if (!flags) goto parsed;
char *mflags = uwsgi_str(flags);
char *p, *ctx = NULL;
uwsgi_foreach_token(mflags, ",", p, ctx) {
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
if (!flag) {
uwsgi_log("unknown mount flag \"%s\"\n", p);
exit(1);
}
mountflags |= flag;
}
free(mflags);
parsed:
#ifdef __linux__
return mount(what, where, fs, mountflags, NULL);
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
iov[0].iov_base = "fstype";
iov[0].iov_len = 7;
iov[1].iov_base = fs;
iov[1].iov_len = strlen(fs) + 1;
iov[2].iov_base = "fspath";
iov[2].iov_len = 7;
iov[3].iov_base = where;
iov[3].iov_len = strlen(where) + 1;
iov[4].iov_base = "target";
iov[4].iov_len = 7;
iov[5].iov_base = what;
iov[5].iov_len = strlen(what) + 1;
return nmount(iov, 6, (int) mountflags);
#endif
return -1;
}
int uwsgi_umount(char *where, char *flags) {
unsigned long mountflags = 0;
if (!flags) goto parsed;
char *mflags = uwsgi_str(flags);
char *p, *ctx = NULL;
uwsgi_foreach_token(mflags, ",", p, ctx) {
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
if (!flag) {
uwsgi_log("unknown umount flag \"%s\"\n", p);
exit(1);
}
mountflags |= flag;
}
free(mflags);
parsed:
#ifdef __linux__
// we need a special case for recursive umount
if (mountflags & MS_REC) {
mountflags &= ~MS_REC;
int unmounted = 1;
char *slashed = uwsgi_concat2(where, "/");
while (unmounted) {
unmounted = 0;
FILE *procmounts = fopen("/proc/self/mounts", "r");
if (!procmounts) {
uwsgi_log("the /proc filesystem must be mounted for recursive umount\n");
uwsgi_error("open()");
exit(1);
}
char line[1024];
while (fgets(line, 1024, procmounts) != NULL) {
char *delim0 = strchr(line, ' ');
if (!delim0) continue;
delim0++;
char *delim1 = strchr(delim0, ' ');
if (!delim1) continue;
*delim1 = 0;
if (!uwsgi_starts_with(delim0, strlen(delim0), slashed, strlen(slashed))) goto unmountable;
continue;
unmountable:
if (!umount2(delim0, mountflags)) unmounted++;
}
fclose(procmounts);
}
free(slashed);
}
return umount2(where, mountflags);
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
return unmount(where, mountflags);
#endif
return -1;
}
int uwsgi_mount_hook(char *arg) {
char *tmp_arg = uwsgi_str(arg);
char *fs = tmp_arg;
char *what = strchr(fs, ' ');
if (!what) goto error;
*what = 0; what++;
char *where = strchr(what, ' ');
if (!where) goto error;
*where = 0; where++;
char *flags = strchr(where, ' ');
if (flags) {
*flags = 0; flags++;
}
if (uwsgi_mount(fs, what, where, flags)) {
uwsgi_error("uwsgi_mount()");
free(tmp_arg);
return -1;
}
free(tmp_arg);
return 0;
error:
free(tmp_arg);
uwsgi_log("uwsgi_mount_hook() invalid syntax\n");
return -1;
}
int uwsgi_umount_hook(char *arg) {
char *tmp_arg = uwsgi_str(arg);
char *where = tmp_arg;
char *flags = strchr(where, ' ');
if (flags) {
*flags = 0; flags++;
}
if (uwsgi_umount(where, flags)) {
uwsgi_error("uwsgi_umount()");
free(tmp_arg);
return -1;
}
free(tmp_arg);
return 0;
}
int uwsgi_check_mountpoint(char *mountpoint) {
#ifdef __linux__
struct statfs sfs;
int ret = statfs(mountpoint, &sfs);
if (ret) {
uwsgi_error("uwsgi_check_mountpoint()/statfs()");
return -1;
}
return 0;
#else
uwsgi_log("this platform does not support mountpoints check !!!\n");
return -1;
#endif
}
+2 -4
View File
@@ -453,8 +453,8 @@ void uwsgi_setup_mules_and_farms() {
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
char *p = strtok(mules_list, ",");
while (p != NULL) {
char *p, *ctx = NULL;
uwsgi_foreach_token(mules_list, ",", p, ctx) {
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
if (!um) {
uwsgi_log("invalid mule id: %s\n", p);
@@ -462,8 +462,6 @@ void uwsgi_setup_mules_and_farms() {
}
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);
+94 -4
View File
@@ -58,6 +58,22 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
return 0;
}
/*
pipe offload engine:
fd -> the file descriptor to read from
len -> amount of data to transfer
*/
static int u_offload_pipe_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (uor->fd < 0 || !uor->len) {
return -1;
}
return 0;
}
/*
memory offload engine:
@@ -66,7 +82,7 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
*/
int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
static int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->buf || !uor->len) {
return -1;
@@ -83,7 +99,7 @@ int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload
*/
int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
static int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->name) {
return -1;
@@ -307,7 +323,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
if (event_queue_add_fd_write(ut->queue, uor->fd2)) return -1;
return 0;
}
#if defined(__linux__) || defined(__sun__)
#if defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
if (len > 0) {
uor->written += len;
@@ -329,7 +345,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
uwsgi_offload_retry
uwsgi_error("u_offload_sendfile_do()");
}
#elif defined(__APPLE__)
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
off_t len = 0;
int ret = sendfile(uor->fd, uor->fd2, uor->pos, &len, NULL, 0);
// transfer finished
@@ -343,6 +359,71 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
}
/*
pipe offloading
status:
0 -> waiting for data on fd
1 -> waiting for write to s
*/
static int u_offload_pipe_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
ssize_t rlen;
// setup
if (fd == -1) {
event_queue_add_fd_read(ut->queue, uor->fd);
return 0;
}
switch(uor->status) {
// read event from fd
case 0:
if (!uor->buf) {
uor->buf = uwsgi_malloc(4096);
}
rlen = read(uor->fd, uor->buf, 4096);
if (rlen > 0) {
uor->to_write = rlen;
uor->pos = 0;
if (event_queue_del_fd(ut->queue, uor->fd, event_queue_read())) return -1;
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
uor->status = 1;
return 0;
}
if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_pipe_do() -> read()");
}
return -1;
// write event on s
case 1:
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_del_fd(ut->queue, uor->s, event_queue_write())) return -1;
if (event_queue_add_fd_read(ut->queue, uor->fd)) return -1;
uor->status = 0;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_pipe_do() -> write()");
}
return -1;
default:
break;
}
return -1;
}
/*
the offload task starts soon after the call to connect()
@@ -541,6 +622,7 @@ void uwsgi_offload_engines_register_all() {
uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do);
uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do);
uwsgi.offload_engine_memory = uwsgi_offload_register_engine("memory", u_offload_memory_prepare, u_offload_memory_do);
uwsgi.offload_engine_pipe = uwsgi_offload_register_engine("pipe", u_offload_pipe_prepare, u_offload_pipe_do);
}
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
@@ -566,3 +648,11 @@ int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, si
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
int uwsgi_offload_request_pipe_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_pipe, &uor, wsgi_req, 1);
uor.fd = fd;
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
+27 -6
View File
@@ -14,7 +14,9 @@ static void uwsgi_plugin_parse_section(char *filename) {
if (equal) {
*equal = 0;
if (!strcmp(p, "requires")) {
uwsgi_load_plugin(-1, equal + 1, NULL);
if (!plugin_already_loaded(equal+1)) {
uwsgi_load_plugin(-1, equal + 1, NULL);
}
}
}
p = strtok_r(NULL, "\n", &ctx);
@@ -24,7 +26,7 @@ static void uwsgi_plugin_parse_section(char *filename) {
}
#endif
int plugin_already_loaded(const char *plugin) {
struct uwsgi_plugin *uwsgi_plugin_get(const char *plugin) {
int i;
for (i = 0; i < 256; i++) {
@@ -33,7 +35,7 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
if (uwsgi.p[i]->alias) {
@@ -41,7 +43,7 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
}
@@ -53,7 +55,7 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
if (uwsgi.gp[i]->alias) {
@@ -61,14 +63,21 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
}
return NULL;
}
int plugin_already_loaded(const char *plugin) {
struct uwsgi_plugin *up = uwsgi_plugin_get(plugin);
if (up) return 1;
return 0;
}
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
void *plugin_handle = NULL;
@@ -91,6 +100,12 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
colon[0] = ':';
}
char *init_func = strchr(plugin_name, '|');
if (init_func) {
init_func[0] = 0;
init_func++;
}
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
need_free = 1;
@@ -150,6 +165,12 @@ success:
uwsgi_log("!!! UNABLE to load uWSGI plugin: %s !!!\n", dlerror());
}
else {
if (init_func) {
void (*plugin_init_func)() = dlsym(plugin_handle, init_func);
if (plugin_init_func) {
plugin_init_func();
}
}
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) {
+1 -1
View File
@@ -57,7 +57,7 @@ void uwsgi_init_queue() {
uwsgi.queue_header->pos = 0;
uwsgi.queue_header->pull_pos = 0;
}
if (!uwsgi.queue) {
if (uwsgi.queue == MAP_FAILED) {
uwsgi_error("mmap()");
exit(1);
}
+4 -2
View File
@@ -389,6 +389,8 @@ wait:
remains -= len;
*rlen += len;
continue;
}else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
*rlen = -1;
if (len == 0) {
@@ -478,9 +480,9 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
int upload_progress_fd = -1;
char *upload_progress_filename = NULL;
wsgi_req->post_file = tmpfile();
wsgi_req->post_file = uwsgi_tmpfile();
if (!wsgi_req->post_file) {
uwsgi_error("uwsgi_postbuffer_do_in_disk()/tmpfile()");
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
return -1;
}
+234 -5
View File
@@ -180,6 +180,10 @@ int uwsgi_apply_routes_do(struct uwsgi_route *routes, struct wsgi_request *wsgi_
r_goto = &wsgi_req->error_route_goto;
r_pc = &wsgi_req->error_route_pc;
}
else if (routes == uwsgi.response_routes) {
r_goto = &wsgi_req->response_route_goto;
r_pc = &wsgi_req->response_route_pc;
}
else if (routes == uwsgi.final_routes) {
r_goto = &wsgi_req->final_route_goto;
r_pc = &wsgi_req->final_route_pc;
@@ -306,6 +310,20 @@ int uwsgi_apply_error_routes(struct wsgi_request *wsgi_req) {
return uwsgi_apply_routes_do(uwsgi.error_routes, wsgi_req, NULL, 0);
}
int uwsgi_apply_response_routes(struct wsgi_request *wsgi_req) {
if (!uwsgi.response_routes) return 0;
if (wsgi_req->response_routes_applied) return 0;
// do not forget to check it !!!
if (wsgi_req->is_response_routing) return 0;
wsgi_req->is_response_routing = 1;
int ret = uwsgi_apply_routes_do(uwsgi.response_routes, wsgi_req, NULL, 0);
wsgi_req->response_routes_applied = 1;
return ret;
}
static void *uwsgi_route_get_condition_func(char *name) {
struct uwsgi_route_condition *urc = uwsgi.route_conditions;
@@ -337,6 +355,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
ur = uwsgi.error_routes;
}
else if (!uwsgi_starts_with(opt, strlen(opt), "response", 8)) {
ur = uwsgi.response_routes;
}
uint64_t pos = 0;
while(ur) {
old_ur = ur;
@@ -354,6 +375,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
uwsgi.error_routes = ur;
}
else if (!uwsgi_starts_with(opt, strlen(opt), "response", 8)) {
uwsgi.response_routes = ur;
}
else {
uwsgi.routes = ur;
}
@@ -564,7 +588,7 @@ static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsg
if (route->custom > 0) {
set_user_harakiri(route->custom);
}
return UWSGI_ROUTE_CONTINUE;
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_harakiri(struct uwsgi_route *ur, char *arg) {
@@ -616,7 +640,6 @@ static int uwsgi_router_fixcl(struct uwsgi_route *ur, char *arg) {
return 0;
}
// log route
static int uwsgi_router_log_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -701,6 +724,11 @@ static int uwsgi_router_goto_func(struct wsgi_request *wsgi_req, struct uwsgi_ro
r_goto = &wsgi_req->final_route_goto;
r_pc = &wsgi_req->final_route_pc;
}
else if (wsgi_req->is_response_routing) {
routes = uwsgi.response_routes;
r_goto = &wsgi_req->response_route_goto;
r_pc = &wsgi_req->response_route_pc;
}
while(routes) {
if (!routes->label) goto next;
if (!uwsgi_strncmp(routes->label, routes->label_len, ub->buf, ub->pos)) {
@@ -806,6 +834,31 @@ static int uwsgi_router_remheader(struct uwsgi_route *ur, char *arg) {
return 0;
}
// clearheaders route
static int uwsgi_router_clearheaders_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
if (uwsgi_response_prepare_headers(wsgi_req, ub->buf, ub->pos)) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_clearheaders(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_clearheaders_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// signal route
@@ -889,6 +942,126 @@ static int uwsgi_router_setscriptname(struct uwsgi_route *ur, char *arg) {
return 0;
}
// setmethod route
static int uwsgi_router_setmethod_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "REQUEST_METHOD", 14, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->method = ptr;
wsgi_req->method_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setmethod(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setmethod_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// seturi route
static int uwsgi_router_seturi_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "REQUEST_URI", 11, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->uri = ptr;
wsgi_req->uri_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_seturi(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_seturi_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setdocroot route
static int uwsgi_router_setdocroot_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "DOCUMENT_ROOT", 13, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->document_root = ptr;
wsgi_req->document_root_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setdocroot(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setdocroot_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setpathinfo route
static int uwsgi_router_setpathinfo_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "PATH_INFO", 9, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->path_info = ptr;
wsgi_req->path_info_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setpathinfo(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setpathinfo_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setscheme route
static int uwsgi_router_setscheme_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_SCHEME", 12, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->scheme = ptr;
wsgi_req->scheme_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setscheme(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setscheme_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setuser route
static int uwsgi_router_setuser_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -1025,10 +1198,21 @@ static int uwsgi_router_alarm(struct uwsgi_route *ur, char *arg) {
// send route
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
uwsgi_response_write_body_do(wsgi_req, route->data, route->data_len);
char **subject = (char **) (((char *)(wsgi_req))+route->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+route->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, route, *subject, *subject_len, route->data, route->data_len);
if (!ub) {
return UWSGI_ROUTE_BREAK;
}
if (route->custom) {
uwsgi_response_write_body_do(wsgi_req, "\r\n", 2);
if (uwsgi_buffer_append(ub, "\r\n", 2)) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
}
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_send(struct uwsgi_route *ur, char *arg) {
@@ -1389,6 +1573,11 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
*vallen = strlen(ret);
}
else if (!uwsgi_strncmp(key, keylen, "lq", 2)) {
ret = uwsgi_num2str(uwsgi.shared->load);
*vallen = strlen(ret);
}
return ret;
}
@@ -1505,6 +1694,8 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("addheader", uwsgi_router_addheader);
uwsgi_register_router("delheader", uwsgi_router_remheader);
uwsgi_register_router("remheader", uwsgi_router_remheader);
uwsgi_register_router("clearheaders", uwsgi_router_clearheaders);
uwsgi_register_router("resetheaders", uwsgi_router_clearheaders);
uwsgi_register_router("signal", uwsgi_router_signal);
uwsgi_register_router("send", uwsgi_router_send);
uwsgi_register_router("send-crnl", uwsgi_router_send_crnl);
@@ -1514,6 +1705,11 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("sethome", uwsgi_router_sethome);
uwsgi_register_router("setfile", uwsgi_router_setfile);
uwsgi_register_router("setscriptname", uwsgi_router_setscriptname);
uwsgi_register_router("setmethod", uwsgi_router_setmethod);
uwsgi_register_router("seturi", uwsgi_router_seturi);
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
uwsgi_register_router("setdocroot", uwsgi_router_setdocroot);
uwsgi_register_router("setscheme", uwsgi_router_setscheme);
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
uwsgi_register_router("alarm", uwsgi_router_alarm);
@@ -1620,6 +1816,7 @@ struct uwsgi_route_condition *uwsgi_register_route_condition(char *name, int (*f
}
void uwsgi_routing_dump() {
struct uwsgi_string_list *usl = NULL;
struct uwsgi_route *routes = uwsgi.routes;
if (!routes) goto next;
uwsgi_log("*** dumping internal routing table ***\n");
@@ -1654,8 +1851,25 @@ next:
}
uwsgi_log("*** end of the internal error routing table ***\n");
next2:
routes = uwsgi.response_routes;
if (!routes) goto next3;
uwsgi_log("*** dumping internal response routing table ***\n");
while(routes) {
if (routes->label) {
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
}
else if (!routes->subject_str && !routes->if_func) {
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
}
else {
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
}
routes = routes->next;
}
uwsgi_log("*** end of the internal response routing table ***\n");
next3:
routes = uwsgi.final_routes;
if (!routes) return;
if (!routes) goto next4;
uwsgi_log("*** dumping internal final routing table ***\n");
while(routes) {
if (routes->label) {
@@ -1670,5 +1884,20 @@ next2:
routes = routes->next;
}
uwsgi_log("*** end of the internal final routing table ***\n");
next4:
uwsgi_foreach(usl, uwsgi.collect_headers) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid collect header syntax, must be <header> <var>\n");
exit(1);
}
*space = 0;
usl->custom = strlen(usl->value);
*space = ' ';
usl->custom_ptr = space+1;
usl->custom2 = strlen(space+1);
uwsgi_log("collecting header %.*s to var %s\n", usl->custom, usl->value, usl->custom_ptr);
}
}
#endif
+48 -8
View File
@@ -4,26 +4,30 @@ extern struct uwsgi_server uwsgi;
// sendfile() abstraction
ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
// for platform not supporting sendfile we need to rely on boring read/write
// generally that platforms have very low memory, so use a 8k buffer
char buf[8192];
if (uwsgi.disable_sendfile) goto no_sendfile;
#if defined(__FreeBSD__) || defined(__DragonFly__)
off_t sf_len = len;
int sf_ret = sendfile(filefd, sockfd, pos, len, NULL, &sf_len, 0);
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
return -1;
#elif defined(__APPLE__)
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
off_t sf_len = len;
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
return -1;
#elif defined(__linux__) || defined(__sun__)
#elif defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
off_t off = pos;
return sendfile(sockfd, filefd, &off, len);
#else
// for platform not supporting sendfile we need to rely on boring read/write
// generally that platforms have very low memory, so use a 8k buffer
char buf[8192];
#endif
no_sendfile:
if (pos > 0) {
if (lseek(filefd, pos, SEEK_SET)) {
if (lseek(filefd, pos, SEEK_SET) < 0) {
uwsgi_error("uwsgi_sendfile_do()/seek()");
return -1;
}
@@ -34,6 +38,42 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
return -1;
}
return write(sockfd, buf, rlen);
#endif
}
/*
simple non blocking sendfile implementation
(generally used as fallback)
*/
int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
wsgi_req->write_pos = 0;
for(;;) {
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_simple_sendfile()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) {
wsgi_req->write_errors++;
return -1;
}
if (ret == 0) {
uwsgi_log("uwsgi_simple_sendfile() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
return 0;
}
+2
View File
@@ -301,8 +301,10 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
else {
uwsgi_error("uwsgi_signal_send()");
}
uwsgi.shared->unrouted_signals++;
return -1;
}
uwsgi.shared->routed_signals++;
return 0;
}
+55 -14
View File
@@ -23,6 +23,7 @@ static uint64_t get_uwsgi_custom_snmp_value(uint64_t, uint8_t *);
static uint8_t snmp_int_to_snmp(uint64_t, uint8_t, uint8_t *);
static ssize_t build_snmp_response(uint8_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
static ssize_t build_snmp_metric_response(int64_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_addr) {
@@ -71,7 +72,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
uwsgi_debug("SNMP version: %d\n", version);
#endif
// check for community string (this must be set from the python vm using uwsgi.snmp_community or with --snmp-community arg)
// check for community string (this must be set from the api using uwsgi.snmp_community or with --snmp-community arg)
if (*ptr != SNMP_STRING)
return;
ptr++;
@@ -196,7 +197,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
ptr++;
oidlen = *ptr;
if (oidlen != 11)
if (oidlen < 11)
return;
ptr++;
@@ -208,21 +209,33 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
oid_part[0] = *ptr;
if (oid_part[0] != 1 && oid_part[0] != 2)
return;
ptr++;
// old style SNMP metrics
if (oid_part[0] == 1 || oid_part[0] == 2) {
ptr++;
oid_part[1] = *ptr;
if (oid_part[1] < 1 || oid_part[1] > 100)
return;
ptr++;
oid_part[1] = *ptr;
if (oid_part[1] < 1 || oid_part[1] > 100)
return;
ptr++;
// check for null
if (memcmp((char *) ptr, "\x05\x00", 2))
return;
ptr += 2;
// check for null
if (memcmp((char *) ptr, "\x05\x00", 2))
return;
ptr += 2;
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
}
// metrics subsystem
else {
size_t metric_asn_len = oidlen - 9;
char *metric_asn = (char *) ptr;
struct uwsgi_metric *um = uwsgi_metric_find_by_asn(metric_asn, metric_asn_len);
if (!um) return;
uwsgi_rlock(uwsgi.metrics_lock);
int64_t value = *um->value;
uwsgi_rwunlock(uwsgi.metrics_lock);
size = build_snmp_metric_response(value, um->type, buffer, size, seq1, seq2, seq3);
}
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
if (size > 0) {
if (sendto(fd, buffer, size, 0, (struct sockaddr *) client_addr, sizeof(struct sockaddr_in)) < 0) {
@@ -292,6 +305,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
uint8_t tlen;
int i, j;
uint8_t *ptr = (uint8_t *) & snmp_val;
int32_t val32 = (int32_t) snmp_val;
// check for counter, counter64 or gauge
@@ -303,6 +317,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
}
else {
tlen = 4;
ptr = (uint8_t *) &val32;
}
buffer[0] = tlen;
@@ -352,6 +367,32 @@ static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer,
}
static ssize_t build_snmp_metric_response(int64_t value, uint8_t type, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
uint8_t oid_sz;
if (type == UWSGI_METRIC_GAUGE) {
buffer[size - 2] = SNMP_GAUGE;
oid_sz = snmp_int_to_snmp(value, SNMP_GAUGE, buffer + (size - 1));
}
else {
buffer[size - 2] = SNMP_COUNTER64;
oid_sz = snmp_int_to_snmp(value, SNMP_COUNTER64, buffer + (size - 1));
}
if (oid_sz < 1)
return -1;
oid_sz--;
buffer[1] += oid_sz;
*seq1 += oid_sz;
*seq2 += oid_sz;
*seq3 += oid_sz;
return size + oid_sz;
}
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
uwsgi.snmp = 1;
if (value) {
+77 -21
View File
@@ -74,7 +74,7 @@ int bind_to_unix_dgram(char *socket_name) {
}
if (unlink(socket_name) != 0 && errno != ENOENT) {
uwsgi_error("unlink()");
uwsgi_error("error removing unix socket, unlink()");
}
uws_addr = uwsgi_calloc(sizeof(struct sockaddr_un));
@@ -187,6 +187,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
return -1;
}
#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 (%li).\n", somaxconn);
uwsgi_nuclear_blast();
return -1;
}
#endif
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
@@ -1358,7 +1366,7 @@ void uwsgi_add_sockets_to_queue(int queue, int async_id) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->fd_threads && async_id > -1) {
if (uwsgi_sock->fd_threads && async_id > -1 && uwsgi_sock->fd_threads[async_id] > -1) {
event_queue_add_fd_read(queue, uwsgi_sock->fd_threads[async_id]);
}
else if (uwsgi_sock->fd > -1) {
@@ -1645,8 +1653,8 @@ void uwsgi_map_sockets() {
}
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) {
char *p, *ctx = NULL;
uwsgi_foreach_token(colon + 1, ",", p, ctx) {
int w = atoi(p);
if (w < 1 || w > uwsgi.numproc) {
uwsgi_log("invalid worker num: %d\n", w);
@@ -1657,7 +1665,6 @@ void uwsgi_map_sockets() {
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, ",");
}
}
@@ -1666,18 +1673,7 @@ void uwsgi_map_sockets() {
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_remap_fd(uwsgi_sock->fd, "/dev/null");
uwsgi_sock->disabled = 1;
}
@@ -1707,6 +1703,10 @@ void uwsgi_bind_sockets() {
while (uwsgi_sock) {
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
char *tcp_port = strrchr(uwsgi_sock->name, ':');
int current_defer_accept = uwsgi.no_defer_accept;
if (uwsgi_sock->no_defer) {
uwsgi.no_defer_accept = 1;
}
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;
@@ -1714,6 +1714,10 @@ void uwsgi_bind_sockets() {
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);
struct stat st;
if (uwsgi_sock->name[0] != '@' && !stat(uwsgi_sock->name, &st)) {
uwsgi_sock->inode = st.st_ino;
}
}
else {
#ifdef AF_INET6
@@ -1736,6 +1740,7 @@ void uwsgi_bind_sockets() {
uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
exit(1);
}
uwsgi.no_defer_accept = current_defer_accept;
}
uwsgi_sock->bound = 1;
uwsgi_sock = uwsgi_sock->next;
@@ -1781,7 +1786,8 @@ void uwsgi_bind_sockets() {
int fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
uwsgi_log("WARNING: unable to remap stdin, /dev/null not available\n");
goto stdin_done;
}
if (fd != 0) {
if (dup2(fd, 0) < 0) {
@@ -1799,6 +1805,8 @@ void uwsgi_bind_sockets() {
}
stdin_done:
// check for auto_port socket
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
@@ -1863,7 +1871,20 @@ setup_proto:
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
else if (requested_protocol && !strcmp("raw", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_raw_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
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))) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
@@ -1889,7 +1910,7 @@ setup_proto:
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && (!strcmp("scgi", requested_protocol) || !strcmp("scgi", requested_protocol))) {
else if (requested_protocol && !strcmp("scgi", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
@@ -1902,7 +1923,7 @@ setup_proto:
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
else if (requested_protocol && (!strcmp("scgi-nph", requested_protocol) || !strcmp("scgi-nph", requested_protocol))) {
else if (requested_protocol && !strcmp("scgi-nph", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
@@ -1921,6 +1942,22 @@ setup_proto:
uwsgi.zeromq = 1;
}
#endif
else if (requested_protocol && !strcmp("puwsgi", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_puwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_puwsgi_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_noop_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_puwsgi_close;
uwsgi_sock->fd_threads = uwsgi_malloc(sizeof(int) * uwsgi.cores);
memset(uwsgi_sock->fd_threads, -1, sizeof(int) * uwsgi.cores);
uwsgi_sock->retry = uwsgi_calloc(sizeof(int) * uwsgi.cores);
uwsgi.is_et = 1;
}
else {
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
@@ -1951,3 +1988,22 @@ void uwsgi_tcp_nodelay(int fd) {
#endif
}
int uwsgi_accept(int server_fd) {
struct sockaddr_un client_src;
memset(&client_src, 0, sizeof(struct sockaddr_un));
socklen_t client_src_len = 0;
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
return accept4(server_fd, (struct sockaddr *) &client_src, &client_src_len, SOCK_NONBLOCK);
#elif defined(__linux__)
int client_fd = accept(server_fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd >= 0) {
uwsgi_socket_nb(client_fd);
}
return client_fd;
#else
return accept(server_fd, (struct sockaddr *) &client_src, &client_src_len);
#endif
}
+18 -4
View File
@@ -227,20 +227,33 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
#endif
if (write(fd, &uh, 4) != 4) {
uwsgi_log("[spooler] unable to write header for %s\n", filename);
goto clear;
}
if (write(fd, buffer, size) != size) {
uwsgi_log("[spooler] unable to write args for %s\n", filename);
goto clear;
}
if (body && body_len > 0) {
if ((size_t) write(fd, body, body_len) != body_len) {
uwsgi_log("[spooler] unable to write body for %s\n", filename);
goto clear;
}
}
if (at > 0) {
#ifdef __UCLIBC__
struct timespec ts[2];
ts[0].tv_sec = at;
ts[0].tv_nsec = 0;
ts[1].tv_sec = at;
ts[1].tv_nsec = 0;
if (futimens(fd, ts)) {
uwsgi_error("futimens()");
}
#else
struct timeval tv[2];
tv[0].tv_sec = at;
tv[0].tv_usec = 0;
@@ -253,6 +266,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
#endif
uwsgi_error("futimes()");
}
#endif
}
// here the file will be unlocked too
@@ -380,7 +394,7 @@ void spooler(struct uwsgi_spooler *uspool) {
static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
struct dirent **tasklist;
int n;
int n, i;
if (!dir)
dir = uspool->dir;
@@ -391,9 +405,9 @@ static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
return;
}
while (n--) {
spooler_manage_task(uspool, dir, tasklist[n]->d_name);
free(tasklist[n]);
for (i = 0; i < n; i++) {
spooler_manage_task(uspool, dir, tasklist[i]->d_name);
free(tasklist[i]);
}
free(tasklist);
+4
View File
@@ -71,7 +71,11 @@ SSL_SESSION *uwsgi_ssl_session_get_cb(SSL *ssl, unsigned char *key, int keylen,
}
return NULL;
}
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&value, valsize);
#else
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (unsigned char **)&value, valsize);
#endif
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
return sess;
}
+18 -45
View File
@@ -440,6 +440,11 @@ 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) {
if (errno == EINTR) continue;
uwsgi_log_verbose("ending the stats pusher thread...\n");
return;
}
if (nevents > 0) {
int interesting_fd = event_queue_interesting_fd(events, 0);
char buf[4096];
@@ -457,7 +462,8 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
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->last_run + delta) <= now) || (uspi->needs_retry && (uspi->next_retry <= now))) {
if (uspi->needs_retry) uspi->retries++;
if (uspi->raw) {
uspi->pusher->func(uspi, now, NULL, 0);
}
@@ -470,6 +476,17 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
uspi->pusher->func(uspi, now, us->base, us->pos);
}
uspi->last_run = now;
if (uspi->needs_retry && uspi->max_retries > 0 && uspi->retries < uspi->max_retries) {
uwsgi_log("[uwsgi-stats-pusher] %s failed (%d), retry in %ds\n", uspi->pusher->name, uspi->retries, uspi->retry_delay);
uspi->next_retry = now + uspi->retry_delay;
} else if (uspi->needs_retry && uspi->retries >= uspi->max_retries) {
uwsgi_log("[uwsgi-stats-pusher] %s failed and maximum number of retries was reached (%d)\n", uspi->pusher->name, uspi->retries);
uspi->needs_retry = 0;
uspi->retries = 0;
} else if (uspi->retries) {
uwsgi_log("[uwsgi-stats-pusher] retry succeeded for %s\n", uspi->pusher->name);
uspi->retries = 0;
}
}
next:
uspi = uspi->next;
@@ -531,50 +548,6 @@ struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func)
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);
}
static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
struct uwsgi_stats *us = (struct uwsgi_stats *) data;
if (us->dirty) return;
+145
View File
@@ -1,5 +1,46 @@
#include <uwsgi.h>
char *uwsgi_str_split_nget(char *str, size_t len, char what, size_t pos, size_t *rlen) {
size_t i;
size_t current = 0;
char *choosen = str;
size_t choosen_len = 0;
*rlen = 0;
for(i=0;i<len;i++) {
if (!choosen) choosen = str + i;
if (str[i] == what) {
if (current == pos) {
if (choosen_len == 0) return NULL;
*rlen = choosen_len;
return choosen;
}
current++;
choosen = NULL;
choosen_len = 0;
}
else {
choosen_len ++;
}
}
if (current == pos) {
if (choosen_len == 0) return NULL;
*rlen = choosen_len;
return choosen;
}
return NULL;
}
size_t uwsgi_str_occurence(char *str, size_t len, char what) {
size_t count = 0;
size_t i;
for(i=0;i<len;i++) {
if (str[i] == what) count++;
}
return count;
}
// check if a string_list contains an item
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *list, char *key, size_t keylen) {
struct uwsgi_string_list *usl = list;
@@ -338,3 +379,107 @@ char *uwsgi_cheap_string(char *buf, int len) {
return buf - 1;
}
/*
status 0: append mode
status 1: single quote found
status 2: double quote found
status 3: backslash found (on 0)
status 4: backslash found (on 1)
status 5: backslash found (on 2)
*/
char ** uwsgi_split_quoted(char *what, size_t what_len, char *sep, size_t *rlen) {
size_t i;
int status = 0;
char *base = uwsgi_concat2n(what, what_len, "", 0);
char *item = NULL;
char *ptr = NULL;
*rlen = 0;
char **ret = (char **) uwsgi_malloc(sizeof(char *) * (what_len+1));
for(i=0;i<what_len;i++) {
if (!item) {
item = uwsgi_malloc((what_len - i)+1);
ptr = item;
}
if (status == 0) {
if (base[i] == '\\') {
status = 3;
}
else if (base[i] == '"') {
status = 2;
}
else if (base[i] == '\'') {
status = 1;
}
else if (strchr(sep, base[i])) {
*ptr++= 0;
ret[(*rlen)] = item; (*rlen)++;
item = NULL;
}
else {
*ptr++= base[i];
}
continue;
}
// backslash
if (status == 3) {
*ptr++= base[i];
status = 0;
continue;
}
// single quote
if (status == 1) {
if (base[i] == '\\') {
status = 4;
}
else if (base[i] == '\'') {
status = 0;
}
else {
*ptr++= base[i];
}
continue;
}
// double quote
if (status == 2) {
if (base[i] == '\\') {
status = 5;
}
else if (base[i] == '"') {
status = 0;
}
else {
*ptr++= base[i];
}
continue;
}
// backslash single quote
if (status == 4) {
*ptr++= base[i];
status = 1;
continue;
}
// backslash double quote
if (status == 5) {
*ptr++= base[i];
status = 2;
continue;
}
}
if (item) {
*ptr++= 0;
ret[(*rlen)] = item; (*rlen)++;
}
free(base);
return ret;
}
+10 -5
View File
@@ -82,6 +82,8 @@ int uwsgi_apply_final_transformations(struct wsgi_request *wsgi_req) {
found_nostream = 1;
}
else {
// stop the chain if no chunk is available
if (!ut->chunk) return 0;
t_buf = ut->chunk->buf;
t_len = ut->chunk->pos;
goto next;
@@ -132,6 +134,12 @@ void uwsgi_free_transformations(struct wsgi_request *wsgi_req) {
if (current_ut->chunk) {
uwsgi_buffer_destroy(current_ut->chunk);
}
if (current_ut->ub) {
uwsgi_buffer_destroy(current_ut->ub);
}
if (current_ut->fd > -1) {
close(current_ut->fd);
}
ut = ut->next;
free(current_ut);
}
@@ -144,12 +152,9 @@ struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_
ut = ut->next;
}
ut = uwsgi_malloc(sizeof(struct uwsgi_transformation));
ut = uwsgi_calloc(sizeof(struct uwsgi_transformation));
ut->func = func;
ut->is_final = 0;
ut->next = NULL;
ut->chunk = NULL;
ut->can_stream = 0;
ut->fd = -1;
ut->data = data;
if (old_ut) {
+1340 -949
View File
File diff suppressed because it is too large Load Diff
+703 -227
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -59,7 +59,7 @@ static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) {
}
return 0;
}
// pong received, send anther ping
// pong received, send another ping
if (now - wsgi_req->websocket_last_ping >= uwsgi.websockets_ping_freq) {
return uwsgi_websockets_ping(wsgi_req);
}
+68
View File
@@ -120,6 +120,19 @@ error:
//each protocol has its header generator
static int uwsgi_response_add_header_do(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
// collect the header ?
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.collect_headers) {
if (!uwsgi_strnicmp(key, key_len, usl->value, usl->custom)) {
if (!uwsgi_req_append(wsgi_req, usl->custom_ptr, usl->custom2, value, value_len)) {
wsgi_req->write_errors++ ; return -1;
}
}
}
if (!wsgi_req->headers) {
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->headers->limit = UMAX16;
@@ -171,6 +184,16 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
#ifdef UWSGI_ROUTING
// apply response routes
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
// from now on ignore write body requests...
wsgi_req->ignore_body = 1;
return -1;
}
wsgi_req->is_response_routing = 0;
#endif
struct uwsgi_string_list *ah = uwsgi.additional_headers;
while(ah) {
if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
@@ -221,6 +244,19 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
if (wsgi_req->write_errors) return -1;
if (wsgi_req->ignore_body) return UWSGI_OK;
#ifdef UWSGI_ROUTING
// special case here, we could need to set transformations before
if (!wsgi_req->headers_sent) {
// apply response routes
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
// from now on ignore write body requests...
wsgi_req->ignore_body = 1;
return -1;
}
wsgi_req->is_response_routing = 0;
}
#endif
// if the transformation chain returns 1, we are in buffering mode
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
int t_ret = uwsgi_apply_transformations(wsgi_req, buf, len);
@@ -408,3 +444,35 @@ int uwsgi_simple_wait_write_hook(int fd, int timeout) {
return ret;
}
/*
simplified write to client
(generally used as fallback)
*/
int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
wsgi_req->write_pos = 0;
for(;;) {
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_simple_write()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
uwsgi_log("uwsgi_simple_write() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
return 0;
}
+3
View File
@@ -151,6 +151,8 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
}
/* We can safely free resources */
if (colon) colon[0] = ':';
xmlFreeDoc(doc);
xmlCleanupParser();
@@ -267,6 +269,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
} while (!done);
if (colon) colon[0] = ':';
// we can safely free, as we have a copy of datas
XML_ParserFree(parser);
+1
View File
@@ -280,6 +280,7 @@ next:
}
#endif
if (colon) colon[0] = ':';
}
+66
View File
@@ -0,0 +1,66 @@
/*
*** WORK IN PROGRESS ***
Zeus mode
A Zeus instance can load all of the available imperial monitor plugins, but instead of spawning
vassals it delegates actions to Emperors connected to it.
The Zeus instance try to distribute vassals evenly between Emperors.
Emperors register to one (ore more, maybe...) Zeus instance, passing various informations (like the maximum number
of vassals it can manage)
to spawn a Zeus:
# unencrypted mode
uwsgi --zeus "192.168.173.17:4040 /etc/uwsgi/vassals"
# crypted mode
uwsgi --zeus "192.168.173.17:4040,foobar.crt,foobar.key /etc/uwsgi/vassals"
# crypted + authentication mode
uwsgi --zeus "192.168.173.17:4040,foobar.crt,foobar.key,clients.pem /etc/uwsgi/vassals"
to connect an Emperor to Zeus
# unencrypted mode
uwsgi --emperor zeus:192.168.173.17:4040
# crypted mode
uwsgi --emperor zeus-ssl:192.168.173.17:4040
# crypted + authentication mode
uwsgi --emperor zeus-ssl:192.168.173.17:4040,myself.key
Protocol
(each message is a basic uwsgi packet: modifier1 pktsize modifier2 payload)
modifier2 identifies the type of the message
0 -> I_AM_ALIVE {node: 'node001', max_vassals: '100', running_vassals: '17'} [ emperor -> zeus ]
1 -> NEW_VASSAL {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
2 -> ACCEPTED_VASSAL {name: 'foobar.ini'} [ emperor -> zeus ]
3 -> CONFIG_CHUNK {name: 'foobar.ini', body: '[uwsgi].....'} [ zeus -> the choosen emperor ]
4 -> CONFIG_END {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
5 -> VASSAL_SPAWNED {name: 'foobar.ini'} [the choosen emperor -> zeus]
6 -> VASSAL_REJECTED {name: 'foobar.ini'} [the choosen emperor -> zeus]
7 -> VASSAL_RELOAD {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
8 -> VASSAL_UPDATE {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
9 -> VASSAL_DESTROY {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
10 -> VASSAL_RELOADED {name: 'foobar.ini'} [the choosen emperor -> zeus]
11 -> VASSAL_DESTROYED {name: 'foobar.ini'} [the choosen emperor -> zeus]
*/
+59 -2
View File
@@ -2,6 +2,8 @@
char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
extern struct uwsgi_server uwsgi;
char *uwsgi_gzip_chunk(z_stream *z, uint32_t *crc32, char *buf, size_t len, size_t *dlen) {
uwsgi_crc32(crc32, buf, len);
return uwsgi_deflate(z, buf, len, dlen);
@@ -38,6 +40,45 @@ end:
return ub;
}
struct uwsgi_buffer *uwsgi_zlib_decompress(char *buf, size_t len) {
z_stream z;
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
if (inflateInit(&z) != Z_OK) {
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
unsigned char out[8192];
z.next_in = (unsigned char *)buf;
z.avail_in = len;
z.next_out = out;
do {
z.avail_out = 8192;
z.next_out = out;
int ret = inflate(&z, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
uwsgi_buffer_destroy(ub);
ub = NULL;
goto end;
}
if (uwsgi_buffer_append(ub, (char *)out, 8192 - z.avail_out)) {
uwsgi_buffer_destroy(ub);
ub = NULL;
goto end;
}
}
while (z.avail_out == 0);
end:
inflateEnd(&z);
return ub;
}
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
z->zalloc = Z_NULL;
z->zfree = Z_NULL;
@@ -54,6 +95,21 @@ int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
return 0;
}
int uwsgi_inflate_init(z_stream *z, char *dict, size_t dict_len) {
z->zalloc = Z_NULL;
z->zfree = Z_NULL;
z->opaque = Z_NULL;
if (inflateInit2(z, 16+MAX_WBITS) != Z_OK) {
return -1;
}
if (dict && dict_len) {
if (inflateSetDictionary(z, (Bytef *) dict, dict_len) != Z_OK) {
return -1;
}
}
return 0;
}
int uwsgi_gzip_prepare(z_stream *z, char *dict, size_t dict_len, uint32_t *crc32) {
uwsgi_crc32(crc32, NULL, 0);
if (uwsgi_deflate_init(z, NULL, 0)) return -1;
@@ -67,12 +123,13 @@ int uwsgi_gzip_fix(z_stream *z, uint32_t crc32, struct uwsgi_buffer *ub, size_t
if (!gzipped0) goto end;
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
free(gzipped0);
if (uwsgi_buffer_u32le(ub, crc32)) goto end;
if (uwsgi_buffer_u32le(ub, len)) goto end;
if (uwsgi_buffer_u32le(ub, crc32)) goto end2;
if (uwsgi_buffer_u32le(ub, len)) goto end2;
deflateEnd(z);
return 0;
end:
if (gzipped0) free(gzipped0);
end2:
deflateEnd(z);
return -1;
}
View File
View File
+146
View File
@@ -0,0 +1,146 @@
<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:html="http://www.w3.org/TR/html4/"
xmlns="http://www.w3.org/TR/html4/"
exclude-result-prefixes="html">
<xsl:output method="html" doctype-public="-//W3C//DTD HTML 4.01 Strict//EN"
indent="yes" doctype-system="http://www.w3.org/TR/html4/strict.dtd"
encoding="UTF-8" />
<xsl:template name="format-date">
<xsl:param name="date" />
<xsl:value-of select="substring-before($date, 'T')" />
<xsl:text> </xsl:text>
<xsl:value-of select="substring-after($date, 'T')" />
</xsl:template>
<xsl:template match="index">
<html>
<head>
<xsl:choose>
<xsl:when test="$stylesheet">
<link rel="stylesheet" type="text/css" media="all" href="{$stylesheet}" />
</xsl:when>
<xsl:otherwise>
<style type="text/css">
html {
color: #000000;
background-color: #fefefe;
font-family: sans-serif;
}
h1 {
font-size: 1.5em;
font-weight: bold;
margin: .67em 0;
}
th {
text-align: left;
}
td {
font-family: mono;
}
td, th {
padding: 0 1em;
}
td.size {
text-align: right;
}
:link, :visited {
text-decoration: none;
}
:link {
color: #000099;
}
:visited {
color: #6600cc;
}
:link:hover,
:visited:hover {
text-decoration: underline;
}
:link:focus,
:visited:focus {
text-decoration: underline;
}
:link:active,
:visited:active {
text-decoration: underline;
}
</style>
</xsl:otherwise>
</xsl:choose>
<title>Index of <xsl:value-of select="@path" /></title>
</head>
<body>
<h1>Index of <xsl:value-of select="@path" /></h1>
<table>
<tr>
<th class="name">Name</th>
<th class="mtime">Last Modified</th>
<th class="size">Size</th>
</tr>
<tr>
<td class="name" colspan="3"><a href=".." title="Parent">Parent directory</a></td>
</tr>
<xsl:apply-templates select="directory" />
<xsl:apply-templates select="file" />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="directory">
<tr class="directory">
<td class="name">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="." />
<xsl:text>/</xsl:text>
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="." />
<xsl:text>/</xsl:text>
</xsl:attribute>
<xsl:value-of select="." />
<xsl:text>/</xsl:text>
</xsl:element>
</td>
<td class="mtime">
<xsl:call-template name="format-date">
<xsl:with-param name="date" select="@mtime" />
</xsl:call-template>
</td>
<td class="size">
<xsl:value-of select="@size" />
</td>
</tr>
</xsl:template>
<xsl:template match="file">
<tr class="file">
<td class="name">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="." />
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="." />
</xsl:attribute>
<xsl:value-of select="." />
</xsl:element>
</td>
<td class="mtime">
<xsl:call-template name="format-date">
<xsl:with-param name="date" select="@mtime" />
</xsl:call-template>
</td>
<td class="size">
<xsl:value-of select="@size" />
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
+17
View File
@@ -0,0 +1,17 @@
[uwsgi]
plugin = 0:notfound, router_xmldir, xslt
http-socket = :8080
docroot = .
check-static = %(docroot)
route-if = isdir:%(docroot)/${PATH_INFO} goto:index
route-run = last:
route-label = index
; uncomment to link CSS stylesheet /css/default.css
;route-run = toxslt:stylesheet=examples/xmlindex-html.xsl,params=stylesheet=/css/default.css,content_type=text/html
; use embedded CSS
route-run = toxslt:stylesheet=examples/xmlindex-html.xsl,params=stylesheet=,content_type=text/html
route-run = xmldir:%(docroot)/${PATH_INFO}
+8 -1
View File
@@ -7,7 +7,14 @@ Net::HTTP.start("uwsgi.it") do |http|
end
end
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
major,minor = RUBY_VERSION.split('.')
if major.to_i >= 2 or (major.to_i == 1 and minor.to_i >= 9)
# a trick for installations with messy PATH
ENV['UWSGICONFIG_RUBYPATH'] = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name']).sub(/.*\s.*/m, '"\&"')
system("bash install.sh ruby2 #{Dir.pwd}/uwsgi.ruby")
else
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
end
open("Makefile", "w") do |file|
file.write("all:\n")
-54
View File
@@ -1,54 +0,0 @@
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:
uwsgi.cache_set('foo', "Hello World from cache")
except:
pass
def application(env, start_response):
print env['wsgi.input'].read()
if uwsgi.loop == 'gevent':
gevent.sleep()
start_response('200 OK', [('Content-Type', 'text/html')])
yield "foobar<br/>"
if uwsgi.loop == 'gevent':
gevent.sleep(3)
yield str(env['wsgi.input'].fileno())
yield "<h1>Hello World</h1>"
try:
yield uwsgi.cache_get('foo')
except:
pass
-31
View File
@@ -1,31 +0,0 @@
import uwsgi
import time
import rrdtool
# rrdtool create test.rrd --start 1270879004 -s 10 DS:requests:COUNTER:300:U:U RRA:AVERAGE:0.5:3:105120
s_freq = 10
# this task will be executed every s_freq seconds
def rrdtool_updater(sig, sec):
rrdtool.update('test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.register_timer(0, s_freq, uwsgi.KIND_WORKER, rrdtool_updater)
def hello_world(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain')])
return 'Hello world !'
def graph(env, start_response):
start_response('200 Ok', [('Content-type', 'image/png')])
now = int(time.time())
graph_range = (3600*24)
rrdtool.graph('uwsgi_graph.png', '--start', str(now - graph_range), '--end', str(now), 'DEF:urequests=test.rrd:requests:AVERAGE', 'LINE2:urequests#00FF00')
# send file to client
uwsgi.sendfile('uwsgi_graph.png')
uwsgi.applications = {'/': hello_world, '/graph':graph}
+15 -1
View File
@@ -66,11 +66,17 @@ void linux_namespace_start(void *argv) {
uwsgi_error("clone()");
exit(1);
}
#if defined(MS_REC) && defined(MS_PRIVATE)
if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)) {
uwsgi_error("mount()");
exit(1);
}
#endif
// run the post-jail scripts
if (setenv("UWSGI_JAIL_PID", uwsgi_num2str((int) pid), 1)) {
uwsgi_error("setenv()");
}
uwsgi_hooks_run(uwsgi.hook_post_jail, "post-jail", 1);
struct uwsgi_string_list *usl = uwsgi.exec_post_jail;
while(usl) {
uwsgi_log("running \"%s\" (post-jail)...\n", usl->value);
@@ -82,6 +88,13 @@ void linux_namespace_start(void *argv) {
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_post_jail) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
}
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
pid = waitpid(pid, &waitpid_status, 0);
if (pid < 0) {
@@ -167,6 +180,7 @@ void linux_namespace_jail() {
uwsgi_log("remounting /proc\n");
if (mount("proc", "/proc", "proc", 0, NULL)) {
uwsgi_error("mount()");
exit(1);
}
struct uwsgi_string_list *usl = uwsgi.ns_keep_mount;
+52
View File
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="768px" height="272.667px" viewBox="0 0 768 272.667" enable-background="new 0 0 768 272.667" xml:space="preserve">
<g>
<path fill="#AEC84D" d="M170.667,41.334"/>
<path fill="#AEC84D" d="M46.167,106.667v92.5c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34l0.062-140h-34
l-0.062,86.5c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.167-89H46.167z"/>
<polygon fill="#141215" points="227,250.334 241,250.334 286.667,137.334 332.333,250.001 346.333,250.001 403,41.334
368.667,32.667 334.333,161.667 293.667,60.001 279.333,60.001 240,160.667 204.667,32.667 170.667,41.334 "/>
<path fill="#141215" d="M402,203c0,0,8.667,26.001,23,35.334s38.666,12.999,50.333,12.666s71.001-1.333,71.667-56.333
c5-28-19.333-48.334-26-52.334s-28.334-18-45.667-23s-34.334-16-35.667-24.666s0.001-34,37.334-34.334
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334s-13.333-19-55.333-18.666
c-42,0.332-66.666,17.666-68.333,47.666s4.666,44,35.333,62.666c19,10.334,39.001,12.667,59.667,28.334
c14.333,11.667,11.334,25.001,11,30.667s-7.334,21.666-36.334,20.333S441,209.668,439,206.334s-9-17-9-17L402,203z"/>
<rect x="710.667" y="36.334" fill="#141215" width="35.333" height="211.333"/>
<path fill="#141215" d="M636.333,135.001v27.666h27.333v56c0,0-8.334,5.001-26.667,4.334s-47.332,1.666-49.666-81.667
s37.334-80.667,42-80.667s28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667s-12.334-50.333-67-47.666
c-54.666,2.666-75.666,30.999-78.666,102c-3,71,21.999,117.334,81.666,115s64-7.334,64-7.334l-0.083-107.583L636.333,135.001z"/>
<g>
<circle fill="#AEC84D" cx="521.333" cy="71.001" r="11.667"/>
<circle fill="#252326" cx="521.333" cy="71.001" r="3.5"/>
</g>
<g>
<path fill="none" d="M81.147,185.163L81,106.667H46.167v90.88C56.139,192.016,68.027,187.752,81.147,185.163z"/>
<path fill="none" d="M171.729,106.667h-34l-0.057,78.023c12.606,2.254,24.141,6.043,34.017,11.019L171.729,106.667z"/>
<path opacity="0.1" fill="#FFFFFF" d="M46.167,199.167c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34
l0.023-50.958c-9.876-4.976-21.411-8.765-34.017-11.019l-0.006,8.477c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.02-10.504
c-13.12,2.589-25.008,6.853-34.98,12.384V199.167z"/>
</g>
<g>
<path fill="none" d="M342.89,129.517l-8.557,32.15l-13.896-34.738c-22.89-2.918-44.071-6.524-63.071-10.708L240,160.667
l-14.526-52.621c-16.399-4.896-30.286-10.312-41.175-16.132L227,250.334h14l45.667-113l45.667,112.667h14l31.898-117.459
C366.127,131.707,354.33,130.695,342.89,129.517z"/>
<path opacity="0.1" fill="#FFFFFF" d="M403,41.334l-34.333-8.667l-25.776,96.85c11.44,1.178,23.237,2.19,35.341,3.025L403,41.334z
"/>
<path opacity="0.1" fill="#FFFFFF" d="M204.667,32.667l-34,8.667l13.633,50.58c10.889,5.82,24.775,11.236,41.175,16.132
L204.667,32.667z"/>
<path opacity="0.1" fill="#FFFFFF" d="M293.667,60.001h-14.333l-21.967,56.22c19,4.185,40.182,7.79,63.071,10.708L293.667,60.001z
"/>
</g>
<path opacity="0.1" fill="#FFFFFF" d="M474.333,33.001c-42,0.332-66.666,17.666-68.333,47.666
c-1.409,25.351,2.897,39.276,22.77,54.247c10.646,0.275,21.452,0.419,32.396,0.419c15.9,0,31.514-0.299,46.756-0.872
c-9.466-5.486-21.856-12.032-32.589-15.128c-17.333-5-34.334-16-35.667-24.666s0.001-34,37.334-34.334
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334S516.333,32.667,474.333,33.001z"/>
<path opacity="0.1" fill="#FFFFFF" d="M631,33.001c-53.87,2.627-75.047,30.182-78.522,98.93c11.947-0.916,23.576-2.007,34.838-3.26
c1.845-70.377,37.603-68.004,42.019-68.004c4.666,0,28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667
S685.666,30.334,631,33.001z"/>
<path opacity="0.1" fill="#FFFFFF" d="M710.667,103.59c14.42-5.033,26.342-10.521,35.333-16.36V36.334h-35.333V103.59z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

+1
View File
@@ -229,6 +229,7 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
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);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;
char *opts = uwsgi_str(uacc->arg);

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