Compare commits

..
1558 Commits
Author SHA1 Message Date
Unbit ef17013945 sethostname fix for sun [2] 2014-02-09 07:34:51 +01:00
Unbit a225d53825 sethostname fix for sun 2014-02-09 07:33:31 +01:00
Unbit d4298469ba fixed race condition in u_pypy_thread_attach() 2014-02-08 14:20:49 +01:00
unbit 395de489b8 Merge pull request #518 from xrmx/coverity0802
Some coverity fixes
2014-02-08 13:56:36 +01:00
Riccardo Magliocchetti 6e6efc5605 plugins/logpipe: check setsid return code
Reported by Coverity as CID #1167589
2014-02-08 12:52:20 +01:00
Riccardo Magliocchetti ce260ecbb6 spooler: filename cannot be null
Since it is allocated by uwsgi_malloc.
Reported by Coverity as CID #1153071
2014-02-08 12:49:17 +01:00
Riccardo Magliocchetti e143e25b3c spooler: fix use after free
Reported by Coverity as CID #1153073
2014-02-08 12:45:47 +01:00
Riccardo Magliocchetti e9a58bac46 ssl: avoid null pointer dereference
name is checked not to be null earlier, if it is here just error
out.

Reported by Coverity as CID #1167590
2014-02-08 12:39:58 +01:00
Riccardo Magliocchetti 1448fbc5a3 ssl: Fix fd leak on write error
Reported by Coverity as CID #1167591
2014-02-08 12:36:09 +01:00
Unbit b801f839fc check for heartbeat only if heartneat is enabled 2014-02-06 07:02:58 +01:00
Unbit bcb8321480 improved heartbeat mode 2014-02-06 05:34:29 +01:00
Unbit 5cd9e64073 positive tests for psgi input 2014-02-05 13:40:52 +01:00
Unbit d878b65401 added first round of tests for psgi input with offset 2014-02-05 12:37:46 +01:00
Unbit ded149fc80 fixed perl stacktrace usage 2014-02-05 11:34:14 +01:00
Unbit f041d1095d perl refactoring 2014-02-05 11:21:01 +01:00
unbit 886842de12 Merge pull request #516 from comel/cgi-fix
CGI: remove double header_size check.
2014-02-04 08:18:36 -08:00
Andjelko Horvat b4915f778e CGI: remove double header_size check. 2014-02-04 16:32:36 +01:00
unbit a25e02bbb3 Merge pull request #514 from comel/cgi-fix
CGI: search and set Status header in RFC 3875 compliant way.
2014-02-04 07:13:14 -08:00
Unbit 16aec7c44b fixed sni subscriptions 2014-02-04 14:52:00 +01:00
Andjelko Horvat 42dfa20f27 CGI: search and set Status header in RFC 3875 compliant way. 2014-02-03 12:03:25 +01:00
Unbit 2092050f00 allow building without ssl 2014-02-02 18:54:49 +01:00
Unbit b5a0434710 fixed #513 2014-02-02 04:56:21 +01:00
Unbit 2737cd5c35 improved embedding 2014-01-31 08:55:10 +01:00
Unbit 7a29d9649c added --pypy-paste and paste logging 2014-01-31 08:34:56 +01:00
Unbit 27cc164ebe added --pypy-ini-paste 2014-01-31 08:24:22 +01:00
Unbit 40be8fc916 fixed rpc 2014-01-29 09:08:44 +01:00
Unbit f219afc6e0 start unsubscribed 2014-01-29 08:42:32 +01:00
unbit f20f72ceb1 Merge pull request #509 from xiaost-bytedance/master
[spooler]memory leak bugfix & simplified code
2014-01-28 14:46:54 -08:00
xiaost 6555c2804c simplified the python spooler code 2014-01-29 04:56:54 +08:00
xiaost c05082a8e4 fixed python spooler memory leak 2014-01-29 04:39:51 +08:00
Unbit 62dab40a22 added j magic var 2014-01-23 00:50:28 +01:00
Unbit 02e68ae578 reintroduced no orphans 2014-01-22 15:38:26 +01:00
Unbit ba1fb72427 fixed sni 2014-01-19 13:50:49 +01:00
Unbit df9a76a171 improve dotsplit support 2014-01-19 13:36:21 +01:00
Unbit 98e7e0845d sub-emperor can be loyal 2014-01-19 08:27:05 +01:00
Unbit 6c9f73ae7f added sticky hook 2014-01-18 08:45:55 +01:00
Unbit b12658102d added creat hook 2014-01-18 08:18:10 +01:00
Unbit c51b74a32b improved emperor death procedure 2014-01-16 15:05:22 +01:00
Unbit b0e6d19d5c added --http-server-name-as-http-host 2014-01-16 07:12:56 +01:00
Unbit 7ff3584ad7 imrpvoed ruby1.8.7 support 2014-01-15 17:22:56 +01:00
Unbit 57b6d1f51b spawn without socker when setns is in place 2014-01-14 04:31:18 +01:00
Roberto De Ioris 1646f9c199 fixed notifications 2014-01-13 12:36:08 +01:00
Unbit 260b49c3f6 more clear error report when unix sockets are not removable 2014-01-13 06:38:27 +01:00
Unbit 58af067bef fixed #507 2014-01-13 06:26:07 +01:00
Unbit d1285c6dc4 fixed harakiri tracebacker 2014-01-12 10:25:32 +01:00
Unbit d4e9f3a2d4 allow sni to use stream as certificates 2014-01-12 10:03:01 +01:00
Unbit a15de85811 another refactoring of subscription subsystem 2014-01-12 09:22:10 +01:00
Unbit 4b09ead07d refactored recured subscription system 2014-01-12 09:04:57 +01:00
Unbit 338aca9da5 fixed subscription uid check 2014-01-12 08:17:52 +01:00
Unbit 3f0b9390d9 added subscriptions-sign-skip-uid 2014-01-12 08:01:21 +01:00
Unbit e14b189c77 improved pid namespace daemons 2014-01-11 11:51:44 +01:00
Unbit cabb179a84 minor fix 2014-01-11 10:49:59 +01:00
Unbit ad9b48b69e fixed vars stats item 2014-01-11 10:01:54 +01:00
Unbit 08443d5463 fixed logfile-chown 2014-01-11 07:36:01 +01:00
Unbit 5d11a5cd77 improved legion reload 2014-01-11 07:27:26 +01:00
Unbit 3aba97745c added as-gateway hook 2014-01-11 07:09:18 +01:00
Unbit 0b596bdf42 Merge branch 'master' of https://github.com/unbit/uwsgi 2014-01-09 20:13:42 +01:00
Unbit 4c4b08c36f fixed tuntap netmask 2014-01-09 20:13:23 +01:00
Unbit 1f0827abc8 fixed a busyness bug 2014-01-09 15:42:51 +01:00
Unbit 2ea67c67df notify subscriptions 2014-01-09 13:13:20 +01:00
Unbit 8eebc9f400 allows passing notify object to subscription packets 2014-01-09 12:59:36 +01:00
Unbit 2ad6a1c8e8 prepare for notification socket 2014-01-09 12:43:28 +01:00
Unbit d39d0e8403 updated copyright notes 2014-01-09 05:56:50 +01:00
Unbit 2838fffbde added inject-before and inject-after 2014-01-09 05:12:17 +01:00
Unbit 45bc51541a better to use lstat for inode 2014-01-08 20:06:38 +01:00
Unbit 3427a17191 added %i magic var 2014-01-08 20:03:05 +01:00
Unbit 0cf61abf9d improved ruby builder 2014-01-08 14:35:40 +00:00
Unbit 53fde5fcdd added for-readline 2014-01-08 11:06:29 +01:00
Unbit e81f068e4b a fix from nginx for SNI client authentication 2014-01-08 07:55:46 +01:00
Unbit aaee226183 fix sni subscription 2014-01-08 06:53:09 +01:00
Unbit d7bba38d7a better re-fork management for daemons 2014-01-08 06:20:37 +01:00
Unbit 18fa1172db re-fork on NEWPID daemon usage 2014-01-08 06:17:33 +01:00
Unbit 9e95312169 added ns_pid keyval option for daemons 2014-01-08 06:07:04 +01:00
Unbit 216aff3820 allows fixed binding for resubscription 2014-01-07 15:23:13 +01:00
Unbit eae335a43e added support for yajl 1.0 2014-01-07 09:22:49 +01:00
unbit e0cf245a0e Merge pull request #502 from prymitive/cast_fix
cast internal_counter to expected type
2014-01-05 03:26:51 -08:00
Łukasz Mierzwa d463f9e7d9 cast internal_counter to expected type 2014-01-05 12:19:15 +01:00
Unbit 06c62033dd Merge branch 'master' of https://github.com/unbit/uwsgi 2014-01-05 11:34:51 +01:00
Unbit 72ea5ab54a support embedding external plugins 2014-01-05 11:34:40 +01:00
Roberto De Ioris 843a3b18ad fixed hv_delete on clang 2014-01-05 09:35:49 +01:00
Unbit 37acca060b added --spooler-frequency 2014-01-05 09:19:40 +01:00
Unbit a0ff5b91b8 cast non-bytes arguments to bytes in python3 spool api 2014-01-05 09:08:29 +01:00
Unbit ea19e1e67b perl spool arg must be a hashref 2014-01-05 09:01:17 +01:00
Unbit c20e3fb1a8 fix debug un-needed option in default profile 2014-01-05 08:36:07 +01:00
Unbit a57c2997f4 prepare for 2.0.1 2014-01-05 08:35:33 +01:00
Unbit 3d051e5d79 completed perl spooler support 2014-01-05 08:35:03 +01:00
Unbit 3b0d18c1ec directly call .to_s in the rack spool request 2014-01-05 06:25:31 +01:00
Unbit 89e04c5d17 fixed UWSGI_PROFILE_OVERRIDE 2014-01-05 06:06:47 +01:00
Roberto De Ioris 84ea262203 some minor tycasting fix 2014-01-05 05:22:09 +01:00
Unbit 15fa2be4ee preliminary refactoring for the spooler 2014-01-04 19:28:01 +01:00
Unbit f18ceea9bf fixed resubscription when different sockets type are in place 2014-01-04 10:12:03 +01:00
Unbit e4a993ac31 improved fsmon api 2014-01-04 07:22:20 +01:00
Unbit cf2c20418c implemented hook touch 2014-01-04 06:36:10 +01:00
Unbit d155197d98 added alarm legion action 2014-01-04 06:14:51 +01:00
Unbit fbc1551112 do not forward signature in resubscriptions 2014-01-04 06:09:27 +01:00
Unbit b3bba48d1a add buffer-size configuration to the other routers 2014-01-03 17:24:40 +01:00
Unbit 18972d95a8 improved subscription system 2014-01-03 17:22:23 +01:00
Unbit 8aa8d6070b error check on greenlet error 2014-01-03 15:08:07 +01:00
Unbit 3f0e9f899a fixed daemons touch stop 2014-01-03 12:41:02 +01:00
Unbit 00bf0aa713 improved legion_action api 2014-01-03 11:44:47 +01:00
Unbit 60675724d3 added support for custom log messages in legion actions 2014-01-03 11:05:18 +01:00
Unbit b45deb780d added uwsgi.legion_death_on_lord_error 2014-01-03 10:59:27 +01:00
Unbit 24e144268b announce legion dead on lord hook failure 2014-01-03 10:26:26 +01:00
Unbit b870b8c6d8 fixed json build check for true 2014-01-03 09:24:12 +01:00
Roberto De Ioris 62be7482d4 prepare for touch event 2014-01-03 08:51:23 +01:00
Roberto De Ioris 0c8f473e6f rset fd flags only if close_on_exec2 is enabled 2014-01-02 17:20:52 +01:00
unbit 8b19fd3f94 Merge pull request #498 from kunkku/close-serverfd
core/socket: close TCP server fd when spawning
2014-01-02 08:17:26 -08:00
Kaarle Ritvanen 7553ce3a48 option for closing server sockets when spawning
If server fd is not closed, it is not possible to restart uwsgi if the
spawned process is still running as it keeps the address/port bound.
2014-01-02 12:29:50 +02:00
unbit 9ff67391c0 Merge pull request #499 from kunkku/socket-refactor
core/socket: eliminate some duplicated code from bind_to_* functions
2014-01-01 21:21:03 -08:00
Kaarle Ritvanen 4f4f9b93aa core/socket: move SO_REUSEADDR setting to create_server_socket 2014-01-02 00:51:52 +02:00
Kaarle Ritvanen 51a8f31f17 core/socket: move listen queue size checking to create_server_socket 2014-01-02 00:51:52 +02:00
Kaarle Ritvanen 32b7126836 core/socket: move socket buffer size setting to create_server_socket 2014-01-02 00:47:22 +02:00
Kaarle Ritvanen 4d43a66581 core/socket: common socket creation function for bind_to_* 2014-01-02 00:08:32 +02:00
Unbit 0f95ef6d5a added alarm-metric alias 2013-12-31 12:36:07 +01:00
Unbit c0c43a7d47 added --alarm-backlog 2013-12-31 12:09:32 +01:00
Unbit 4361ef2dc6 more hooks 2013-12-31 09:24:23 +01:00
Unbit b7298aba85 more straight ruby lib detection 2013-12-30 16:43:02 +01:00
Unbit 0d4172a271 prepare for 2.0 2013-12-30 09:44:59 +01:00
Unbit e842a181aa fixed #478 2013-12-30 06:44:54 +01:00
Unbit 1ba0935579 fixed lua prepare_headers 2013-12-28 18:39:30 +01:00
unbit 920d1e5cfe Merge pull request #497 from xrmx/coverity2812
More coverity fixes
2013-12-28 09:28:31 -08:00
Riccardo Magliocchetti 473b4f1e57 plugins/lua: check return value of uwsgi_response_prepare_headers
Reported by Coverity as CID #1100802
2013-12-28 16:11:59 +01:00
Riccardo Magliocchetti b5c19bc1f8 plugins/php: check return value of uwsgi_response_prepare_headers
Reported by Coverity as CID #1100794
2013-12-28 16:06:58 +01:00
Riccardo Magliocchetti 79222adfe7 plugins/sslrouter: check return value of uwsgi_cr_set_hooks
Reported by Coverity as CID #971229
2013-12-28 15:56:46 +01:00
Riccardo Magliocchetti 8b90efc567 plugins/http: check return value of uwsgi_cr_set_hooks
Reported by Coverity as CID #970970
2013-12-28 15:54:59 +01:00
Riccardo Magliocchetti 4667eedc2b core/static: check return value of uwsgi_response_prepare_headers
Reported by Coverity as CID #970965
2013-12-28 15:49:04 +01:00
Riccardo Magliocchetti 752252c9e4 core/emperor: check return value of uwsgi_stats_str
Reported by Coverity as CID #970959
2013-12-28 15:45:05 +01:00
Unbit 6d91b7317d try to address a strange crash 2013-12-28 07:10:23 +01:00
unbit cddd1148fd Merge pull request #496 from xrmx/coverity2712
More Coverity fixes
2013-12-27 18:02:23 -08:00
Riccardo Magliocchetti c2096e8373 plugins/python: check return value of bind to unix
Reported by Coverity as CID #995784
2013-12-27 19:25:00 +01:00
Riccardo Magliocchetti 4f57ef33af Revert "yaml: fix memory leak"
This reverts commit ba3ac9ad09.

Since it looks like add_export_option does not copy the string we
shouldn't free it.
2013-12-27 19:16:59 +01:00
Riccardo Magliocchetti aa34beade1 core/legion: fix memory leak
Reported by coverity as CID #971022.
2013-12-27 19:09:49 +01:00
Riccardo Magliocchetti 1149e60125 core/subscription: fix memory leak
Reported by Coverity as CID #971040.
2013-12-27 19:06:12 +01:00
Riccardo Magliocchetti 7def85636e linux_ns: fix memory leak
Reported by Coverity as CID #971052.
2013-12-27 18:53:49 +01:00
Riccardo Magliocchetti d44692b268 plugins/xslt: fix compilation
After 594880fb46
2013-12-27 18:50:46 +01:00
Riccardo Magliocchetti 46322b84b4 plugins/python: fix memory leak
Reported by Coverity as CID #971056
2013-12-27 18:45:44 +01:00
Riccardo Magliocchetti 5785c61a13 core/legion: fix memory leak
Reported by Coverity as CID #1010086
2013-12-27 18:24:02 +01:00
Riccardo Magliocchetti 594880fb46 plugins/xslt: fix memory leak on error path
Reported by Coverity as CID #1125165
2013-12-27 18:17:49 +01:00
Unbit 4373306f78 added --declare-option2 2013-12-27 10:45:41 +01:00
Unbit f3e164b397 fixed return value in hv_store 2013-12-26 18:57:52 +01:00
Unbit a60bb56b18 cygwin does not support sethostname 2013-12-26 18:00:59 +01:00
Unbit d08d08f39b exit(1) on setns propen failure 2013-12-26 17:54:05 +01:00
Unbit 4c4c2bb0fe setns-peopen does not take arguments 2013-12-26 17:53:14 +01:00
Unbit cf79ce40e4 fixed max worker lifetime 2013-12-26 17:46:19 +01:00
Unbit c153c26c18 fixed scripts/tests making use of dynamic options 2013-12-26 17:42:28 +01:00
Unbit 82f5d1f988 prepare for 2.0-rc1 2013-12-26 17:28:13 +01:00
Unbit 5de83201ea getting rid of dynami options (step 3) 2013-12-26 17:06:36 +01:00
Unbit 6d69c01651 getting rid of dynami options (step 2) 2013-12-26 17:03:27 +01:00
Unbit 61f3d162a4 getting rid og dynamic options (step 1) 2013-12-26 16:48:50 +01:00
Unbit 0a025ef93a fixed minor bug in listen queue management 2013-12-26 11:21:16 +01:00
Unbit f0951d3f41 refactored listen queue management 2013-12-26 11:14:28 +01:00
Unbit f2e4eabf42 fixed cheaper busyness check 2013-12-26 08:02:27 +01:00
Unbit 4fc99b3a3e fixed memory allocation in --attach-daemon2 2013-12-24 18:02:32 +01:00
Unbit 1efb3f4096 expose uid gid and pid in subscription nodes 2013-12-24 17:43:54 +01:00
Unbit 9c29d6899f implemented touch management for daemons 2013-12-24 17:30:23 +01:00
Unbit 9a7524b55d added --attach-daemon2 2013-12-24 17:08:36 +01:00
Unbit 04dfc3ae19 fixed hooks when exit on reload is in place 2013-12-24 07:58:06 +01:00
Unbit fc10411adb added three new emperor hooks 2013-12-24 07:08:31 +01:00
unbit 2378db4520 Merge pull request #495 from prymitive/busyness_metrics
metrics support for cheaper busyness plugin
2013-12-23 11:11:33 -08:00
Łukasz Mierzwa bdbd484db5 metrics support for cheaper busyness plugin 2013-12-23 19:07:51 +01:00
unbit a2f6dd4ee2 Merge pull request #494 from xrmx/coverity-2312-4
More Coverity fixes
2013-12-23 08:36:30 -08:00
Riccardo Magliocchetti ac001beb41 emperor: Avoid integer overflow
Reported by Coverity as CID #971237, #971238.
2013-12-23 17:12:43 +01:00
unbit 05895c40f7 Merge pull request #493 from xrmx/setns_array2
core: setns_fds is an array on stack
2013-12-23 08:09:53 -08:00
Riccardo Magliocchetti fbf9a5b27c uwsgi_app.chdir is an array
So check if it's first member is not 0 instead.

Fix Coverity CID #971000, #970998.
2013-12-23 16:53:41 +01:00
Riccardo Magliocchetti 9c84e9f6cc core: setns_fds is an array on stack
So it makes not sense to check if it's set to something. Instead
check just check setns_fds_count.

Reported by Coverity as CID #1142188, #1142187.
2013-12-23 16:45:58 +01:00
unbit 486796bdf9 Merge pull request #491 from xrmx/coverity2312-3
Coverity2312 3
2013-12-23 05:09:03 -08:00
Riccardo Magliocchetti e795cd8912 plugins/python: fix uwsgi_python_harakiri error handling
Fixes close with a negative fd.

Reported by Coverity as CID #970996.
2013-12-23 13:43:02 +01:00
Riccardo Magliocchetti 643fc3019b plugins/corerouter: check return value of bind_to_unix_dgram
Reported by Coverity as CID #1142187
2013-12-23 13:19:00 +01:00
Riccardo Magliocchetti f409e8b501 core/hooks: fix typo
which leds to coverity issues :)

Reported by Coverity as CID #1142190 and #1142186
2013-12-23 13:09:06 +01:00
Unbit 361ec8bcd4 fixed sni delete 2013-12-23 13:08:31 +01:00
Riccardo Magliocchetti ba3ac9ad09 yaml: fix memory leak
Reported by Coverity as CID #971051.
2013-12-23 13:07:43 +01:00
Riccardo Magliocchetti 419f1801cd core/ns: fix resource leak
Reported by Coverity as CID #1142191
2013-12-23 12:56:08 +01:00
unbit d3c5ccc061 Merge pull request #490 from xrmx/coverity2312-2
master: fix a couple of resource leaks
2013-12-23 03:40:15 -08:00
Riccardo Magliocchetti be6f61aa1b master: fix a couple of resource leaks
Reported by Coverity as CID #1141954
2013-12-23 12:18:26 +01:00
Roberto De Ioris eb6c35aa95 fixed #488 2013-12-23 02:56:49 +01:00
Roberto De Ioris 797b14b23e fixed #487 2013-12-23 02:24:01 +01:00
unbit 44e7be13e2 Merge pull request #485 from prymitive/typo
Few typos in cheaper plugin
2013-12-22 03:30:29 -08:00
Łukasz Mierzwa 18f6660603 typos in cheaper plugin 2013-12-22 12:23:22 +01:00
Unbit c3f64af2df implemented private hooks 2013-12-22 11:14:52 +01:00
Unbit 2278f98318 fixed writen and append 2013-12-22 08:53:29 +01:00
Unbit b4ee27b524 added chown2 hook 2013-12-22 06:20:54 +01:00
Unbit 85ee422dcb added non-tolerant chown hook 2013-12-22 06:04:20 +01:00
Unbit 15f70b2444 fix first retry in harakiri mode 2013-12-22 05:50:45 +01:00
Unbit b7b126e89f git push added append and appendn 2013-12-22 05:24:49 +01:00
Unbit 56e284e18a added writen hook 2013-12-21 09:28:25 +01:00
Unbit 0d4f4a2411 added chmod hook 2013-12-21 08:21:17 +01:00
Unbit 68049a5177 more solid log rotation 2013-12-21 08:11:35 +01:00
Unbit fc2355e5be added putenv hook 2013-12-21 07:21:34 +01:00
Unbit 49925e95d4 added mkdir hook 2013-12-20 17:39:22 +01:00
unbit bee171e5da Merge pull request #484 from xiaost-bytedance/master
fixed master fd leak when using tracebacker
2013-12-20 05:14:57 -08:00
xiaost df809c8e34 fixed master fd leak when using tracebacker 2013-12-20 21:02:31 +08:00
Unbit 3b64838324 fixed snprintf() usage all over the place 2013-12-20 08:54:27 +01:00
Unbit f1f51948eb close alarm fds on fork() 2013-12-20 08:16:36 +01:00
Unbit 906da5cb9a do not rely on unix signals to print request status during harakiri 2013-12-20 05:56:56 +01:00
Unbit dacad8d9b9 added magic vars for uid and gid 2013-12-19 17:06:49 +01:00
Unbit 39fbea6d48 added support for yajl library 2013-12-19 12:30:26 +01:00
Unbit 4796f85277 added UWSGI_PROFILE_OVERRIDE 2013-12-19 09:36:53 +01:00
Unbit 01ee66d1f6 simplify buildconf syntax for alternative implementation 2013-12-19 09:27:58 +01:00
Unbit 6c61ac9c7e added APPEND_CFLAGS support 2013-12-19 09:08:35 +01:00
Unbit 77c279b3a9 added rx and tx to subscription nodes 2013-12-18 07:31:53 +01:00
Unbit 34430ceac4 fixed gateway packet 2013-12-18 06:53:56 +01:00
Unbit fd1f79d154 fixed tuntap endianess 2013-12-17 21:31:03 +01:00
unbit 56f7d09b2b Merge pull request #483 from prymitive/sni_fix
sni support in corerouter stats requires ssl
2013-12-17 11:13:07 -08:00
unbit 479df7c2cc Merge pull request #482 from prymitive/idle_zero_mem
reset worker memory usage when --idle option kills it
2013-12-17 11:12:43 -08:00
Łukasz Mierzwa 69c41026a4 sni support in corerouter stats requires ssl 2013-12-17 20:07:02 +01:00
Łukasz Mierzwa 7a305704f1 reset worker memory usage when --idle option kills it, needed for #479 2013-12-17 20:03:53 +01:00
Unbit 8d44dff97e Merge branch 'master' of ssh://github.com/unbit/uwsgi 2013-12-17 06:51:05 +01:00
Unbit c9324c06ca implemented perl spooler and fixed a leak in the CPython one 2013-12-17 06:50:47 +01:00
unbit 3446c2d322 Merge pull request #481 from prymitive/metrics_avg_rt
2 small metrics fixes
2013-12-16 20:28:14 -08:00
Łukasz Mierzwa 6704d1a95a * add core.avg_response_time metric
* don't add worker 0 to total metrics
2013-12-16 22:33:57 +01:00
Unbit 0e539f25cd removed additional debug 2013-12-16 19:20:54 +01:00
Unbit 00eb37f724 improved credentials usage in tuntap 2013-12-16 17:47:49 +01:00
Unbit 30c6ac8cb8 allows gateway to drop privileges 2013-12-16 17:09:39 +01:00
Unbit faa13228a5 improved tuntap dynamic rules 2013-12-16 16:45:11 +01:00
Unbit e1941a49b8 added build profile for uwsgi.it 2013-12-16 15:44:14 +01:00
Unbit d32f7b997d allow unprivileged usage of setns 2013-12-16 15:23:50 +01:00
Unbit 972333941d added --jailed 2013-12-16 14:51:55 +01:00
Unbit 1691263744 added dynamic rules for tuntap devices 2013-12-16 13:52:22 +01:00
Unbit debfe5b2b9 added gateway support to tuntap router 2013-12-16 07:25:50 +01:00
Unbit d2ce28f441 added hostname hook 2013-12-15 19:28:20 +01:00
Unbit b9170b2c85 added credentials support to the tuntap router 2013-12-15 07:49:44 +01:00
Unbit 33a6195e44 improvements in SCM_CREDENTIALS subscription system 2013-12-15 06:31:33 +01:00
Unbit 933ef85cf2 SCM_CREDENTIALS are not available everywhere 2013-12-14 18:11:45 +01:00
Unbit 0b27d41712 fixed corerouter servername for sni 2013-12-14 18:00:23 +01:00
Unbit 2124b930fd subscription system can now create sni contexts 2013-12-14 17:54:19 +01:00
Unbit b5a2a89630 added api for passing credentials 2013-12-14 16:53:07 +01:00
Unbit 22bf9b33b0 added tuntaprouter stats 2013-12-14 16:16:28 +01:00
Unbit b44c2208d9 added nosuid mount support to linux 2013-12-14 14:22:02 +01:00
Unbit 44136aa572 added support for data mount option 2013-12-14 14:16:00 +01:00
Unbit 5dd62ef909 fixed #479 2013-12-14 13:37:38 +01:00
Unbit 5ea95c9e89 fixed a couple of memory leaks 2013-12-14 13:27:46 +01:00
Unbit 8095a9108c added setns() support 2013-12-14 10:43:27 +01:00
Unbit 1cbc423afc fixed 2 typos 2013-12-14 07:49:37 +01:00
Unbit 4e260fa8a1 fixed #476 and #477 2013-12-14 07:45:38 +01:00
Unbit bb4be12fda implemented more async api in lua 2013-12-13 11:51:05 +01:00
Unbit 672fb0eaa6 added --lua-gc-freq 2013-12-13 09:07:44 +01:00
Unbit def274f28c Merge branch 'master' of ssh://github.com/unbit/uwsgi 2013-12-13 07:35:48 +01:00
Unbit be9f1578cc prepare for --attach-daemon2 2013-12-13 07:35:32 +01:00
unbit 8d8f3bdc51 Merge pull request #474 from craigbruce/master
Minor typo
2013-12-12 11:28:35 -08:00
Craig Bruce 4d9720e4b5 Minor typo 2013-12-12 12:22:16 -07:00
Unbit 6e2adf9cf3 added support for async api to lua 2013-12-12 13:42:12 +01:00
Unbit 7f004c5d6d removed async_force_again from lua 2013-12-12 13:34:25 +01:00
Unbit 13e7b53c54 async_force_again 2013-12-12 13:33:37 +01:00
Unbit 1c89522519 added websocket api to lua 2013-12-12 11:16:38 +01:00
Unbit 3b4581a581 Merge branch 'master' of ssh://github.com/unbit/uwsgi 2013-12-12 03:57:30 +01:00
Unbit dfaa1d9313 1.9.21 2013-12-12 03:57:11 +01:00
unbit 795721b91e Merge pull request #473 from prymitive/stypo
fixed block check in subscriptions
2013-12-11 18:56:52 -08:00
Łukasz Mierzwa 6bd0095513 fixed block check in subscriptions 2013-12-11 20:21:09 +01:00
Unbit 38682590e9 added UWSGI_END_OF_OPTIONS macro 2013-12-11 11:38:32 +01:00
Unbit aa2a212be8 prepare for tomorrow release 2013-12-10 18:47:37 +01:00
Unbit 51714203a7 added var. logchunk 2013-12-10 17:19:58 +01:00
Unbit fbac57a903 fixed mongrel2 plugin 2013-12-10 15:55:11 +01:00
Unbit 768d1c4099 support platforms not exposing RTLD_NEXT 2013-12-10 13:13:24 +01:00
Unbit 82fa510030 fixed build on python 2.6 2013-12-10 12:04:52 +01:00
Unbit a6e6bff082 sharedarea can be mapped to generic objects 2013-12-10 10:09:38 +01:00
Unbit 304f847dc6 added sharedarea_update api 2013-12-10 09:06:27 +01:00
Roberto De Ioris 5bb7f02921 added memoryview wrapper for sharedarea and locking api 2013-12-10 07:33:45 +01:00
unbit 02ee60c6ef Merge pull request #472 from prymitive/ns_exit_on_reload
namespace init process should exit if exit-on-reload is enabled
2013-12-09 21:52:27 -08:00
Łukasz Mierzwa 4d3526a377 namespace init process should exit if exit-on-reload is enabled, fixes #471 2013-12-09 21:42:48 +01:00
Unbit ca9d1830bb refactored logchunks management 2013-12-08 05:43:21 +01:00
Unbit 4ff485d565 allow using RTLD_NEXT in symcall 2013-12-08 05:04:03 +01:00
Unbit 63d5c6afc9 added symcal routing action 2013-12-08 04:49:34 +01:00
Roberto De Ioris 3a36551d1f fix G_EVAL in coroae 2013-12-07 11:32:43 +01:00
Roberto De Ioris 26877e1da9 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-12-07 10:54:16 +01:00
Unbit d81330c514 support IO object is perl async mode too 2013-12-07 09:52:51 +00:00
Unbit 441013b71b added mule support for symcall and more robust check for psgi response 2013-12-07 09:07:42 +00:00
Unbit a6b9e653a4 fix plugin build time 2013-12-07 08:26:01 +00:00
Unbit c7161139e7 report build time even for plugins 2013-12-07 08:16:43 +00:00
Unbit ce07c1a454 report total build time 2013-12-07 07:33:38 +01:00
unbit 4eb3b76c35 Update README 2013-12-06 17:38:52 +01:00
unbit 3519fcbcc6 Update README 2013-12-06 17:37:51 +01:00
Unbit 70dd9fca32 allows building plugin from a single file 2013-12-04 21:33:27 +01:00
Unbit a573602171 added tmsecs and tmicros log vars 2013-12-04 12:56:31 +01:00
Unbit 29418654d7 added support for mountpoints in the symcall plugin 2013-12-04 12:03:47 +01:00
Unbit 31c31c4ce2 fixed read2 hook in non async mode 2013-12-03 22:52:51 +01:00
Unbit 0217766dd1 read2 hook for async mode 2013-12-03 22:25:30 +01:00
Unbit 3d15660407 added a skel hook for waiting for 2 file descriptors 2013-12-03 19:34:15 +01:00
Unbit 57ce416ae1 fixed unbit CPU smashing 2013-12-03 14:26:49 +01:00
Unbit 248a22b064 added another optimization for writev and a test for it 2013-12-02 07:01:44 +01:00
Roberto De Ioris 49c5206d86 fixed writev optimization 2013-12-02 04:58:08 +01:00
Unbit 5b17363b40 enable writev optimization by default 2013-12-01 09:11:33 +01:00
Unbit e6c3c04e64 completed vector based I/O 2013-12-01 08:47:43 +01:00
Unbit 9a36b2b891 added writev api 2013-12-01 08:12:32 +01:00
Roberto De Ioris bfd699dac5 another mjpeg fix 2013-12-01 05:44:36 +01:00
Unbit cc3e43eb3d fixed uwsgi_sharedarea_read 2013-12-01 04:40:39 +00:00
Unbit b934ac9588 refactored sharedarea read 2013-11-30 18:30:52 +00:00
Unbit 92b6c62cac improved mjpeg example 2013-11-30 15:43:17 +01:00
Unbit 46cceb0465 croak if the psgi streamer fails 2013-11-30 14:30:22 +00:00
Unbit f1b3522c2a allows building coroae on raspberrypi 2013-11-30 13:49:21 +00:00
Unbit c99f5d0875 fixed sharedarea_wait perl api 2013-11-30 12:46:17 +01:00
Unbit b972c2d6bb another round of non-blocking optimizations 2013-11-30 12:33:24 +01:00
Unbit d226f65890 optimized sendfile 2013-11-30 12:23:13 +01:00
Unbit 60b54c4d7c allows sending websockets messages directly from a sharedarea 2013-11-30 11:19:28 +00:00
Unbit ace79b1179 various websockets and sharedarea optimizations 2013-11-30 10:41:56 +00:00
Roberto De Ioris 9993e3710c first attempt of uwsgi_sharedarea_readfast 2013-11-30 07:31:57 +01:00
Roberto De Ioris 98541dbc65 more sharedarea improvements 2013-11-30 07:23:05 +01:00
Roberto De Ioris cabb6d72d9 added uwsgi.websocket_send_binary_message to cpython 2013-11-30 06:49:15 +01:00
Roberto De Ioris 217f2f99ff added declarations for sharedarea api 2013-11-30 06:47:52 +01:00
Unbit 890e0004b6 fixed signs in sharedarea 2013-11-29 17:28:05 +01:00
Unbit d17d947cd1 added dec variants for sharedarea 2013-11-29 17:21:15 +01:00
Unbit a69c775cd5 added inc variants for sharedarea 2013-11-29 17:17:36 +01:00
Unbit 4c051d90ed split setup from running for easy library integration 2013-11-29 17:07:11 +01:00
Unbit f55c52eaff added milliseconds hook support for rbthreads 2013-11-29 16:47:33 +01:00
Unbit 88b5f968a4 added milliseconds hook support to gevent 2013-11-29 16:43:07 +01:00
Unbit 6fdeecce0f added milliseconds wait hook to Coro::AnyEvent 2013-11-29 16:33:39 +01:00
Unbit f6923728d8 more sharedarea api functions 2013-11-29 16:07:27 +01:00
unbit cf96783dce Merge pull request #468 from xrmx/coverity2911
Coverity Fixes
2013-11-29 06:34:36 -08:00
Unbit e4d3d209c8 allows sharedarea_wait to specify the freq 2013-11-29 13:32:30 +00:00
Unbit 5182eaf485 another round of sharedarea implementations 2013-11-29 12:47:59 +00:00
Roberto De Ioris 082d47e156 area is a better field name for sharedarea 2013-11-29 07:46:28 +01:00
Roberto De Ioris 0715031b00 prepare for the new sharedarea api 2013-11-29 07:39:12 +01:00
Unbit 27c3532617 added S master fifo command 2013-11-28 11:36:28 +01:00
Roberto De Ioris cb1370b148 avoid allocating memory structures for fd monitoring and timeouts when non-plain async mode is in place 2013-11-28 07:12:38 +01:00
Roberto De Ioris 9cc58a3c13 avoid segfault when async mode api is called without async mode 2013-11-28 07:00:18 +01:00
Roberto De Ioris 150f0c631e fixed plain (without suspend engine) async mode 2013-11-28 06:47:36 +01:00
Roberto De Ioris 0574a120bc ported mjpeg stream to newer osx 2013-11-28 06:04:15 +01:00
Unbit c6550ece68 added as-mule hook 2013-11-27 16:01:49 +01:00
Unbit e76a40530b in request context uwsgi_req_error should always be used 2013-11-26 09:41:15 +01:00
Unbit 31c73ce298 report request data in writers and readers 2013-11-26 09:33:02 +01:00
Unbit b304766718 added werr, rerr and ioerr to logvars 2013-11-26 07:20:36 +01:00
Unbit 0ab1cfacc9 added read errors counters and --log-ioerror 2013-11-26 07:13:07 +01:00
Riccardo Magliocchetti b1f06bce32 plugins/rpc_plugin: check return value of uwsgi_response_prepare_headers
Reported by Coverity as CID #1100798.
2013-11-23 16:18:09 +01:00
Riccardo Magliocchetti 347ef1a5bf plugins/router_hash: Avoid possible divide by zero
Reported by Coverity as CID #1100804.
2013-11-23 16:05:56 +01:00
Unbit b4d9eb4f73 various fifo improvements 2013-11-23 08:01:56 +01:00
Unbit f44a36900a added unlink command 2013-11-23 07:48:50 +01:00
Unbit b6c969254d added accepting once variant 2013-11-23 07:40:53 +01:00
Unbit c5003561dd added write hook 2013-11-23 07:35:08 +01:00
Unbit 18dead4cd2 added hook-accepting1 2013-11-23 07:31:20 +01:00
Unbit 62aee259fa prepare for 1.9.21 2013-11-23 05:11:02 +01:00
Unbit 69c49f713e remove zeromq from build profiles 2013-11-23 05:09:50 +01:00
Unbit 08525a91ee reverted gccgo argv_list free 2013-11-23 04:59:12 +01:00
unbit 40fee74a5f Merge pull request #464 from xrmx/coverity2211
Fix a couple of memory leaks
2013-11-22 19:56:37 -08:00
unbit 6d8f179863 Merge pull request #465 from xrmx/coverity2211-2
core: Fix unintentonal integer overflow
2013-11-22 19:52:40 -08:00
Riccardo Magliocchetti d0b3c442c1 core: Fix unintential integer overflow
The expression would be evaluated as 32bit unsigned before
promoting to 64bit unsigned so cast the strtoul return value to
avoid integer overflows. Please note that the value passed here
comes from the user.

Reported by Coverity as CID #971244.
2013-11-22 20:13:54 +01:00
Riccardo Magliocchetti de82b58952 plugins/gccgo: fix memory leak
Reported by Coverity as CID #1128440
2013-11-22 19:44:04 +01:00
Riccardo Magliocchetti eb33fa7b19 core/config: fix memory leak
Reported by Coverity s CID #1128441
2013-11-22 19:32:56 +01:00
Unbit 9dde5f9d82 completed error pages 2013-11-22 18:53:05 +01:00
Unbit 036df0e5ff fixed fd leak in error pages 2013-11-22 18:52:02 +01:00
Unbit 1154aa8ddc added accepting hook 2013-11-22 18:46:07 +01:00
Unbit 3371dd2f94 added error-page management 2013-11-22 18:42:30 +01:00
unbit 06791376af honour CFLAGS and LDFLAGS in embedded builder 2013-11-22 09:22:08 +01:00
Roberto De Ioris 30e0af3826 only GCC_LIST and NAME are required 2013-11-22 06:45:14 +01:00
Unbit e4903ee0bf first working prototype of embedded plugins builder 2013-11-21 15:29:30 +01:00
Unbit 859c386b40 improved --extra-plugin 2013-11-21 14:54:42 +01:00
Unbit b83fecf4d3 another step for embedded plugins builder 2013-11-21 14:37:58 +01:00
Unbit 25dc608fa3 prepare for embedded plugins builder 2013-11-21 14:10:41 +01:00
Roberto De Ioris c01cf1f6be added accepting and ready state to the Emperor 2013-11-21 06:39:23 +01:00
Roberto De Ioris 9825f95ed5 improved chain reloading 2013-11-20 18:47:55 +01:00
Unbit 36143381e1 tiny uwsgi.h refactoring 2013-11-20 05:28:32 +01:00
unbit 8c25bafc73 Merge pull request #462 from Kapishin/master
Fix few typos
2013-11-19 01:46:12 -08:00
Pavlo Kapyshin 826f49c010 Fix few typos 2013-11-19 11:28:50 +02:00
Unbit 8b006c0874 support timerfd_create/timerfd_settime on __arm__ 2013-11-18 16:34:45 +01:00
Unbit 5806c333f5 do not spit errors on non x86 timerfd_create 2013-11-18 16:21:36 +01:00
Unbit e606d1e5d1 removal of embedded zeromq api 2013-11-18 11:11:46 +01:00
Unbit ec954b8aa7 fixed v8 RPC 2013-11-17 07:02:21 +01:00
Unbit 95d20e9f48 add rack to gemspec 2013-11-17 06:44:16 +01:00
Unbit 165aad8cd0 Merge branch 'master' of ssh://github.com/unbit/uwsgi 2013-11-17 06:42:04 +01:00
Unbit 29c339a3c3 gemspec for 1.9.20 2013-11-17 06:41:46 +01:00
unbit 12afba035b Merge pull request #460 from Kapishin/master
Fix typos
2013-11-16 09:01:33 -08:00
Pavlo Kapyshin eeb203afd4 Fix typos 2013-11-16 17:41:26 +02:00
Roberto De Ioris 2ccdd0fb67 fixed zeromq support 2013-11-15 07:46:37 +01:00
Unbit 6a18d10c56 fixed typo in total_tx metric 2013-11-13 21:38:56 +01:00
Unbit d1383d7749 added multiplier and adder collector 2013-11-13 19:53:47 +01:00
Unbit 0abbabbe10 added accumulator metrics collector 2013-11-13 19:51:22 +01:00
Roberto De Ioris ea44525c22 fixed zeromq support 2013-11-15 07:48:49 +01:00
Unbit 2396c7cf31 prepare for 1.9.20 2013-11-13 15:14:51 +01:00
Roberto De Ioris 4805a9c219 added chunked input api to psgi 2013-11-14 07:44:13 +01:00
Roberto De Ioris 882cdcc2b6 added --plshell and Perl uwsgi::rpc 2013-11-14 06:24:56 +01:00
unbit 59c8bb51b4 Merge pull request #454 from xiaost-bytedance/master
fixed master hang when gracefully reloading in lazy mode
2013-11-13 08:50:52 -08:00
xiaost 3c2350f5ad fixed master hang when gracefully reloading in lazy mode 2013-11-14 00:33:49 +08:00
Unbit 422e958fe3 added uwsgi over SSL 2013-11-13 04:46:27 +01:00
Unbit 4d9c7809d6 added support for proxy protocol 2013-11-13 03:20:55 +01:00
Unbit 6b3d8ea146 added avg metrics collector 2013-11-13 02:41:47 +01:00
Unbit b5d8538fe8 added oid metric in stats 2013-11-12 17:48:48 +01:00
Unbit 47796b315e fixed stupid bug in websocket perl example 2013-11-12 12:38:22 +01:00
Unbit 222bcd8fdc another fix for default app 2013-11-12 12:22:54 +01:00
Unbit f92b800a7c fixed default app usage 2013-11-12 12:18:31 +01:00
Unbit dec2b234f8 fixed no default app 2013-11-12 12:14:15 +01:00
Unbit 3dbd7e3115 fixed comments in websockets_chat.pl 2013-11-12 08:50:50 +01:00
Unbit 09d8747918 added tests/websockets_chat.pl 2013-11-12 08:48:49 +01:00
Unbit fa78fd915b force https to on when --https-socket is in place 2013-11-12 05:59:10 +01:00
Unbit db56141485 completed --https-socket 2013-11-12 05:54:47 +01:00
Unbit 7685af4652 pluginized the socket protocols 2013-11-12 05:44:52 +01:00
unbit 21cb62db6c Merge pull request #452 from Kapishin/master
Fix typos
2013-11-11 20:15:07 -08:00
Pavlo Kapyshin c62aa8e7ed Fix typos 2013-11-11 23:05:30 +02:00
unbit 4765965d8e Merge pull request #451 from xrmx/coverity1111
build/coverity: remove broken erlang plugin
2013-11-11 10:14:08 -08:00
Riccardo Magliocchetti 556feaef2c build/coverity: remove broken erlang plugin 2013-11-11 19:11:20 +01:00
Unbit 799b8a22e0 improved content_type detection for rpc-path_info bridge 2013-11-11 15:50:11 +01:00
Unbit 2336580164 more rpc fixes 2013-11-11 15:09:13 +01:00
Unbit ca4f30c003 fixed rpc 64bit networking extension 2013-11-11 14:52:22 +01:00
Unbit d7d0a71d87 completed rpc 64bit network client 2013-11-11 14:42:28 +01:00
Unbit 44b92f1578 implemented 64bit extension for rpc protocol 2013-11-11 14:08:26 +01:00
Unbit abed95362f another series of rpc 64bit fixes 2013-11-11 13:46:00 +01:00
Unbit 72ecc217f7 perl passes the 64bit rpc test 2013-11-11 13:43:21 +01:00
Unbit 1405d01d50 pypy passes 64bit rpc local test 2013-11-11 13:24:08 +01:00
Unbit def65c4793 fixed python, perl and ruby rpc 64bit 2013-11-11 13:06:16 +01:00
Unbit 26386909de first attempt of moving rpc output from 16 to 64 bit 2013-11-11 13:00:20 +01:00
Unbit 2d4e04059a uwsgi.go low-level optimizations and implementation of uwsgi.CacheGet 2013-11-11 12:18:43 +01:00
unbit ac557739c2 allows monolithic gccgo to run on 32bit 2013-11-11 11:00:33 +01:00
Unbit 73bfc20ba1 added connection_fd to rack plugin 2013-11-11 09:12:52 +01:00
Unbit 6d5ae96d50 hack for adding an empty DEBUG section to the uwsgi core binary 2013-11-11 09:04:48 +01:00
Unbit 20b5b7b0dc added support for uwsgi::connection_fd and psgix.io 2013-11-11 08:22:01 +01:00
Unbit 82c5afd0c7 forgot PROFILE in Makefile 2013-11-11 06:12:32 +01:00
Unbit ec14f5b0fe Merge branch 'master' of ssh://github.com/unbit/uwsgi 2013-11-11 05:45:06 +01:00
unbit d93bdcb7b4 Merge pull request #450 from awentzonline/patch-1
Fixed spelling of error message in pyloader.c
2013-11-10 20:55:22 -08:00
Unbit b68ffc842d prepare for gccgo docs 2013-11-11 05:44:51 +01:00
Adam Wentz 0326c1d508 Fixed spelling of error message in pyloader.c 2013-11-10 14:08:41 -06:00
Unbit 42f45bfbf9 erlang plugin is broken 2013-11-10 08:27:44 +01:00
Unbit d018d3af99 pyerl plugin is broken 2013-11-10 08:27:23 +01:00
Unbit 42afc476d7 improved gccgo monolithic build 2013-11-10 08:26:14 +01:00
Unbit b5037d3f0f sanitize gccgo environment 2013-11-10 07:54:13 +01:00
Unbit 065dd7cfff return after grace_them_all 2013-11-10 06:49:02 +01:00
unbit 7909e092b5 Merge pull request #449 from xrmx/coverity0911-2
More coverity fixes
2013-11-09 21:52:49 -08:00
Unbit 9da53f5fd4 improved gccgo signal handling and added --timer and --rbtimer commodity options 2013-11-10 06:42:46 +01:00
Unbit 025cb7744e implemented goroutines timeout 2013-11-10 05:55:54 +01:00
Unbit e48a3ff1b7 added %k magic vars (number of cpu cores) 2013-11-10 04:51:25 +01:00
Unbit 2be371003c added %t and %T magic vars 2013-11-10 04:36:14 +01:00
Unbit 60d940e301 added simple math and concat to placeholders 2013-11-10 04:27:26 +01:00
Unbit 96c56cd8d5 added simple math routing actions 2013-11-10 03:30:33 +01:00
Unbit 4184619f7b removed snapshotting old feature 2013-11-10 02:59:15 +01:00
Unbit 50a8ec8a19 removed matheval flag, added generic matheval plugin and startin 1.9.20 development cycle 2013-11-10 02:53:08 +01:00
Unbit 79c702278a fixed async queue full condition in goroutine mode 2013-11-10 02:42:00 +01:00
Unbit 8fc41a4c85 remove useless gccgo code 2013-11-09 18:45:57 +01:00
Unbit 9c6455252d avoid GC to destroy go request env 2013-11-09 18:22:36 +01:00
Unbit 83e41844f3 first hardcore commit for supporting gccgo coroutines 2013-11-09 17:28:06 +01:00
Riccardo Magliocchetti 2cc17d6b11 core/logging: if we cannot reopen the log exit
This fixes passing negative fds to write and lseek.

Reported by Coverity as CID #1100807.
2013-11-09 16:15:49 +01:00
Riccardo Magliocchetti 14057b72c8 core: fix memory leak
Reported by Coverity as CID #1100813.
2013-11-09 16:08:47 +01:00
Riccardo Magliocchetti faf72b6a77 plugins/corerouter: fix memory leak
While at it reindent the code

Reported by Coverity as CID #1100818.
2013-11-09 16:05:41 +01:00
Riccardo Magliocchetti 963afa5174 core: fix memory leak
Reported by Coverity as CID #1100819
2013-11-09 15:46:05 +01:00
Unbit ce8ff8c45f fixed metric bug discovered by coverity 2013-11-09 15:15:32 +01:00
Riccardo Magliocchetti 5ae742e8e1 plugins/xslt: fail early if content_type is null
Fixes null pointer dereference.

Reported by Coverity as CID #1125161
2013-11-09 15:11:35 +01:00
Riccardo Magliocchetti 60f6572985 plugins/xslt: fix memory leak
Reported by Coverity as CID #1125168
2013-11-09 15:06:46 +01:00
Riccardo Magliocchetti 4ea34c63d2 plugins/servlet: Check uwsgi_jvm_exception return value
Reported vy Coverity as CID #1125169.
2013-11-09 15:04:47 +01:00
Riccardo Magliocchetti 5699d21aa7 metrics: add missing exit on error path
Fixed null pointer dereference.

Reported by Coverity as CID #1127337
2013-11-09 15:00:58 +01:00
Unbit dda8d25495 try to address EAGAIn body read problem 2013-11-09 13:17:17 +01:00
Unbit d4f690322c moved go to broken plugins 2013-11-09 13:01:28 +01:00
Unbit 4f2f30d1e5 improved gccgo plugin 2013-11-09 12:55:52 +01:00
Unbit d3b28e7956 more plugins for coveriti, fixed gccgo 2013-11-09 12:20:32 +01:00
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
Unbit cb603682e4 updated gemspec for the new release 2013-05-26 08:08:32 +02:00
Unbit c986a06bf7 more api functions in the uwsgi pypy module, it is enough for 1.9.11 2013-05-26 07:24:57 +02:00
Unbit e2843a6cee fixed static cache paths 2013-05-25 21:03:59 +02:00
Unbit ea1f239807 added memory offload 2013-05-25 20:01:26 +02:00
Unbit 8d7618146a fixed X-Sendfile + gzip 2013-05-25 18:07:41 +02:00
Unbit eb9e419bb0 fixed GC problem with pypy callback 2013-05-25 08:26:52 +02:00
Unbit f98f71ac26 added rbtimer and rpc/call to pypy 2013-05-25 08:09:09 +02:00
Unbit 03baaaebcb only import gevent.select in chat example 2013-05-24 20:41:51 +02:00
Unbit cbca954508 added tests/websockets_chat.py 2013-05-24 20:37:53 +02:00
Unbit 22ba6cc406 added uwsgi.lock/unlock to pypy and fixed --pypy-wsgi-file 2013-05-24 18:10:29 +02:00
Unbit 6bd172acb4 added preinit_apps hook in pypy 2013-05-24 06:59:13 +02:00
unbit 818ba4416f Merge pull request #295 from prymitive/cron_harakiri_fix
send sigkill to whole process group on cron harakiri
2013-05-23 06:50:45 -07:00
Łukasz Mierzwa adff12841c fixed harakiri for cron2 2013-05-23 15:40:02 +02:00
Łukasz Mierzwa 480c306591 send sigkill to whole process group on cron harakiri 2013-05-23 14:52:38 +02:00
unbit cbd1481cb7 Merge pull request #294 from prymitive/cron2
--cron2 option
2013-05-23 04:51:36 -07:00
Łukasz Mierzwa d1c1871222 --cron2 option 2013-05-23 13:44:13 +02:00
Unbit 15a94b8fb0 fixed a typo 2013-05-23 12:10:28 +02:00
unbit 66be54e6a7 Merge pull request #293 from prymitive/cron_stats
cron harakiri and stats
2013-05-23 03:46:24 -07:00
Łukasz Mierzwa 62c85cc2eb cron harakiri and stats 2013-05-23 12:25:02 +02:00
Unbit 1ae05a9ebc avoid loading pypy when python is already loaded 2013-05-23 12:02:35 +02:00
unbit 3457c70f30 Merge pull request #292 from prymitive/unique_crons
unique crons, fixes #227
2013-05-23 02:28:48 -07:00
Łukasz Mierzwa c1ec9126da unique crons, fixes #227 2013-05-23 11:09:56 +02:00
Unbit 398da2fac7 added 'harakiri' routing action 2013-05-23 08:52:19 +02:00
Unbit 47f33d6346 added --print-sym 2013-05-23 08:46:01 +02:00
Unbit 2cad82d537 removed support for SLOW pypy cpyext 2013-05-23 07:48:19 +02:00
Unbit 8d06d78537 preliminary support for GNU HURD 2013-05-23 07:43:01 +00:00
Unbit b61be000de added support for non-file object in pypy wsgi.file_wrapper 2013-05-23 07:03:41 +02:00
Unbit 9ca6de6e7a fixed #291 2013-05-23 06:51:59 +02:00
unbit 5c03c25e96 Merge pull request #237 from prymitive/cgroup_perms
allow setting cgroup dir mode
2013-05-22 05:23:42 -07:00
Roberta Giordano 23843163ad right fix for pipeline requests 2013-05-22 07:41:18 +02:00
Roberta Giordano 8b07fbbedc honour read() method if original file_wrapper object is not a file 2013-05-22 07:16:34 +02:00
Unbit 5bf55220d4 fixed python3 stdout/stderr line buffering 2013-05-21 14:19:33 +02:00
Unbit 0e1de3d6e8 added __name__ and sys.argv[0] in pypy setup script 2013-05-21 00:37:02 +02:00
Unbit 3a7ba3675b better sanity check for http requests 2013-05-20 23:44:05 +02:00
Unbit 5c0deb5bdb correctly handle pep333 exc_info in pypy 2013-05-20 23:31:14 +02:00
Unbit 50dcbc2b01 improved sendfile() on pypy 2013-05-20 23:21:08 +02:00
Unbit 90d72f7843 completed pep3333 vars for pypy 2013-05-20 21:35:02 +02:00
Unbit 90ee59c70d try to automatically set pypy home during compilation 2013-05-20 21:05:41 +02:00
Unbit 59eda11c1b Merge branch 'master' of https://github.com/unbit/uwsgi 2013-05-20 18:58:21 +02:00
Unbit 78684a424f support for http keepalive for request with body 2013-05-20 14:27:50 +02:00
unbit 4a936dda6e Merge pull request #289 from edevil/DropInvalid
Drop obvious invalid requests.
2013-05-20 03:04:14 -07:00
Andre Cruz 094d4b99a4 Drop obvious invalid requests. 2013-05-20 10:44:35 +01:00
Unbit 382268308e improved PYTHONPATH management 2013-05-19 23:40:49 +02:00
Unbit 97315d27b9 added osx support to pypy plugin 2013-05-19 23:33:49 +02:00
Unbit 26ae573b72 added cache_get,cache_update and cache_del to pypy 2013-05-19 22:40:47 +02:00
Unbit 803c44d783 added pypy management of .wsgi files and pythonpath manipulation 2013-05-19 22:33:42 +02:00
Unbit 90f3f1037a fixed a leak in uwsgi_get_app_id 2013-05-19 12:01:04 +02:00
Unbit ce39a751d9 improved uwsgi_get_app_id 2013-05-19 12:00:12 +02:00
unbit ceebf7d32d Merge pull request #288 from alex/pypy-cleanups
Some cleanups for the PyPy plugin:
2013-05-18 22:54:53 -07:00
Unbit 8da59bf0ac better __main__ setup in pypy 2013-05-19 07:52:31 +02:00
Unbit d25979502a better auto-detection of pypy paths 2013-05-19 07:45:21 +02:00
Unbit 549bc3bf9f added --pypy-eval --pypy-eval-post-fork --pypy-eval-exec --pypy-eval-exec-post-fork 2013-05-19 07:17:22 +02:00
Alex Gaynor 22b2f325e0 removed a method with a nonsense implementation 2013-05-18 22:09:24 -07:00
Alex Gaynor 6615d1b90c Catch a more precise error 2013-05-18 22:06:36 -07:00
Alex Gaynor 8f045c4254 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-05-18 22:06:04 -07:00
Alex Gaynor a4434349e5 whoops, a few small fixse 2013-05-18 22:03:55 -07:00
Unbit 01272be25f automatically detect pypy in setup.py 2013-05-19 07:02:05 +02:00
Alex Gaynor be0beed403 Some cleanups for the PyPy plugin:
a) pep8 and such
b) Made classes be newstyle
c) Made the classes be created once, not once per request
2013-05-18 21:59:37 -07:00
Unbit 453d2abed5 another micro optimization for pypy 2013-05-19 06:52:01 +02:00
Unbit 57e9ccbef0 added uwsgi.opt to pypy 2013-05-19 06:33:57 +02:00
Unbit 989124772b added wsgi.file_wrapper and improved import in pypy 2013-05-19 06:20:02 +02:00
Unbit 72400e4b91 completed wsgi.input for pypy 2013-05-19 05:33:53 +02:00
Unbit 900cba29a7 fixed python3 pyargv 2013-05-19 04:55:52 +02:00
Unbit f177a65c1e added uwsgi.add_file_monitor to pypy 2013-05-18 20:08:50 +02:00
Unbit b6baf9016d Merge branch 'master' of github.com:unbit/uwsgi 2013-05-18 20:02:37 +02:00
Unbit 86ac6e8044 implemented uwsgi.add_timer for pypy 2013-05-18 20:01:18 +02:00
unbit 66d8fb95db Merge pull request #286 from alex/patch-1
Fixed a clear typo.
2013-05-18 10:55:50 -07:00
Unbit 22da8d9ba2 optimized pypy environ helper 2013-05-18 19:45:18 +02:00
Alex Gaynor 819e9c1b16 Fixed a clear typo.
Only call writer once when the result of a WSGI application is a string.
2013-05-18 11:23:01 -06:00
Unbit dd4b2e8bc2 fixed a typo 2013-05-18 18:29:16 +02:00
Unbit e2f7ac2017 added --mule-msg-size 2013-05-18 18:28:50 +02:00
Unbit 31b5cf6926 fixed mule_msg 2013-05-18 17:52:23 +02:00
Unbit 25fe3035c2 fixed SCRIPT_NAME handling in python 2013-05-18 17:27:51 +02:00
Unbit 0cf56823cd added uwsgi.cache_get to pypy 2013-05-18 15:45:53 +02:00
Unbit c2f36968c3 trying to understand why multirheading is flaky on pypy 2013-05-18 12:17:43 +02:00
Unbit a508c7f53e added signal handling to pypy 2013-05-18 09:59:06 +02:00
Unbit 48de68031d more pypy implementations 2013-05-18 09:20:55 +02:00
Unbit 81ef85af82 added xmlrpc wrapper 2013-05-17 16:42:45 +02:00
Unbit 16b65d7dbe uwsgi RPC http wrapper 2013-05-17 15:45:43 +02:00
Unbit 5a98e6511b prepare for pypy multithreading 2013-05-17 14:28:42 +02:00
unbit 2418f08e22 Update README 2013-05-16 23:31:23 +03:00
Unbit 80a821bc20 updated pypy README 2013-05-16 18:09:36 +02:00
Unbit 378f78bd87 removed uwsgi.py 2013-05-16 18:03:35 +02:00
Unbit f010591e19 more WSGI vars 2013-05-16 17:58:15 +02:00
Unbit 5274abdcca fixed pypy environ 2013-05-16 17:30:29 +02:00
Unbit 48f9e8c5c8 improved PyPy plugin 2013-05-16 16:29:13 +02:00
unbit 5c02117fde Merge pull request #285 from fijal/master
A sketch for a PyPy plugin
2013-05-15 05:21:57 -07:00
Maciej Fijalkowski bc56a188f8 Add a copyright info 2013-05-15 14:18:47 +02:00
Maciej Fijalkowski b6df1b22ab flush the pypy debug file 2013-05-14 23:55:27 +02:00
Maciej Fijalkowski 0fbf2dd5bb Progress - now example wsgi runs 2013-05-14 23:32:05 +02:00
Unbit 38c126d11a fixed file action status 2013-05-14 16:49:22 +02:00
Unbit 7dff602e5e try to fix retry engine 2013-05-14 16:43:44 +02:00
Maciej Fijalkowski e401f32815 This was indeed temporary 2013-05-14 15:19:04 +02:00
Maciej Fijalkowski 12e94b70a7 Merge github.com:fijal/uwsgi 2013-05-14 15:06:48 +02:00
Maciej Fijalkowski 884de3959c initial checkin of pypy plugin 2013-05-14 15:04:17 +02:00
Unbit fe12325e50 fixed goto and pc in error and final routing 2013-05-14 12:19:17 +02:00
Unbit bea86f3f79 fixed a typo 2013-05-13 18:55:48 +02:00
unbit 7a5f3667da Merge pull request #280 from xrmx/warn-ini
core: print a warning if the configuration section can't be read
2013-05-13 07:35:20 -07:00
Riccardo Magliocchetti 0813788c98 core: print a warning if the configuration section can't be read
Fixes #278
2013-05-13 16:21:30 +02:00
Unbit b1ca73e7f0 added file-next action 2013-05-13 07:33:05 +02:00
Unbit ebf9e9b1a3 added ignore_body flag 2013-05-13 07:19:12 +02:00
Unbit b0abab7a1d fixed #277 2013-05-12 22:57:07 +02:00
Unbit 995bb493df preliminary implementation of error routing 2013-05-12 22:48:10 +02:00
Unbit 1b2375fc84 added error routes 2013-05-12 18:02:33 +02:00
Unbit b7315bcb5a added "file" routing action 2013-05-12 17:36:40 +02:00
Unbit 2c9ebdaa69 updated gemspec for 1.9.10 2013-05-11 17:12:00 +02:00
Unbit fbd9e5b4d7 goroutines support must be completely rewritten :( 2013-05-11 16:57:41 +02:00
unbit b9a3425b6d Merge pull request #276 from prymitive/build_fixes
better check for default value, this allows using false or empty string ...
2013-05-11 02:53:56 -07:00
Łukasz Mierzwa d4742c611b better check for default value, this allows using false or empty string as defaults 2013-05-11 11:43:29 +02:00
Unbit c645a590aa added goroutine reference to gccgo 2013-05-11 08:43:46 +02:00
Unbit 275a7fe63f added --go-args 2013-05-11 08:26:02 +02:00
unbit 0ff16d8312 Merge pull request #275 from prymitive/df
fixed legion-smart-attach-daemon2
2013-05-10 14:21:42 -07:00
Łukasz Mierzwa 1cb31d6c7e fixed legion-smart-attach-daemon2 2013-05-10 20:51:39 +02:00
Unbit 8a6eb553df fixed attach-daemon 2013-05-10 17:20:44 +02:00
Unbit 946af8b9ee added errorlimiter.ini example config 2013-05-10 15:15:51 +02:00
Unbit 098a1f647e added final routes or running rules at the end of the request 2013-05-10 15:08:33 +02:00
Unbit c9681dc430 Merge branch 'master' of github.com:unbit/uwsgi 2013-05-10 08:18:33 +02:00
Unbit ff0b8b2d53 fixed #274 2013-05-10 08:17:54 +02:00
unbit 75f520d43a Merge pull request #255 from prymitive/airbrake_fixes
few airbrake fixes
2013-05-09 11:52:29 -07:00
Unbit 65209748ba completed the first phase of the gccgo plugin 2013-05-09 19:55:27 +02:00
Unbit cd604ef07b extended the build system to support .o files and added preliminary gccgo plugin 2013-05-09 18:38:53 +02:00
Łukasz Mierzwa 51da8bc531 * report more data in airbrake plugin
* preserve text version of backtrace (there might be multiple alarm handlers for any segfault)
* fix reload errors
2013-05-09 15:44:29 +02:00
Unbit 2374ba12bd better file descriptor management for alarm threads 2013-05-09 15:17:57 +02:00
Unbit 0a75aaec25 added the uwsgi_takeover commodity function 2013-05-09 13:53:22 +02:00
Unbit a8c286ae83 prepare for gccgo integration 2013-05-09 11:43:01 +02:00
Unbit 9cbdfc7764 updated gemspec for 1.9.9 2013-05-08 17:48:41 +02:00
Unbit cb1423436f fixed radius-next 2013-05-08 16:30:32 +02:00
Unbit 2fb391795a added symcall-post-fork 2013-05-08 13:29:21 +02:00
Unbit 9ec20f2d8f allows cache math from the routing subsystem 2013-05-08 11:00:23 +02:00
Unbit 9323ca5136 added cache math api to python 2013-05-08 10:34:34 +02:00
Unbit 978e6072ab prepare for math operations in cache 2013-05-08 09:41:24 +02:00
Unbit d0e3869d54 fixed go arguments on osx 2013-05-07 16:35:34 +02:00
unbit 15c7e956f2 Merge pull request #270 from prymitive/numleaks
2 small memory leaks valgrind complains about
2013-05-07 07:01:11 -07:00
Łukasz Mierzwa ed61545ec7 2 small memory leaks valgrind complains about 2013-05-07 15:54:35 +02:00
Unbit 1aac5becdc added --touch-exec 2013-05-07 15:14:09 +02:00
Unbit 4bca26debc added the radius plugin 2013-05-07 14:38:44 +02:00
Unbit d6eecd1637 report gateway harakiri 2013-05-07 13:41:40 +02:00
unbit 00e7620d2e Merge pull request #269 from prymitive/legion_daemons
legion daemons
2013-05-07 03:36:25 -07:00
Łukasz Mierzwa d657283aad legion daemons 2013-05-07 12:09:26 +02:00
Unbit 70a879ea94 added incache routing condition 2013-05-07 11:56:18 +02:00
Unbit 591ee22472 fixed support for go 1.1rc2 2013-05-07 11:11:25 +02:00
Unbit 956b05d39d Merge branch 'master' of github.com:unbit/uwsgi 2013-05-07 10:02:00 +02:00
Roberto De Ioris 5bdad6d4cb support for go 1.1 on osx 2013-05-07 04:36:05 +02:00
unbit 29a6ac6ed7 Merge pull request #267 from prymitive/log_retries
log retry count on router error
2013-05-06 09:16:07 -07:00
Łukasz Mierzwa 8f7f091e9b log retry count on router error 2013-05-06 16:20:04 +02:00
Unbit 63dfe7628b added uwsgi_connect_udp 2013-05-06 15:22:13 +02:00
Unbit ce507e7851 try to fix multithread + dynamic mode 2013-05-04 15:44:44 +02:00
Unbit a9cd76173e added default app for psgi 2013-05-04 15:41:12 +02:00
Unbit 44f8ffb434 another fix in spnego 2013-05-04 15:27:40 +02:00
Unbit 28c395f111 it looks like both MIT krb5 and heimdal leaks memory... 2013-05-04 15:14:17 +02:00
Unbit 39df68c38e better next support for spnego 2013-05-04 13:49:32 +02:00
Unbit b33ca9225a improved route-if regexp to store vectors 2013-05-04 13:36:09 +02:00
Unbit bd137afecf fixed thread bug with routing regexp vectors 2013-05-04 12:39:08 +02:00
Roberta Giordano a3b9bed8c2 fixed spnego build 2013-05-04 08:37:55 +02:00
Unbit 0a157739bc Merge branch 'master' of github.com:unbit/uwsgi 2013-05-04 08:11:37 +02:00
Unbit c46b08ad5e completed spnego plugin 2013-05-04 08:11:19 +02:00
unbit 754e6193a4 Merge pull request #265 from ttreptow/master
Fix mule farm initialization
2013-05-03 12:03:26 -07:00
Tim Treptow 56b49fe2dd fix mule farm initialization 2013-05-03 09:40:10 -07:00
Unbit 36a7215f94 added setscriptname and donotlog routing actions 2013-05-03 17:49:06 +02:00
Unbit 702247affd spnego plugin is almost ready 2013-05-03 17:44:21 +02:00
Unbit e752b1f8e5 added Graham credits 2013-05-03 10:21:15 +02:00
Unbit 920eee36e3 fixed a wrong cast in gevent plugin 2013-05-02 17:28:06 +02:00
unbit a5070a5d98 Merge pull request #262 from edevil/master
Call atexit hook after all requests are done, or immediately if there are no requests
2013-05-02 08:24:57 -07:00
Unbit ccb5aefa61 do not use the stack on ldapauth filter generation 2013-05-02 16:50:55 +02:00
Unbit 378b08e37c fixed a memory leak in ldapauth 2013-05-02 16:48:04 +02:00
Unbit 5763483c91 avoid using deprecated apis in the ldap plugin 2013-05-02 15:54:45 +02:00
Andre Cruz 559f8ee095 Call atexit hook when we want to graceful reload and there are no requests being served. Otherwise call it when the last request finishes. 2013-05-02 14:36:50 +01:00
Unbit 4382ef360c Merge branch 'master' of github.com:unbit/uwsgi 2013-05-02 15:12:07 +02:00
Unbit 0cb576cf1a added ldap to all buildconf 2013-05-02 15:11:57 +02:00
unbit dee4d047b4 Merge pull request #261 from prymitive/ldapauth1
remove useless reconnect
2013-05-02 06:11:25 -07:00
Łukasz Mierzwa 2520cc7bb9 remove useless reconnect 2013-05-02 12:24:11 +02:00
unbit 192c31efe0 Merge pull request #257 from prymitive/router_ldapauth
router_ldapauth plugin with simple bind support
2013-05-02 02:54:23 -07:00
Łukasz Mierzwa a1d8ebc2d2 router_ldapauth plugin with simple bind support 2013-05-02 11:47:31 +02:00
Unbit 14a9de2147 spnego authentication is still broken 2013-05-02 10:17:28 +02:00
Unbit a760a9a3f1 ported the xslt plugin to the new api 2013-05-02 10:04:04 +02:00
Unbit efd14e1c7a added cookie-based authentication test 2013-05-02 09:34:31 +02:00
Unbit 6019c46cee removed the GOON routing return value 2013-05-02 08:45:37 +02:00
Unbit ec6acfbc1c improved transformation system 2013-05-01 19:36:13 +02:00
Unbit e925dbaad6 other gzip improvements 2013-05-01 12:04:41 +02:00
Unbit 8321adf0bc completed chunked transformation 2013-05-01 10:21:35 +02:00
Unbit e1c5e9e874 prepare for gzip streaming 2013-05-01 10:05:39 +02:00
Unbit 0aec581714 prepare for streaming transformations 2013-05-01 09:56:56 +02:00
Unbit b77b8623d1 added a simple dumper for REPORT method 2013-04-30 18:49:58 +02:00
Unbit 5ab986d6d9 send only requested webdav props 2013-04-30 11:41:16 +02:00
Unbit 09b8332236 prepare for caldav support 2013-04-29 21:42:46 +02:00
Unbit d05345abc0 added current-user-privilege-set 2013-04-29 15:06:37 +02:00
Unbit 804c369f0d toward programmable webdav, carddav support ensured 2013-04-29 14:42:04 +02:00
Roberta Giordano 8f67fc886c added support for OSX xattr in WebDAV plugin 2013-04-28 11:37:20 +02:00
Roberta Giordano ca3b1a9b30 support for OSX in the webdav plugin 2013-04-28 11:24:07 +02:00
Unbit 63c1dbb3ed windows-webdav compatibility fix 2013-04-28 11:16:44 +02:00
Unbit 9a424dfe29 prepare for webdav locking 2013-04-28 10:07:36 +02:00
Unbit 0a6eb596bb completed PROPPATCH 2013-04-28 09:46:10 +02:00
Unbit 34452376db added PROPFIND + xattr in the webdav plugin 2013-04-28 08:31:47 +02:00
Unbit 53a90a59c5 added xattr plugin 2013-04-27 19:01:09 +02:00
Unbit ec491ebd83 added the WebDAV plugin (beta) 2013-04-27 18:24:21 +02:00
Unbit cdc41c305e improved url encoding api 2013-04-27 11:45:48 +02:00
Unbit 6cf67b399c new api functions for http headers 2013-04-27 09:10:11 +02:00
unbit dc3c56bccc Merge pull request #253 from prymitive/alarm_airbrake_plugin
airbrake plugin
2013-04-26 07:55:23 -07:00
Łukasz Mierzwa 4657f2039a airbrake plugin 2013-04-26 16:29:18 +02:00
Unbit b0082fbd0d added --alarm-segfault 2013-04-26 15:09:04 +02:00
Unbit ede1b4df11 fixed initial flush 2013-04-26 08:36:41 +02:00
unbit d78a3d1f8a Merge pull request #247 from prymitive/cache_sync_fix
fixed cache sync parsing
2013-04-25 05:44:08 -07:00
Unbit 6152555f26 another fix in python async mode 2013-04-25 14:43:40 +02:00
Unbit bbad505044 fixed python async mode with the improved api 2013-04-25 14:28:38 +02:00
Łukasz Mierzwa 11c5429184 fixed cache sync parsing - uwsgi_hooked_parse() was getting invalid data lenght 2013-04-25 14:28:18 +02:00
Unbit 4e865c4525 fixed stackless + threads 2013-04-25 14:03:40 +02:00
Unbit 2fa785a539 improved fiber support 2013-04-25 13:51:05 +02:00
Unbit 296a8449c9 improved stackless plugin 2013-04-25 13:46:30 +02:00
Unbit f20213ff10 various async/green mode improvements and fixes 2013-04-25 11:33:45 +02:00
Unbit 8a7067ee24 added routing support to coroae and fixed backtrace-depth 2013-04-25 09:09:46 +02:00
Unbit a3024e9f5a refactored async mode 2013-04-25 08:57:58 +02:00
Unbit 86e651f5e7 call gevent atexit hook before destroying uwsgi-related greenlets 2013-04-25 07:09:39 +02:00
unbit 409710b2b1 Merge pull request #245 from prymitive/dont_count_tx_on_pings
don't increment tx counter on requests that should not be accounted
2013-04-24 04:27:27 -07:00
Łukasz Mierzwa 14a406a276 don't increment tx counter on requests that should not be accounted (ping plugin requests) 2013-04-24 10:57:05 +02:00
Unbit 28a283b1c1 added uwsgi.atexit management to gevent 2013-04-23 21:20:42 +02:00
Unbit ccf298a148 updated gemspec 2013-04-23 14:29:45 +02:00
Unbit 914b600af4 prepare for 1.9.8 2013-04-23 14:27:47 +02:00
Unbit 4944994667 fixed #244 2013-04-23 14:27:08 +02:00
Unbit 3a487578a5 remove annoying logline in async mode 2013-04-23 10:10:13 +02:00
Unbit 39eeccb16a refactored async runqueue management 2013-04-23 10:02:36 +02:00
Roberta Giordano 32acd3b9d1 added the flush instruction 2013-04-23 07:07:53 +02:00
Roberta Giordano c57baae477 mime route var has to take variables 2013-04-23 06:46:47 +02:00
Unbit 4a6ed633b9 added hex and base64 routing vars 2013-04-22 16:36:46 +02:00
Unbit 2ab1845547 prepare gemspec for 1.9.7 2013-04-22 15:36:13 +02:00
Unbit f4d2e1f20c added UWSGI_EMBED_PLUGINS 2013-04-22 12:37:31 +02:00
Unbit 81dca1f690 better lock-engine auto-detection 2013-04-22 12:23:59 +02:00
Unbit 2b331fd68f fixed ipcsem removal on reload 2013-04-22 12:16:39 +02:00
Unbit cc77e4dba7 ported gridfs to the new uwsgi_get_app_id function 2013-04-22 10:33:52 +02:00
Unbit 620a13a308 added toxslt transformation 2013-04-22 10:08:56 +02:00
Unbit 42d4ba09d7 refactored uwsgi_get_app_id 2013-04-22 09:43:20 +02:00
Unbit ca071fa52f removed cherokee nginx and lighttpd directories 2013-04-22 08:07:26 +02:00
Unbit d38e5dec7b added uwsgi::register_rpc to perl 2013-04-22 08:05:20 +02:00
Unbit e5db38f7c0 kqueue timer for OpenBSD, NetBSD and DragonFlyBSD 2013-04-22 09:07:19 +02:00
Unbit 68a29730c0 transformation_gzip and transformation_tofile are part of the default build profile 2013-04-22 06:57:29 +02:00
Unbit 5c33c4d341 fixed fd leak in sendfile on error 2013-04-22 06:25:50 +02:00
Unbit a1d6270089 another static gzip refactoring 2013-04-21 20:48:08 +02:00
unbit 1968175b00 Merge pull request #240 from toofishes/static-gz-length
Fix Content-Length header when serving gzipped content
2013-04-21 11:38:18 -07:00
Dan McGee cf1e2aeeba Fix Content-Length header when serving gzipped content
The refactor in a56003d8 to support the Range header broke compliance
with the HTTP spec. When we find a gzipped resource to serve up, ensure
we use the correct Content-Length of the compressed file, not the
original one.
2013-04-21 13:16:33 -05:00
Unbit 199b0b9f57 resources allocated by transformations are correctly freed 2013-04-21 10:22:33 +02:00
Unbit 87a0daa465 ported gzip and toupper to the new transformation api 2013-04-21 10:17:37 +02:00
Unbit c2af90b58f cachestore response is buffered 2013-04-21 10:09:02 +02:00
Unbit 62f01453af refactored cachestore to use transformation api 2013-04-21 10:07:48 +02:00
Unbit 375d6ee331 allows non-request plugin to register rpc functions 2013-04-21 09:43:45 +02:00
Unbit 222ca2915b symcall has been improved and added to the dfault build profile 2013-04-20 19:22:50 +02:00
Unbit 5ca848f9fe more robust subscription propagation using non blocking sockets 2013-04-20 15:17:43 +02:00
Unbit 68d878ff6b added arbiters to the Legion subsystem 2013-04-20 14:20:32 +02:00
Unbit 782a7b418a added mime route var 2013-04-20 13:56:10 +02:00
Unbit 724d7854ad allows transformation to rewrite headers 2013-04-20 13:51:48 +02:00
Unbit f8e64d17e8 added safe-fd concept and --alarm-fd 2013-04-20 13:24:36 +02:00
Unbit 3b40799000 more robust error checking for cgroups and support for writing proc files on the fly 2013-04-20 10:49:42 +02:00
Roberta Giordano 709964ca92 raise an exception with python3 if the headers are not encodable in latin1 2013-04-20 08:08:53 +02:00
Unbit d2cdedc610 maintain headers sent as the last resort even in buffered mode 2013-04-18 22:09:05 +02:00
Unbit b7d0730343 fixed another typo 2013-04-18 18:06:07 +02:00
Unbit 30b4ea7d49 added transformation_gzip 2013-04-18 18:05:01 +02:00
Unbit 546dadbd06 fixed some typo 2013-04-18 17:59:24 +02:00
Unbit 76edf902de added trasnformations 2013-04-18 17:56:13 +02:00
Łukasz Mierzwa 7c4caef5e7 allow setting cgroup dir mode 2013-04-18 13:13:15 +02:00
Unbit 068024134c added --load-file-in-cache-gzip 2013-04-17 16:08:27 +02:00
Unbit 538ab57b6e extend magic cache api to export the expires value (if available) 2013-04-16 18:56:25 +02:00
Unbit fd6d9148f3 filter more headers in proxy mode 2013-04-16 18:00:30 +02:00
Unbit f033f59755 fixed gzip caching 2013-04-16 17:51:50 +02:00
Unbit 7168c6dd69 improved caching 2013-04-16 17:46:36 +02:00
Unbit f121d41c2f added proxyhttp and proxyuwsgi 2013-04-16 17:11:32 +02:00
Unbit e56e774eac Merge branch 'master' of github.com:unbit/uwsgi 2013-04-16 10:17:29 +02:00
Unbit 6d9b0918a3 do not skip atexit hooks on end_me when run by the master 2013-04-16 10:17:11 +02:00
unbit d445418611 Merge pull request #229 from prymitive/cb_in_base
add cheaper_busyness plugin to default build profile
2013-04-16 01:12:52 -07:00
Unbit 6d15a51c9a added --skip-atexit 2013-04-16 10:12:22 +02:00
unbit 42a615efdd Merge pull request #231 from prymitive/legion_lock
add missing locks to legion_cache_fetch plugin
2013-04-15 10:32:01 -07:00
Łukasz Mierzwa 54cd1f79a6 add missing locks to legion_cache_fetch plugin 2013-04-15 19:15:54 +02:00
Unbit 8ed8f46374 fixed some minor-bug dected by cppcheck 2013-04-15 13:45:46 +02:00
Unbit dd3a2996a4 fixed leak in cache gzip 2013-04-15 13:22:26 +02:00
Unbit bf1f90a96a added the ability to store cache items in gzip 2013-04-15 12:36:27 +02:00
Unbit 2d6200231a added content_encoding to routing cache 2013-04-15 11:28:54 +02:00
Unbit 032cd23304 added --legion-mcast shortcut 2013-04-14 18:12:57 +02:00
Łukasz Mierzwa de4c0a9e1c add cheaper_busyness plugin to default build profile 2013-04-14 12:28:49 +02:00
Unbit e33f8e8920 compile the remote spooler plugin by default 2013-04-14 09:39:46 +02:00
Unbit 22615c7921 correctly support default cache in ssl session scaling 2013-04-14 08:23:48 +02:00
Unbit 9d8809c580 added the curl_cron plugin 2013-04-13 10:04:21 +02:00
Unbit 96b92c98ff refactored cron to allows better plugins integration 2013-04-13 09:22:22 +02:00
unbit 07939acecd Merge pull request #228 from prymitive/cache_last_modified
store cache last modification time if enabled, fixes #224
2013-04-13 00:08:10 -07:00
Łukasz Mierzwa 30abcb2563 store cache last modification time if enabled, fixes #224 2013-04-12 22:11:25 +02:00
Unbit 35ce8f2b8d do not spawn the excpetion thread handler if no exception handler has been loaded 2013-04-12 08:12:15 +02:00
Unbit d6453eab38 improved cache usage in corerouters 2013-04-11 20:25:18 +02:00
Unbit e0964d07ea ported router_http improvements to router_uwsgi 2013-04-11 17:59:49 +02:00
Unbit fc359f1956 better to set status to 202 for offloaded requests 2013-04-11 17:39:20 +02:00
Unbit 322261d65d Merge branch 'master' of github.com:unbit/uwsgi 2013-04-11 17:26:42 +02:00
Unbit bd1163c439 fixed websocket proxy 2013-04-11 17:24:44 +02:00
unbit e203a8c706 Merge pull request #226 from prymitive/legion_log_fixes
remove unnecessary new lines in legion logs
2013-04-11 05:54:16 -07:00
unbit 6a1ba2af74 Merge pull request #225 from prymitive/cron_interval_fix
execute cron tasks with 60 second resolution, instead of 61 seconds
2013-04-11 05:37:00 -07:00
Łukasz Mierzwa 22569e64df remove unnecessary new lines in legion logs 2013-04-11 14:33:38 +02:00
Łukasz Mierzwa dcafe41cde execute cron tasks with 60 second resolution, instead of 61 seconds 2013-04-11 14:09:49 +02:00
Unbit dd2adc08a3 fixed teajs support 2013-04-11 12:25:06 +02:00
Unbit d7534d2673 improve post_buffering management in http internal router 2013-04-11 12:20:32 +02:00
Unbit 0a59920025 honour http protocol in http internal router 2013-04-11 11:47:14 +02:00
Unbit 77602a8de4 improved websockets detection 2013-04-11 11:30:15 +02:00
Unbit 65b3fde97c added --legion-cron 2013-04-11 09:37:22 +02:00
unbit b690148452 Merge pull request #223 from prymitive/lcf_fixes
free values on old sync node list
2013-04-10 22:52:55 -07:00
Łukasz Mierzwa 4c7bc9ada6 free list value before we free list itself 2013-04-10 22:12:06 +02:00
Unbit 432651489f let's start with 1.9.7 2013-04-10 19:04:12 +02:00
unbit 82aa232a37 Merge pull request #221 from prymitive/legion_cache_plugin2
plugin for fetching cache dump from any node after joining legion
2013-04-10 09:32:41 -07:00
Unbit 19b13bf7a7 fixed offloading and more metric analysis 2013-04-10 18:21:28 +02:00
Łukasz Mierzwa f7e25d807d Merge remote branch 'upstream/master' into legion_cache_plugin2 2013-04-10 15:57:04 +02:00
unbit cf05316b95 Merge pull request #210 from prymitive/cron_refactoring
move crontab entry parsing to separate function
2013-04-10 06:40:30 -07:00
Łukasz Mierzwa 001c4386b5 move crontab entry parsing to separate function 2013-04-10 15:37:10 +02:00
Łukasz Mierzwa 572527f8cb plugin for fetching cache dump from any node after joining legion 2013-04-10 13:28:03 +02:00
Unbit b4252beda6 updated gemspec 2013-04-09 19:05:26 +02:00
Unbit d82ee16e0c completed first step of teajs integration, improved environ copy 2013-04-09 18:54:08 +02:00
unbit e4d65c07ce added support for gcc 4.8 2013-04-09 15:48:58 +02:00
Unbit 86fcb78cc3 fix for broken linkers 2013-04-09 14:51:47 +02:00
unbit 5beb422d75 Merge pull request #219 from prymitive/legion_cache_plugin
cache refactoring for better plugin friendliness
2013-04-09 05:48:49 -07:00
Łukasz Mierzwa 53679879ca cache refactoring for better plugin friendliness 2013-04-09 14:15:33 +02:00
Unbit a8ad766182 fixed matheval route var, added time route var 2013-04-09 11:09:15 +02:00
Unbit cbb2d30f79 more analysis for the metric subsystem 2013-04-09 06:38:34 +02:00
Unbit c5e00bcec6 preparing for uWSGI 1.9.6 2013-04-09 06:13:51 +02:00
Unbit 51535d374d reindented uwsgi.h 2013-04-09 06:13:28 +02:00
Unbit 1e057e6c35 the ldap support is now a plugin 2013-04-09 05:55:18 +02:00
Unbit b23e8ab862 added --socket-sndbuf and --socket-rcvbuf 2013-04-08 20:41:54 +02:00
Unbit 0f7f13dfb2 prepare for TeaJS integration 2013-04-08 19:50:01 +02:00
Unbit aa19ccda1d removed the probe subsystem 2013-04-08 17:05:12 +02:00
unbit cd0129e780 Merge pull request #218 from prymitive/legion_hooks
more legion hooks
2013-04-08 06:53:55 -07:00
Łukasz Mierzwa 506c9023e6 more legion hooks 2013-04-08 15:48:16 +02:00
Unbit d47c25ea4c added --lua-shell 2013-04-08 14:16:36 +02:00
Unbit 010651073c added rbshell 2013-04-08 13:49:23 +02:00
Unbit 76364e3799 added 'alarm' routing action 2013-04-08 11:10:18 +02:00
Unbit f9fd0a0203 added uwsgi route var 2013-04-08 10:34:45 +02:00
Łukasz Mierzwa edbff83fd6 zero pids after worker killed due to --idle usage 2013-04-08 10:32:39 +02:00
Unbit 8dfbde5d16 added --for-times 2013-04-08 10:20:22 +02:00
Unbit 888991f8c1 core/metrics.c 2013-04-08 09:39:57 +02:00
Unbit ece03922d6 added gridfs authentication 2013-04-06 15:09:01 +02:00
Unbit 47bb827e6e added 'lord' routing condition 2013-04-06 13:46:21 +02:00
Unbit a56003d847 added support for range header 2013-04-06 12:45:03 +02:00
Unbit 61022c398c added rpcraw 2013-04-06 08:42:55 +02:00
Unbit 00bd8cc525 improved pyshell 2013-04-06 07:44:12 +02:00
Unbit cf6a232aef added check for seek and tell in wsgi 2013-04-06 07:33:25 +02:00
Unbit 59d1a45ef0 added math route var 2013-04-05 19:26:33 +02:00
Unbit 0b5f9fcb48 added math[] route var 2013-04-05 18:39:01 +02:00
Unbit f713ffd6a1 improved mongodb dumb plugin 2013-04-05 18:17:28 +02:00
Unbit 22ba9d81d4 more generic mongodb plugin 2013-04-05 17:51:41 +02:00
Unbit 309bc98d7f added simple numeric checks for routing conditions 2013-04-05 17:48:20 +02:00
unbit 9b8646a583 Merge pull request #213 from prymitive/carbon_avg_policy
adds ability to control what values (if any) for avg_rt will be sent if ...
2013-04-05 02:18:19 -07:00
Unbit 48d1b87ab8 completed sqlite3 plugin 2013-04-05 10:37:18 +02:00
Unbit c5f849d846 added sqlite3 plugin 2013-04-05 10:35:30 +02:00
Unbit 31fbb6e4f5 prepare for moving sqlite to a dedicated plugin 2013-04-05 10:29:49 +02:00
Unbit 4d9a88e999 added setfile routing instruction and improved uwsgi_get_var 2013-04-05 07:47:32 +02:00
Unbit 252e8484a8 added chdir,setapp and sethome routing actions 2013-04-04 11:19:31 +02:00
Unbit 1b89203932 prepare for language independent home concept 2013-04-04 11:03:26 +02:00
Unbit 2263c6a618 prepare for uWSGI 1.9.5 release 2013-04-04 09:08:10 +02:00
Łukasz Mierzwa 673cb3ee21 adds ability to control what values (if any) for avg_rt will be sent if no requests were done, fixes #212 2013-04-04 00:55:02 +02:00
Unbit b4ecd504e3 prepare for 1.9.5 2013-04-03 19:19:23 +02:00
Unbit f226f29428 fix psgi post buffering 2013-04-03 18:20:54 +02:00
Unbit b87a284390 added 404/403 management for cgi routing 2013-04-03 18:09:05 +02:00
Unbit f63dcd0d9c fixed escaping in kvlist parse 2013-04-03 17:57:49 +02:00
Unbit 7f5563d581 added cgi router 2013-04-03 15:18:46 +02:00
Unbit d8a61a920e allows building a monolithic gridfs binary 2013-04-03 12:41:07 +02:00
Unbit 5a4900da8e added gridfs build profile 2013-04-03 12:39:00 +02:00
Unbit 677c30057a added routing support for gridfs 2013-04-03 12:24:21 +02:00
Unbit 26113e091b added the gridfs plugin 2013-04-03 11:54:54 +02:00
Unbit 1b5e98f593 more JSGI request vars 2013-04-02 18:22:39 +02:00
Unbit 0aa5201947 first implementation of a JSGI request 2013-04-02 17:30:58 +02:00
Unbit e3951baa3f completed JSGI response 2013-04-02 16:55:01 +02:00
Unbit 9f9dbbab9e preliminary support for JSGI 3.0 2013-04-02 12:26:55 +02:00
Unbit d546bbadbd added commonjs 'require' implementation to v8 2013-04-02 10:57:52 +02:00
Unbit 2b7f25054f added mule support for v8 2013-04-02 10:00:10 +02:00
Unbit bb3f6bcf7e more solid multithreading support for v8 2013-04-01 21:36:07 +02:00
Unbit 41da7175d1 working on v8 multithreading 2013-04-01 20:19:59 +02:00
Unbit 446763b58a added --honour-stdin 2013-04-01 10:07:33 +02:00
Unbit 3e9337a0fc added --daemons-honour-stdin 2013-04-01 09:30:19 +02:00
Unbit 028806165b force the emperor to honour --max-fd 2013-04-01 09:14:11 +02:00
unbit e4be42edbb Merge pull request #208 from xrmx/coverity11
More issues reported by Coverity
2013-04-01 00:07:29 -07:00
Unbit 230fa1f3bb fixed multiple interpreters support 2013-04-01 09:00:24 +02:00
unbit d74653bbad Merge pull request #209 from xrmx/coverity12
plugins/cgi: fix memory leak in uwsgi_cgi_request
2013-03-31 23:30:15 -07:00
Riccardo Magliocchetti 38049b0897 plugins/cgi: fix memory leak in uwsgi_cgi_request
Reported by Coverity as CID #990186.
2013-03-31 20:12:12 +02:00
Riccardo Magliocchetti b4af646929 core/emperor: fix memory leak in uwsgi_emperor_vassal_start
Reported by Coverity as CID #995786.
2013-03-31 19:51:25 +02:00
Riccardo Magliocchetti b21ec73a52 plugins/carbon: fix memory leak in carbon_post_init
Reported by Coverity as CID #995791
2013-03-31 19:45:24 +02:00
Riccardo Magliocchetti c595844f0e plugins/router_cache: fix memory leak in uwsgi_router_cache_store
Reported by Coverity as CID #995792.
2013-03-31 19:38:58 +02:00
Unbit fe8ee7c7b3 uWSGI 1.9.4 2013-03-30 16:29:51 +01:00
Unbit cd382c6bc0 added rpcblob/rpcnext 2013-03-30 16:06:47 +01:00
Unbit e68296c293 a bit of cosmetic for uwsgi.h 2013-03-30 09:28:06 +01:00
Unbit cc189feae5 added uwsgi_register_signal to v8 2013-03-30 09:25:50 +01:00
unbit 18e19027a1 Merge pull request #207 from prymitive/legion_api
refactored legion opt functions to be more plugin friendly
2013-03-30 00:58:46 -07:00
Łukasz Mierzwa 2d2e0e4757 refactored legion opt functions to be more plugin friendly 2013-03-29 23:33:33 +01:00
Unbit a9f50d79f9 start 1.9.4 2013-03-29 21:24:56 +01:00
Unbit 0ccd31bee0 fixed reloading when in Go mode 2013-03-29 21:24:41 +01:00
Unbit 3ea82b2bcd do not differentiate reload when uWSGI is build as shared library 2013-03-29 21:21:46 +01:00
Unbit 6dad7b3ced ported the cplusplus plugin to the new api 2013-03-29 19:43:03 +01:00
Unbit f96ebd2b07 Merge branch 'master' of github.com:unbit/uwsgi 2013-03-29 19:37:53 +01:00
Unbit b8d0e7a3ac beta quality v8 plugin 2013-03-29 19:37:33 +01:00
unbit 14cca3d497 Merge pull request #204 from prymitive/legion_join_hook
legion join hook
2013-03-29 06:02:42 -07:00
Łukasz Mierzwa c343ca0cc3 legion join hook 2013-03-29 14:01:02 +01:00
Unbit 527d371bda fixed multiple mules event handling 2013-03-29 13:34:48 +01:00
Unbit b87a800a9a avoid resetting uwsgi.mywid in the master 2013-03-29 13:24:33 +01:00
Unbit e406993ed1 fixed typo 2013-03-29 12:51:52 +01:00
Unbit eeff935fc9 fixed signal handling in non-workers 2013-03-29 12:50:56 +01:00
Unbit 0791394f1a official support for SmartOS 2013-03-29 08:12:58 +00:00
unbit 082a407b06 Merge pull request #201 from prymitive/cache_restore_items_count
update cache items count after restore
2013-03-28 15:23:22 -07:00
Łukasz Mierzwa 8a89b49df1 update cache items count after restore 2013-03-28 23:20:17 +01:00
unbit 2314b9cbab Merge pull request #200 from jbert/master
Fix segfault in psgi plugin
2013-03-28 15:02:26 -07:00
John Berthels d0cca85c83 fix segfault in psgi handler after taking early-exit error path in coroae_accept_request 2013-03-28 17:29:00 +00:00
unbit 6a7a5cbcba Merge pull request #199 from prymitive/cache_stats_missin_list_close
missing list close in cache stats
2013-03-28 09:28:02 -07:00
Łukasz Mierzwa ecccc82cc8 missing list close 2013-03-28 16:56:31 +01:00
Unbit 02693489fe fixed php headers generation 2013-03-28 12:13:23 +01:00
Unbit 0f5dba5828 apache 2.4 support in mod_proxy_uwsgi 2013-03-28 11:19:13 +01:00
Unbit e528d4c4b7 implemented --emperor-tyrant-nofollow 2013-03-28 10:18:01 +01:00
Unbit 52a3af6acf prepare for uWSGI 1.9.3 2013-03-28 10:05:24 +01:00
Unbit dcefea9958 added rpcret routing action 2013-03-28 10:03:33 +01:00
Unbit 59121ff834 added --lua-load, fixed lua rpc memory leak 2013-03-28 09:21:47 +01:00
Unbit 7f5bb6d472 allows usage of configurators in the emperor 2013-03-28 09:07:15 +01:00
Unbit 639c1a508c support for lua ordered arrays in configurations 2013-03-28 09:00:10 +01:00
Unbit 417a26fc64 added config.lua example 2013-03-28 08:02:32 +01:00
Unbit 210ccd0063 allows configuration via lua 2013-03-28 08:02:07 +01:00
unbit 1bf0162d38 Merge pull request #196 from ryankask/jvm-plugin-import
Fix imports for the JVM plugin
2013-03-27 02:53:03 -07:00
Ryan Kaskel e93027fd7e Fix imports for JVM plugin. 2013-03-27 09:48:14 +00:00
Unbit 807060706f prepare for 1.9.2 2013-03-26 20:05:33 +01:00
Unbit a317f88d3c added the cache command to the ssi plugin 2013-03-26 20:03:37 +01:00
Unbit e17a7f0701 fixed a typo 2013-03-26 19:53:32 +01:00
Unbit db325eb9fe fixed readline() + post_buffering 2013-03-26 17:54:42 +01:00
Unbit b41a4c8c3b fixed python3 headers management 2013-03-26 16:45:57 +01:00
Unbit 73b4d11d18 added ssi router 2013-03-26 15:38:45 +01:00
Unbit 8162b87287 beta quality ssi plugin 2013-03-26 15:19:23 +01:00
Unbit 70e9e4f3ee added printenv 2013-03-26 12:24:17 +01:00
Unbit e61ae376b3 other improvements in the ssi plugin 2013-03-26 11:48:51 +01:00
Unbit 2d57b0e926 added preliminary ssi support 2013-03-26 11:33:00 +01:00
Unbit ae683af07a completed the geoip plugin [2] 2013-03-26 07:11:27 +01:00
Unbit 3c4f6a9171 completed the geoip plugin 2013-03-26 07:05:02 +01:00
Unbit 39986e546c fixed GeoIP plugin 2013-03-26 06:47:18 +01:00
Unbit 2e81a80f7b added preliminary geoip plugin 2013-03-25 19:11:20 +01:00
Unbit fcb3aa38c8 allows freeing route vars 2013-03-25 18:15:29 +01:00
Unbit 00a38d8ec5 fixed routing vars management 2013-03-25 18:10:41 +01:00
Unbit 07a0ab4227 pluggable routing vars 2013-03-25 18:05:57 +01:00
Unbit d4a9a2c543 fixed exceptions in the fiber plugin 2013-03-25 17:46:29 +01:00
Unbit 2b523fc60d added query string management functions 2013-03-25 10:21:20 +01:00
Unbit 0c26928236 added cookie management and --route-run 2013-03-25 09:56:53 +01:00
Unbit 8401e56a22 added 'empty' internal routing condition 2013-03-25 09:04:30 +01:00
Unbit 5109f9ae0b back to libxml2 default 2013-03-25 08:47:22 +01:00
Unbit c9bc06669a .ini file can backreference themselves 2013-03-25 08:47:00 +01:00
unbit a83fb2672c Merge pull request #189 from xtfxme/enhance/189-dashful-endif-endfor
Routing table appear to go nuts when used within a FOR loop
2013-03-24 23:18:50 -07:00
C Anthony Risinger 8f9ecb44d9 [#189] endfor/endif => end-for/end-if ...i know i'm not alone 2013-03-24 15:45:04 -05:00
Unbit bfcc09a8de prepare for cookie management in internal routing 2013-03-24 21:05:21 +01:00
Unbit f8a8c997db removed cache type in routing instruction 2013-03-24 20:30:56 +01:00
Unbit 132b996f30 added cachestore routing instruction 2013-03-24 19:43:41 +01:00
Unbit 12f970cdfb prepare for routing-governed caching 2013-03-24 19:24:13 +01:00
Unbit 9afa963225 prepare for gem 1.9.1 2013-03-24 11:39:44 +01:00
Unbit ed368d0d51 fixed signal copy on write 2013-03-24 10:30:01 +01:00
Unbit 21f21d34ba fixed legion scrolls api 2013-03-24 09:52:16 +01:00
Unbit f37823c809 completed --emperor-on-demand-dir 2013-03-23 10:34:36 +01:00
Unbit 6eaefcff5e added build profile for ubuntu ppa 2013-03-23 06:15:55 +01:00
Unbit 79235c1cc3 another memory report fix for Unbit 2013-03-23 04:41:58 +01:00
Unbit 29135f014b Unbit fixes 2013-03-23 04:11:33 +01:00
Unbit 13c998fb8d added uwsgi_main.c 2013-03-23 03:56:56 +01:00
Unbit 71bfd0d636 prepare for uWSGI 1.9.1 2013-03-23 03:52:19 +01:00
Unbit 51e99e0f5a removed UWSGI_INI 2013-03-23 03:15:33 +01:00
Unbit 66e7beefc4 fixed rack exceptions management 2013-03-22 19:53:47 +01:00
Unbit f2b10c35b7 fixed build without pcre 2013-03-22 11:15:13 +01:00
Unbit e951eba96c improved emperor on demand mode 2013-03-22 14:56:49 +01:00
Unbit 9fe18da7a3 added startswith endswith and regexp/re routing instructions 2013-03-22 10:14:34 +01:00
Unbit a14fdead14 added rpc router instruction 2013-03-22 09:26:11 +01:00
Unbit 9a671a4991 added %V magic var (contains UWSGI_VERSION) 2013-03-21 17:18:41 +01:00
Unbit 8f5e7b124a added --emperor-on-demand-exec 2013-03-21 16:55:23 +01:00
Unbit 5f7464d015 implemented --emperor-on-demand-ext 2013-03-21 16:42:24 +01:00
Unbit 238dd6c1d0 added a commodity mongodb plugin for system without mongoclient shared library 2013-03-21 15:18:09 +01:00
Roberta Giordano 82e4e54edc removed some unbit useless definition 2013-03-21 07:59:45 +01:00
Unbit 9946cbb9da added 'equal' routing func 2013-03-21 06:54:36 +01:00
Unbit 2474adb23a completed routing cache instruction 2013-03-21 06:31:26 +01:00
Unbit f40757bb67 free carbon_address memory 2013-03-21 06:19:31 +01:00
unbit bc29479930 Merge pull request #188 from prymitive/carbon_resolve_hostnames
allow connecting to carbon server using hostname resolved on every cycle...
2013-03-20 22:04:50 -07:00
Łukasz Mierzwa 4ec78edaa3 allow connecting to carbon server using hostname resolved on every cycle, fixes #186 2013-03-20 21:47:56 +01:00
Unbit aa0271158d allows build profiles to be stored on http/https/ftp 2013-03-20 19:44:46 +01:00
Unbit c0aa5bfe17 added the crypto logger 2013-03-20 16:22:40 +01:00
Unbit 3f8e6a8cc8 completed xslt plugin 2013-03-19 17:53:12 +01:00
Unbit ef0316fc2e Merge branch 'master' of github.com:unbit/uwsgi 2013-03-19 15:18:33 +01:00
Unbit 7274efab15 added xslt plugin 2013-03-19 15:18:03 +01:00
Unbit e44b62b6b2 on demand vassals 2013-03-18 15:42:34 +01:00
Unbit 31c041d435 added --exec-post-app 2013-03-18 13:32:09 +01:00
Unbit 35f47371ed first part of uwsgi_legion_scrolls() function api 2013-03-18 13:22:10 +01:00
unbit c5412e1620 Merge pull request #185 from guokr/master
Supporting JVM/Ring installing in Virtualenv
2013-03-18 03:09:03 -07:00
Mingli a9b4c52811 supporting virtualenv 2013-03-18 17:53:04 +08:00
Roberto De Ioris 5ce40b6ac8 fixed --req-logger after reload 2013-03-18 09:19:25 +01:00
Unbit b93dcbf46f removed download_url from setup.py 2013-03-17 08:10:12 +01:00
Unbit 8051a2bc98 prepare for 1.9 release 2013-03-17 07:15:24 +01:00
Unbit 78d8b221fc added --gevent-monkey-patch 2013-03-17 07:14:54 +01:00
Unbit d51cada284 second (and last i hope) part of mongrel2 support refactoring 2013-03-16 18:24:25 +01:00
Unbit 389eef9e88 first part of mongrel2 support refactoring 2013-03-16 18:02:11 +01:00
Unbit 270fb0c50d avoid routing loop 2013-03-16 16:48:26 +01:00
Unbit e7e9dfee88 fixed DragonFlyBSD support 2013-03-16 15:45:49 +01:00
Unbit 3bafae276d improved binary detection path on cygwin 2013-03-16 12:33:00 +01:00
Unbit cfebe2927d fixed lazy mode 2013-03-15 13:47:29 +01:00
Unbit 1d4294a845 added some comment for the statsd plugin 2013-03-15 11:34:19 +01:00
Unbit 12cfdd9864 added stats_pusher_statsd plugin 2013-03-15 11:32:08 +01:00
Unbit add930c517 fixed uuid support in cygwin 2013-03-15 07:31:41 +01:00
Unbit 32972978be added java support for cygwin 2013-03-13 17:50:56 +01:00
Unbit c8bad3550e added proper locking to windows 2013-03-13 15:51:14 +01:00
Unbit ecc55d789d added proper-locking to poll event mode 2013-03-13 15:03:30 +01:00
Unbit 88555e2c20 improved poll() support 2013-03-13 14:33:38 +01:00
Unbit ec2bfcd302 allows building router basicauth on cygwin 2013-03-13 11:14:32 +01:00
Unbit f1f81ed4c4 fixed python3 build 2013-03-13 11:00:05 +01:00
Unbit 87933cca26 another series of cygwin fixes 2013-03-13 10:51:33 +01:00
Unbit 2dcd8624a2 psgi support for windows 2013-03-13 10:12:24 +01:00
Unbit 7fcef76bbe experimental windows/cygwin support 2013-03-13 09:44:32 +01:00
Unbit 2a5c4e938d fixed requets overwrite in PATH_INFO rewrite (fixed typo) 2013-03-12 15:57:44 +01:00
Unbit 274eae27ef fixed requets overwrite in PATH_INFO rewrite 2013-03-12 15:56:30 +01:00
Unbit 207220bc50 fixed #180 2013-03-12 11:45:03 +01:00
Unbit fb8c4439c7 the whole ring test suite passes 2013-03-12 11:15:45 +01:00
Roberto De Ioris 894be9c41e let the /sequence ring test pass 2013-03-12 09:42:13 +01:00
unbit 0a4bff8963 Merge pull request #182 from guokr/master
Ring plugin tests
2013-03-12 00:27:11 -07:00
Mingli d515f3e279 add tests for ring plugin 2013-03-12 14:47:51 +08:00
415 changed files with 44108 additions and 14412 deletions
+8
View File
@@ -1,5 +1,13 @@
*.o
*.py[co]
*.class
*.jar
*~
*.so
/uwsgi
/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
+11 -3
View File
@@ -1,8 +1,16 @@
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
plugin.%:
$(PYTHON) uwsgiconfig.py --plugin plugins/$* $(PROFILE)
%:
$(PYTHON) uwsgiconfig.py --build $@
+4 -2
View File
@@ -1,3 +1,5 @@
surprise i am empty !
The uWSGI project
Look in the online documentation on https://uwsgi-docs.readthedocs.org/en/latest/
For official documentation check: https://uwsgi-docs.readthedocs.org/en/latest/
For commercial support check: http://unbit.com/
+44 -1
View File
@@ -2,7 +2,7 @@
*** mod_proxy_uwsgi ***
Copyright 2009-2013 Unbit S.a.s. <info@unbit.it>
Copyright 2009-2014 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -217,6 +217,45 @@ static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
return OK;
}
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
static request_rec *ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
{
apr_pool_t *pool;
request_rec *rp;
apr_pool_create(&pool, c->pool);
rp = apr_pcalloc(pool, sizeof(*r));
rp->pool = pool;
rp->status = HTTP_OK;
rp->headers_in = apr_table_make(pool, 50);
rp->subprocess_env = apr_table_make(pool, 50);
rp->headers_out = apr_table_make(pool, 12);
rp->err_headers_out = apr_table_make(pool, 5);
rp->notes = apr_table_make(pool, 5);
rp->server = r->server;
rp->log = r->log;
rp->proxyreq = r->proxyreq;
rp->request_time = r->request_time;
rp->connection = c;
rp->output_filters = c->output_filters;
rp->input_filters = c->input_filters;
rp->proto_output_filters = c->output_filters;
rp->proto_input_filters = c->input_filters;
rp->useragent_ip = c->client_ip;
rp->useragent_addr = c->client_addr;
rp->request_config = ap_create_request_config(pool);
proxy_run_create_req(r, rp);
return rp;
}
#endif
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
{
@@ -337,7 +376,11 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
}
// ADD PATH_INFO
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
size_t w_len = strlen(worker->s->name);
#else
size_t w_len = strlen(worker->name);
#endif
char *u_path_info = r->filename + 6 + w_len;
int delta = 0;
if (u_path_info[0] != '/') {
+1 -1
View File
@@ -2,7 +2,7 @@
*** uWSGI/mod_uwsgi ***
Copyright 2009-2013 Unbit S.a.s. <info@unbit.it>
Copyright 2009-2014 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
+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
View File
@@ -1 +0,0 @@
object file for embedded files will be put here
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados,pypy,zabbix,curl_cron,tornado,tuntap,pty,mongrel2,alarm_curl,router_radius,airbrake
inherit = base
+1 -11
View File
@@ -1,29 +1,19 @@
[uwsgi]
xml = auto
ini = true
yaml = true
json = auto
sqlite3 = auto
zeromq = auto
snmp = true
ssl = auto
async = true
ldap = auto
pcre = auto
routing = auto
alarm = auto
ipv6 = false
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter
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
+1 -2
View File
@@ -1,4 +1,3 @@
[uwsgi]
# pypy,jvm,ring,jwsgi
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
main_plugin = psgi,rack,lua,python,gevent,php,cgi,glusterfs,pty,xslt,msgpack,geoip,v8,pam,ldap,mono,jvm,ring,jwsgi,servlet,rados,coroae,pypy,gccgo
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = gccgo
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = glusterfs
inherit = base
-5
View File
@@ -1,5 +0,0 @@
[uwsgi]
main_plugin = go
inherit = base
bin_name = libuwsgi.so
as_shared_library = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = gridfs
inherit = base
+29
View File
@@ -0,0 +1,29 @@
[uwsgi]
xml = false
yaml = false
json = false
ssl = false
pcre = false
routing = false
debug = false
unbit = false
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 =
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = psgi
inherit = minimal
+29
View File
@@ -0,0 +1,29 @@
[uwsgi]
xml = libxml2
yaml = libyaml
json = true
ssl = true
pcre = true
routing = true
debug = false
unbit = false
malloc_implementation = libc
extras =
plugins =
bin_name = /usr/lib/libuwsgi.so
append_version = ubuntu
plugin_dir = /usr/lib/uwsgi
embedded_plugins =
as_shared_library = true
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+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
+6
View File
@@ -0,0 +1,6 @@
[uwsgi]
main_plugin = python,gevent
inherit = base
plugins = jvm,ring
plugin_dir = .
+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
+14 -11
View File
@@ -1,26 +1,29 @@
[uwsgi]
xml = true
ini = true
yaml = true
xml = expat
yaml = embedded
json = false
sqlite3 = false
zeromq = false
ldap = true
ssl = true
pcre = true
routing = true
alarm = true
debug = false
unbit = true
xml_implementation = expat
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = /opt/unbit/bin/uwsgi
bin_name = /opt/unbit/uwsgi19/lib/libuwsgi.so
append_version = unbit
plugin_dir = /opt/unbit/uwsgi_plugins
plugin_dir = /opt/unbit/uwsgi19/plugins
embedded_plugins =
as_shared_library = true
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
-1
View File
@@ -1,6 +1,5 @@
[uwsgi]
inherit = unbit
json = false
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
+29
View File
@@ -0,0 +1,29 @@
[uwsgi]
xml = expat
yaml = embedded
json = true
ssl = true
pcre = true
routing = true
debug = false
unbit = false
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = /opt/unbit/uwsgi/plugins
embedded_plugins =
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 = v8
inherit = base
-1
View File
@@ -1 +0,0 @@
the uwsgi handler is included in the official Cherokee distribution
+24
View File
@@ -0,0 +1,24 @@
require 'socket'
require 'openssl'
secret = 'ciaociao'
iv = ''
address = '127.0.0.1'
port = 1717
algo = 'bf-cbc'
s = UDPSocket.new
s.bind(address, port)
cipher = OpenSSL::Cipher.new(algo)
cipher.decrypt
cipher.key = secret + ("\0" * (cipher.key_len - secret.length))
cipher.iv = iv + ("0" * (cipher.iv_len - iv.length))
loop do
msg, sender = s.recvfrom(8192)
cipher.reset
begin
puts cipher.update(msg) + cipher.final
rescue
end
end
+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
+141 -13
View File
@@ -11,6 +11,29 @@ void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t
uwsgi_route_signal(uai->data8);
}
// simply log an alarm
void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) {
}
void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
if (msg[len-1] != '\n') {
if (uai->arg && strlen(uai->arg) > 0) {
uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg);
}
else {
uwsgi_log_alarm("] %.*s\n", len, msg);
}
}
else {
if (uai->arg && strlen(uai->arg) > 0) {
uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg);
}
else {
uwsgi_log_alarm("] %.*s", len, msg);
}
}
}
// run a command on alarm
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
uai->data_ptr = uai->arg;
@@ -86,6 +109,7 @@ void uwsgi_register_embedded_alarms() {
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
uwsgi_register_alarm("log", uwsgi_alarm_init_log, uwsgi_alarm_func_log);
}
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
@@ -160,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);
@@ -181,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;
@@ -189,21 +212,54 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
#endif
static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) {
// add uwsgi_alarm_fd;
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
while(uafd) {
event_queue_add_fd_read(ut->queue, uafd->fd);
uafd = uafd->next;
}
char *buf = uwsgi_malloc(uwsgi.alarm_msg_size + sizeof(long));
for (;;) {
int interesting_fd = -1;
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
if (ret > 0) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
long ptr = 0;
memcpy(&ptr, buf, sizeof(long));
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
if (!uai)
break;
uwsgi_alarm_run(uai, msg, msg_size);
if (interesting_fd == ut->pipe[1]) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
long ptr = 0;
memcpy(&ptr, buf, sizeof(long));
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
if (!uai)
break;
uwsgi_alarm_run(uai, msg, msg_size);
}
}
// check for alarm_fd
else {
uafd = uwsgi.alarm_fds;
int fd_read = 0;
while(uafd) {
if (interesting_fd == uafd->fd) {
if (fd_read) goto raise;
size_t remains = uafd->buf_len;
while(remains) {
ssize_t len = read(uafd->fd, uafd->buf + (uafd->buf_len-remains), remains);
if (len <= 0) {
uwsgi_error("[uwsgi-alarm-fd]/read()");
uwsgi_log("[uwsgi-alarm-fd] i will stop monitoring fd %d\n", uafd->fd);
event_queue_del_fd(ut->queue, uafd->fd, event_queue_read());
break;
}
remains-=len;
}
fd_read = 1;
raise:
uwsgi_alarm_run(uafd->alarm, uafd->msg, uafd->msg_len);
}
uafd = uafd->next;
}
}
}
}
@@ -243,6 +299,37 @@ void uwsgi_alarms_init() {
if (!uwsgi.alarm_instances) return;
// map alarm file descriptors
usl = uwsgi.alarm_fd_list;
while(usl) {
char *space0 = strchr(usl->value, ' ');
if (!space0) {
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
exit(1);
}
*space0 = 0;
size_t buf_len = 1;
char *space1 = strchr(space0+1, ' ');
if (!space1) {
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
exit(1);
}
char *colon = strchr(space0+1, ':');
if (colon) {
buf_len = strtoul(colon+1, NULL, 10);
*colon = 0;
}
int fd = atoi(space0+1);
uwsgi_add_alarm_fd(fd, usl->value, buf_len, space1+1, strlen(space1+1));
*space0 = ' ';
*space1 = ' ';
if (colon) {
*colon = ':';
}
usl = usl->next;
}
#ifdef UWSGI_PCRE
// then map log-alarm
usl = uwsgi.alarm_logs_list;
@@ -340,3 +427,44 @@ void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
}
}
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
struct uwsgi_alarm_fd *old_uafd = NULL, *uafd = uwsgi.alarm_fds;
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm);
if (!uai) {
uwsgi_log("unable to find alarm \"%s\"\n", alarm);
exit(1);
}
if (!buf_len) buf_len = 1;
while(uafd) {
// check if an equal alarm has been added
if (uafd->fd == fd && uafd->alarm == uai) {
return uafd;
}
old_uafd = uafd;
uafd = uafd->next;
}
uafd = uwsgi_calloc(sizeof(struct uwsgi_alarm_fd));
uafd->fd = fd;
uafd->buf = uwsgi_malloc(buf_len);
uafd->buf_len = buf_len;
uafd->msg = msg;
uafd->msg_len = msg_len;
uafd->alarm = uai;
if (!old_uafd) {
uwsgi.alarm_fds = uafd;
}
else {
old_uafd->next = uafd;
}
// avoid the fd to be closed
uwsgi_add_safe_fd(fd);
uwsgi_log("[uwsgi-alarm] added fd %d\n", fd);
return uafd;
}
+204 -113
View File
@@ -2,6 +2,24 @@
extern struct uwsgi_server uwsgi;
/*
This is a general-purpose async loop engine (it expects a coroutine-based approach)
You can see it as an hub holding the following structures:
1) the runqueue, cores ready to be run are appended to this list
2) the fd list, this is a list of monitored file descriptors, a core can wait for all the file descriptors it needs
3) the timeout value, if set, the current core will timeout after the specified number of seconds (unless an event cancels it)
IMPORTANT: this is not a callback-based engine !!!
*/
// this is called whenever a new connection is ready, but there are no cores to handle it
void uwsgi_async_queue_is_full(time_t now) {
if (now > uwsgi.async_queue_is_full) {
uwsgi_log_verbose("[DANGER] async queue is full !!!\n");
@@ -10,7 +28,6 @@ void uwsgi_async_queue_is_full(time_t now) {
}
void uwsgi_async_init() {
int i;
uwsgi.async_queue = event_queue_init();
@@ -22,13 +39,9 @@ void uwsgi_async_init() {
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
for (i = 0; i < uwsgi.async; i++) {
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
}
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
// optimization, this array maps file descriptor to requests
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
}
@@ -52,7 +65,7 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
child->prev = parent;
}
if (parent == NULL) {
if (u_request == uwsgi.async_runqueue) {
uwsgi.async_runqueue = child;
}
@@ -61,33 +74,33 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
}
free(u_request);
uwsgi.async_runqueue_cnt--;
}
static void runqueue_push(struct wsgi_request *wsgi_req) {
struct uwsgi_async_request *uar;
// do not push the same request in the runqueue
struct uwsgi_async_request *uar = uwsgi.async_runqueue;
while(uar) {
if (uar->wsgi_req == wsgi_req) return;
uar = uar->next;
}
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = NULL;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
if (uwsgi.async_runqueue == NULL) {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
uwsgi.async_runqueue = uar;
}
else {
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
uar->prev = uwsgi.async_runqueue_last;
}
uwsgi.async_runqueue_cnt++;
if (uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last->next = uar;
}
uwsgi.async_runqueue_last = uar;
}
struct wsgi_request *find_first_available_wsgi_req() {
@@ -103,11 +116,28 @@ struct wsgi_request *find_first_available_wsgi_req() {
return wsgi_req;
}
void async_reset_request(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_timeout) {
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
}
struct uwsgi_async_fd *uaf = wsgi_req->waiting_fds;
while (uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
struct uwsgi_async_fd *current_uaf = uaf;
uaf = current_uaf->next;
free(current_uaf);
}
wsgi_req->waiting_fds = NULL;
}
static void async_expire_timeouts(uint64_t now) {
struct wsgi_request *wsgi_req;
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for (;;) {
@@ -121,20 +151,9 @@ static void async_expire_timeouts(uint64_t now) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
uaf = wsgi_req->waiting_fds;
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
while (uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
current_uaf = uaf;
uaf = current_uaf->next;
free(current_uaf);
}
wsgi_req->waiting_fds = NULL;
// put th request in the runqueue
// reset the request
async_reset_request(wsgi_req);
// push it in the runqueue
runqueue_push(wsgi_req);
continue;
}
@@ -146,12 +165,17 @@ static void async_expire_timeouts(uint64_t now) {
int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table){
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return -1;
}
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0)
return -1;
// find first slot
// find last slot
while (uad) {
last_uad = uad;
uad = uad->next;
@@ -179,7 +203,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;
}
@@ -193,8 +221,49 @@ static int async_wait_fd_read(int fd, int timeout) {
return 1;
}
static int async_wait_fd_read2(int fd0, int fd1, int timeout, int *fd) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_read(wsgi_req, fd0, timeout)) {
return -1;
}
if (async_add_fd_read(wsgi_req, fd1, timeout)) {
// reset already registered fd
async_reset_request(wsgi_req);
return -1;
}
if (uwsgi.schedule_to_main) {
uwsgi.schedule_to_main(wsgi_req);
}
if (wsgi_req->async_timed_out) {
wsgi_req->async_timed_out = 0;
return 0;
}
if (wsgi_req->async_ready_fd) {
*fd = wsgi_req->async_last_ready_fd;
return 1;
}
return -1;
}
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
if (uwsgi.async < 2 || !uwsgi.rb_async_timeouts) {
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return;
}
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);
}
@@ -203,12 +272,17 @@ void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table) {
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return -1;
}
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0)
return -1;
// find first slot
// find last slot
while (uad) {
last_uad = uad;
uad = uad->next;
@@ -238,6 +312,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;
}
@@ -252,7 +329,62 @@ static int async_wait_fd_write(int fd, int timeout) {
}
void async_schedule_to_req(void) {
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
goto end;
}
// a trick to avoid calling routes again
uwsgi.wsgi_req->is_routing = 1;
#endif
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) goto end;
if (uwsgi.schedule_to_main) {
uwsgi.schedule_to_main(uwsgi.wsgi_req);
}
return;
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(wsgi_req) == UWSGI_ROUTE_BREAK) {
goto end;
}
#endif
for(;;) {
wsgi_req->async_status = uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req);
if (wsgi_req->async_status <= UWSGI_OK) {
break;
}
wsgi_req->switches++;
if (uwsgi.schedule_fix) {
uwsgi.schedule_fix(wsgi_req);
}
// switch after each yield
uwsgi.schedule_to_main(wsgi_req);
}
#ifdef UWSGI_ROUTING
end:
#endif
// 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() {
@@ -262,7 +394,6 @@ void async_loop() {
exit(1);
}
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
struct uwsgi_rb_timer *min_timeout;
int timeout;
@@ -271,16 +402,18 @@ void async_loop() {
uint64_t now;
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
struct uwsgi_async_request *current_request = NULL;
void *events = event_queue_alloc(64);
struct uwsgi_socket *uwsgi_sock;
uwsgi_async_init();
uwsgi.async_runqueue = NULL;
uwsgi.async_runqueue_cnt = 0;
uwsgi.wait_write_hook = async_wait_fd_write;
uwsgi.wait_read_hook = async_wait_fd_read;
uwsgi.wait_read2_hook = async_wait_fd_read2;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
@@ -292,13 +425,13 @@ 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) {
now = (uint64_t) uwsgi_now();
if (uwsgi.async_runqueue_cnt) {
if (uwsgi.async_runqueue) {
timeout = 0;
}
else {
@@ -328,16 +461,15 @@ void async_loop() {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
// signals are executed in the main stack... in the future we could have dedicated stacks for them
if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
continue;
}
is_a_new_connection = 0;
// new request coming in ?
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
@@ -351,6 +483,7 @@ void async_loop() {
break;
}
// on error re-insert the request in the queue
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock);
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
uwsgi.async_queue_unused_ptr++;
@@ -364,6 +497,9 @@ void async_loop() {
break;
}
// by default the core is in UWSGI_AGAIN mode
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
// some protocol (like zeromq) do not need additional parsing, just push it in the runqueue
if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
runqueue_push(uwsgi.wsgi_req);
}
@@ -380,31 +516,28 @@ void async_loop() {
if (uwsgi.wsgi_req) {
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
// reset timeout
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
async_reset_request(uwsgi.wsgi_req);
// parsing complete
if (!proto_parser_status) {
// remove fd from event poll and fd proto table
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
// put request in the runqueue
// put request in the runqueue (set it as UWSGI_OK to signal the first run)
uwsgi.wsgi_req->async_status = UWSGI_OK;
runqueue_push(uwsgi.wsgi_req);
continue;
}
else if (proto_parser_status < 0) {
if (proto_parser_status == -1)
uwsgi_log("error parsing request\n");
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
close(interesting_fd);
continue;
}
// re-add timer
async_add_timeout(uwsgi.wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
async_add_timeout(uwsgi.wsgi_req, uwsgi.socket_timeout);
continue;
}
// app event
// app-registered event
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
// unknown fd, remove it (for safety)
if (uwsgi.wsgi_req == NULL) {
@@ -413,79 +546,37 @@ void async_loop() {
}
// remove all the fd monitors and timeout
while (uwsgi.wsgi_req->waiting_fds) {
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
async_reset_request(uwsgi.wsgi_req);
uwsgi.wsgi_req->async_ready_fd = 1;
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
// avoid managing other enqueued events...
break;
}
}
// event queue managed, give cpu to runqueue
if (!current_request)
current_request = uwsgi.async_runqueue;
if (uwsgi.async_runqueue_cnt) {
// event queue managed, give cpu to runqueue
current_request = uwsgi.async_runqueue;
while(current_request) {
// current_request could be nulled on error/end of request
struct uwsgi_async_request *next_request = current_request->next;
uwsgi.wsgi_req = current_request->wsgi_req;
uwsgi.schedule_to_req();
uwsgi.wsgi_req->switches++;
next_async_request = current_request->next;
// request ended ?
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
// remove all the monitored fds and timeout
while (uwsgi.wsgi_req->waiting_fds) {
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
// remove from the list
runqueue_remove(current_request);
uwsgi_close_request(uwsgi.wsgi_req);
// push wsgi_request in the unused stack
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from suspended list
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);
}
current_request = next_async_request;
current_request = next_request;
}
}
}
+87 -6
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) {
@@ -61,7 +64,7 @@ int uwsgi_buffer_insert_chunked(struct uwsgi_buffer *ub, size_t pos, size_t len)
// 0xFFFFFFFFFFFFFFFF\r\n\0
char chunked[19];
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
if (ret <= 0 || ret > 19) {
if (ret <= 0 || ret >= 19) {
return -1;
}
return uwsgi_buffer_insert(ub, pos, chunked, ret);
@@ -71,7 +74,7 @@ int uwsgi_buffer_append_chunked(struct uwsgi_buffer *ub, size_t len) {
// 0xFFFFFFFFFFFFFFFF\r\n\0
char chunked[19];
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
if (ret <= 0 || ret > 19) {
if (ret <= 0 || ret >= 19) {
return -1;
}
return uwsgi_buffer_append(ub, chunked, ret);
@@ -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];
@@ -205,7 +245,7 @@ int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *ub, void *addr) {
int uwsgi_buffer_num64(struct uwsgi_buffer *ub, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%lld", (long long) num);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
return uwsgi_buffer_append(ub, buf, ret);
@@ -228,7 +268,7 @@ int uwsgi_buffer_append_keyval32(struct uwsgi_buffer *ub, char *key, uint32_t ke
int uwsgi_buffer_append_keynum(struct uwsgi_buffer *ub, char *key, uint16_t keylen, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, (sizeof(UMAX64_STR)+1), "%lld", (long long) num);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
@@ -240,7 +280,7 @@ int uwsgi_buffer_append_keynum(struct uwsgi_buffer *ub, char *key, uint16_t keyl
int uwsgi_buffer_append_valnum(struct uwsgi_buffer *ub, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, (sizeof(UMAX64_STR)+1), "%lld", (long long) num);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
if (uwsgi_buffer_u16le(ub, ret)) return -1;
@@ -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);
@@ -293,7 +340,7 @@ int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
char *ptr = ub->buf;
while (remains > 0) {
int ret = uwsgi_waitfd_write(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
int ret = uwsgi_waitfd_write(fd, uwsgi.socket_timeout);
if (ret > 0) {
ssize_t len = write(fd, ptr, remains);
if (len > 0) {
@@ -328,3 +375,37 @@ int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modi
ub->buf[3] = modifier2;
return 0;
}
struct uwsgi_buffer *uwsgi_buffer_from_file(char *filename) {
struct stat st;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
return NULL;
}
if (fstat(fd, &st)) {
close(fd);
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(st.st_size);
ssize_t len = read(fd, ub->buf, st.st_size);
close(fd);
if (len != st.st_size) {
uwsgi_buffer_destroy(ub);
return NULL;
}
ub->pos = len;
return ub;
}
void uwsgi_buffer_map(struct uwsgi_buffer *ub, char *buf, size_t len) {
if (ub->buf) {
free(ub->buf);
}
ub->buf = buf;
ub->pos = len;
ub->len = len;
}
+374 -118
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.
@@ -156,14 +156,14 @@ static void cache_send_udp_command(struct uwsgi_cache *, char *, uint16_t, char
static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
struct uwsgi_cache *uc = (struct uwsgi_cache *) data;
if (!uwsgi_strncmp(k, kl, "items", 5)) {
size_t num = uwsgi_str_num(v, vl);
size_t num = uwsgi_str_num(v, vl);
if (num != uc->max_items) {
uwsgi_log("[cache-sync] invalid cache size, expected %llu received %llu\n", (unsigned long long) uc->max_items, (unsigned long long) num);
exit(1);
}
}
if (!uwsgi_strncmp(k, kl, "blocksize", 9)) {
size_t num = uwsgi_str_num(v, vl);
size_t num = uwsgi_str_num(v, vl);
if (num != uc->blocksize) {
uwsgi_log("[cache-sync] invalid cache block size, expected %llu received %llu\n", (unsigned long long) uc->blocksize, (unsigned long long) num);
exit(1);
@@ -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;
@@ -194,12 +230,52 @@ static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
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);
free(value);
}
else {
uwsgi_log("[cache-error] unable to read file \"%.*s\"\n", key_len, key);
}
next:
usl = usl->next;
}
#ifdef UWSGI_ZLIB
usl = uwsgi.load_file_in_cache_gzip;
while(usl) {
size_t len = 0;
char *value = NULL;
char *key = usl->value;
uint16_t key_len = usl->len;
char *space = strchr(usl->value, ' ');
if (space) {
// need to skip ?
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
goto next2;
}
key = space+1;
key_len = usl->len - ((space-usl->value)+1);
}
value = uwsgi_open_and_read(key, &len, 0, NULL);
if (value) {
struct uwsgi_buffer *gzipped = uwsgi_gzip(value, len);
if (gzipped) {
uwsgi_wlock(uc->lock);
if (!uwsgi_cache_set2(uc, key, key_len, gzipped->buf, gzipped->len, 0, 0)) {
uwsgi_log("[cache-gzip] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
uwsgi_rwunlock(uc->lock);
uwsgi_buffer_destroy(gzipped);
}
free(value);
}
next2:
usl = usl->next;
}
#endif
}
@@ -249,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);
}
@@ -259,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);
}
@@ -288,21 +364,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
(unsigned long long) ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items), (unsigned long long) (uc->blocksize * uc->max_items),
(unsigned long long) uc->blocks_bitmap_size);
struct uwsgi_string_list *usl = uc->nodes;
while(usl) {
char *port = strchr(usl->value, ':');
if (!port) {
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
exit(1);
}
// no need to zero the memory, socket_to_in_addr will do that
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
usl->custom_ptr = sin;
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
usl = usl->next;
}
uwsgi_cache_setup_nodes(uc);
uc->udp_node_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (uc->udp_node_socket < 0) {
@@ -311,70 +373,12 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
}
uwsgi_socket_nb(uc->udp_node_socket);
usl = uc->sync_nodes;
while(usl) {
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
int fd = uwsgi_connect(usl->value, 0, 0);
if (fd < 0) {
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
goto next;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
ub->pos = 4;
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to write to the cache server\n");
close(fd);
goto next;
}
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
close(fd);
goto next;
}
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
close(fd);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
goto next;
}
// reset the hashtable
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
// re-fill the hashtable
uwsgi_cache_fix(uc);
uwsgi_buffer_destroy(ub);
close(fd);
break;
next:
if (!usl->next) {
exit(1);
}
uwsgi_log("[cache-sync] trying with the next sync node...\n");
usl = usl->next;
}
uwsgi_cache_sync_from_nodes(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) {
@@ -456,6 +460,67 @@ char *uwsgi_cache_get2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
return NULL;
}
int64_t uwsgi_cache_num2(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
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 0;
uci->hits++;
uc->hits++;
int64_t *num = (int64_t *) (uc->data + (uci->first_block * uc->blocksize));
return *num;
}
uc->miss++;
return 0;
}
char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize, uint64_t *expires) {
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 (expires)
*expires = uci->expires;
uci->hits++;
uc->hits++;
return uc->data + (uci->first_block * uc->blocksize);
}
uc->miss++;
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) {
struct uwsgi_cache_item *uci;
@@ -501,6 +566,10 @@ int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_
uci->expires = 0;
uc->n_items--;
if (uc->use_last_modified) {
uc->last_modified_at = uwsgi_now();
}
}
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
@@ -533,7 +602,8 @@ void uwsgi_cache_fix(struct uwsgi_cache *uc) {
}
}
uwsgi_log("[uwsgi-cache] restored %llu items\n", restored);
uc->n_items = restored;
uwsgi_log("[uwsgi-cache] restored %llu items\n", uc->n_items);
}
int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint64_t flags) {
@@ -546,6 +616,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uint8_t rollback_mode = 0;
int ret = -1;
time_t now = 0;
if (!keylen || !vallen)
return -1;
@@ -555,6 +626,8 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
if (vallen > uc->max_item_size) return -1;
if ((flags & UWSGI_CACHE_FLAG_MATH) && vallen != 8) return -1;
//uwsgi_log("putting cache data in key %.*s %d\n", keylen, key, vallen);
index = uwsgi_cache_get_index(uc, key, keylen);
if (!index) {
@@ -591,13 +664,13 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uc->unused_blocks_stack_ptr++;
}
else if (rollback_mode == 2) {
uc->first_available_block--;
uc->first_available_block--;
}
goto end;
}
// mark used blocks;
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
// optimize teh scan
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
// optimize the scan
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
uc->blocks_bitmap_pos = 0;
}
@@ -605,14 +678,42 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uc->blocks_bitmap_pos = uci->first_block + needed_blocks + 1;
}
}
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE))
expires += uwsgi_now();
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
now = uwsgi_now();
expires += now;
}
uci->expires = expires;
uci->hash = uc->hash->func(key, keylen);
uci->hits = 0;
uci->flags = flags;
memcpy(uci->key, key, keylen);
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
}
// ok math operations here
else {
int64_t *num = (int64_t *)(((char *) uc->data) + (uci->first_block * uc->blocksize));
*num = uc->math_initial;
int64_t *delta = (int64_t *) val;
if (flags & UWSGI_CACHE_FLAG_INC) {
*num += *delta;
}
else if (flags & UWSGI_CACHE_FLAG_DEC) {
*num -= *delta;
}
else if (flags & UWSGI_CACHE_FLAG_MUL) {
*num *= *delta;
}
else if (flags & UWSGI_CACHE_FLAG_DIV) {
if (*delta == 0) {
*num = 0;
}
else {
*num /= *delta;
}
}
}
// set this as late as possibile (to reduce races risk)
@@ -644,8 +745,9 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
}
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = cache_item(index);
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
expires += uwsgi_now();
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE) && !(flags & UWSGI_CACHE_FLAG_FIXEXPIRE)) {
now = uwsgi_now();
expires += now;
uci->expires = expires;
}
if (uc->blocks_bitmap) {
@@ -660,7 +762,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
}
// mark used blocks;
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
// optimize teh scan
// optimize the scan
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
uc->blocks_bitmap_pos = 0;
}
@@ -670,11 +772,38 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
// unmark the old blocks
cache_unmark_blocks(uc, uci->first_block, uci->valsize);
}
memcpy(uc->data + (uci->first_block * uc->blocksize), val, vallen);
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
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));
int64_t *delta = (int64_t *) val;
if (flags & UWSGI_CACHE_FLAG_INC) {
*num += *delta;
}
else if (flags & UWSGI_CACHE_FLAG_DEC) {
*num -= *delta;
}
else if (flags & UWSGI_CACHE_FLAG_MUL) {
*num *= *delta;
}
else if (flags & UWSGI_CACHE_FLAG_DIV) {
if (*delta == 0) {
*num = 0;
}
else {
*num /= *delta;
}
}
}
uci->valsize = vallen;
ret = 0;
}
if (uc->use_last_modified) {
uc->last_modified_at = (now ? now : uwsgi_now());
}
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
cache_send_udp_command(uc, key, keylen, val, vallen, expires, 10);
}
@@ -952,6 +1081,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
uc->nodes = uwsgi.cache_udp_node;
uc->udp_servers = uwsgi.cache_udp_server;
uc->store_sync = uwsgi.cache_store_sync;
uc->use_last_modified = (uint8_t) uwsgi.cache_use_last_modified;
if (uwsgi.cache_sync) {
uwsgi_string_new_list(&uc->sync_nodes, uwsgi.cache_sync);
@@ -971,6 +1101,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
char *c_sync = NULL;
char *c_udp_servers = NULL;
char *c_bitmap = NULL;
char *c_use_last_modified = NULL;
char *c_math_initial = NULL;
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"name", &c_name,
@@ -996,6 +1128,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
"udpservers", &c_udp_servers,
"udpserver", &c_udp_servers,
"bitmap", &c_bitmap,
"lastmod", &c_use_last_modified,
"math_initial", &c_math_initial,
NULL)) {
uwsgi_log("unable to parse cache definition\n");
exit(1);
@@ -1020,7 +1154,6 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
// defaults
uc->blocks = uc->max_items;
uc->blocksize = UMAX16;
uc->max_item_size = uc->blocksize;
uc->keysize = 2048;
uc->hashsize = UMAX16;
uc->hash = uwsgi_hash_algo_get("djb33x");
@@ -1028,6 +1161,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
// customize
if (c_blocksize) uc->blocksize = uwsgi_n64(c_blocksize);
if (!uc->blocksize) { uwsgi_log("invalid cache blocksize for \"%s\"\n", uc->name); exit(1); }
// set the true max size of an item
uc->max_item_size = uc->blocksize;
if (c_blocks) uc->blocks = uwsgi_n64(c_blocks);
if (!uc->blocks) { uwsgi_log("invalid cache blocks for \"%s\"\n", uc->name); exit(1); }
if (c_hash) uc->hash = uwsgi_hash_algo_get(c_hash);
@@ -1040,6 +1176,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
uc->use_blocks_bitmap = 1;
uc->max_item_size = uc->blocksize * uc->blocks;
}
if (c_use_last_modified) uc->use_last_modified = 1;
if (c_math_initial) uc->math_initial = strtol(c_math_initial, NULL, 10);
uc->store_sync = uwsgi.cache_store_sync;
if (c_store_sync) { uc->store_sync = uwsgi_n64(c_store_sync); }
@@ -1052,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, ";");
}
}
@@ -1296,7 +1432,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
// ok now wait for the response, using the same buffer of the request
// NOTE: after using a uwsgi_buffer in that way we basically destroy (even if we can safely free it)
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout)) return -1;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout, NULL, NULL)) return -1;
// try to fix the buffer to maintain size info
ub->pos = rlen;
@@ -1306,7 +1442,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
return 0;
}
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *cache) {
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64_t *expires, char *cache) {
struct uwsgi_cache_magic_context ucmc;
struct uwsgi_cache *uc = NULL;
char *cache_server = NULL;
@@ -1331,7 +1467,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
// we have a local cache !!!
if (uc) {
uwsgi_rlock(uc->lock);
char *value = uwsgi_cache_get2(uc, key, keylen, vallen);
char *value = uwsgi_cache_get3(uc, key, keylen, vallen, expires);
if (!value) {
uwsgi_rwunlock(uc->lock);
return NULL;
@@ -1347,7 +1483,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
int fd = uwsgi_connect(cache_server, 0, 1);
if (fd < 0) return NULL;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
if (ret <= 0) {
close(fd);
return NULL;
@@ -1359,7 +1495,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
return NULL;
}
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
close(fd);
uwsgi_buffer_destroy(ub);
return NULL;
@@ -1390,7 +1526,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
}
// read the raw value from the socket
if (uwsgi_read_whole_true_nb(fd, ub->buf, ucmc.size, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
if (uwsgi_read_whole_true_nb(fd, ub->buf, ucmc.size, uwsgi.socket_timeout)) {
close(fd);
uwsgi_buffer_destroy(ub);
return NULL;
@@ -1401,6 +1537,9 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
ub->buf = NULL;
uwsgi_buffer_destroy(ub);
*vallen = ucmc.size;
if (expires) {
*expires = ucmc.expires;
}
return value;
}
@@ -1446,7 +1585,7 @@ int uwsgi_cache_magic_exists(char *key, uint16_t keylen, char *cache) {
int fd = uwsgi_connect(cache_server, 0, 1);
if (fd < 0) return 0;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
if (ret <= 0) {
close(fd);
return 0;
@@ -1458,7 +1597,7 @@ int uwsgi_cache_magic_exists(char *key, uint16_t keylen, char *cache) {
return 0;
}
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
close(fd);
uwsgi_buffer_destroy(ub);
return 0;
@@ -1513,7 +1652,7 @@ int uwsgi_cache_magic_set(char *key, uint16_t keylen, char *value, uint64_t vall
int fd = uwsgi_connect(cache_server, 0, 1);
if (fd < 0) return -1;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
if (ret <= 0) {
close(fd);
return -1;
@@ -1531,7 +1670,7 @@ int uwsgi_cache_magic_set(char *key, uint16_t keylen, char *value, uint64_t vall
return -1;
}
if (cache_magic_send_and_manage(fd, ub, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
if (cache_magic_send_and_manage(fd, ub, value, vallen, uwsgi.socket_timeout, &ucmc)) {
close(fd);
uwsgi_buffer_destroy(ub);
return -1;
@@ -1591,7 +1730,7 @@ int uwsgi_cache_magic_del(char *key, uint16_t keylen, char *cache) {
int fd = uwsgi_connect(cache_server, 0, 1);
if (fd < 0) return -1;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
if (ret <= 0) {
close(fd);
return -1;
@@ -1603,7 +1742,7 @@ int uwsgi_cache_magic_del(char *key, uint16_t keylen, char *cache) {
return -1;
}
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
close(fd);
uwsgi_buffer_destroy(ub);
return -1;
@@ -1664,7 +1803,7 @@ int uwsgi_cache_magic_clear(char *cache) {
int fd = uwsgi_connect(cache_server, 0, 1);
if (fd < 0) return -1;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
if (ret <= 0) {
close(fd);
return -1;
@@ -1676,7 +1815,7 @@ int uwsgi_cache_magic_clear(char *cache) {
return -1;
}
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
close(fd);
uwsgi_buffer_destroy(ub);
return -1;
@@ -1695,3 +1834,120 @@ int uwsgi_cache_magic_clear(char *cache) {
}
void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uc->sync_nodes;
while(usl) {
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
int fd = uwsgi_connect(usl->value, 0, 0);
if (fd < 0) {
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
goto next;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
ub->pos = 4;
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.socket_timeout)) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to write to the cache server\n");
close(fd);
goto next;
}
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.socket_timeout, NULL, NULL)) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
close(fd);
goto next;
}
uwsgi_hooked_parse(ub->buf, rlen, cache_sync_hook, uc);
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.socket_timeout)) {
uwsgi_buffer_destroy(ub);
close(fd);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
goto next;
}
// reset the hashtable
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
// re-fill the hashtable
uwsgi_cache_fix(uc);
uwsgi_buffer_destroy(ub);
close(fd);
break;
next:
if (!usl->next) {
exit(1);
}
uwsgi_log("[cache-sync] trying with the next sync node...\n");
usl = usl->next;
}
}
void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uc->nodes;
while(usl) {
char *port = strchr(usl->value, ':');
if (!port) {
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
exit(1);
}
// no need to zero the memory, socket_to_in_addr will do that
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
usl->custom_ptr = sin;
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
usl = usl->next;
}
}
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.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() {}
+5
View File
@@ -2,6 +2,11 @@
extern struct uwsgi_server uwsgi;
int uwsgi_simple_wait_milliseconds_hook(int timeout) {
return poll(NULL, 0, timeout);
}
// in the future we will need to use the best clock source for each os/system
time_t uwsgi_now() {
return uwsgi.clock->seconds();
+817
View File
@@ -0,0 +1,817 @@
#include <uwsgi.h>
/*
pluggable configuration system
*/
extern struct uwsgi_server uwsgi;
struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(char *, char **)) {
struct uwsgi_configurator *old_uc = NULL,*uc = uwsgi.configurators;
while(uc) {
if (!strcmp(uc->name, name)) {
return uc;
}
old_uc = uc;
uc = uc->next;
}
uc = uwsgi_calloc(sizeof(struct uwsgi_configurator));
uc->name = name;
uc->func = func;
if (old_uc) {
old_uc->next = uc;
}
else {
uwsgi.configurators = uc;
}
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_readline(char *key, char *value) {
char line[1024];
FILE *fh = fopen(uwsgi.logic_opt_data, "r");
if (fh) {
while (fgets(line, 1024, fh)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi_chomp(uwsgi_str(line))), 0);
}
fclose(fh);
return 1;
}
uwsgi_error_open(uwsgi.logic_opt_data);
return 0;
}
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);
}
char *uwsgi_get_exported_opt(char *key) {
int i;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (!strcmp(uwsgi.exported_opts[i]->key, key)) {
return uwsgi.exported_opts[i]->value;
}
}
return NULL;
}
char *uwsgi_get_optname_by_index(int index) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (op->shortcut == index) {
return op->name;
}
op++;
}
return NULL;
}
/*
this works as a pipeline
processes = 2
cpu_cores = 8
foobar = %(processes cpu_cores + 2)
translate as:
step1 = proceses cpu_cores = 2 8 = 28 (string concatenation)
step1 + = step1_apply_func_plus (func token)
step1_apply_func_plus 2 = 28 + 2 = 30 (math)
*/
char *uwsgi_manage_placeholder(char *key) {
enum {
concat = 0,
sum,
sub,
mul,
div,
} state;
state = concat;
char *current_value = NULL;
char *space = strchr(key, ' ');
if (!space) {
return uwsgi_get_exported_opt(key);
}
// let's start the heavy metal here
char *tmp_value = uwsgi_str(key);
char *p, *ctx = NULL;
uwsgi_foreach_token(tmp_value, " ", p, ctx) {
char *value = NULL;
if (is_a_number(p)) {
value = uwsgi_str(p);
}
else if (!strcmp(p, "+")) {
state = sum;
continue;
}
else if (!strcmp(p, "-")) {
state = sub;
continue;
}
else if (!strcmp(p, "*")) {
state = mul;
continue;
}
else if (!strcmp(p, "/")) {
state = div;
continue;
}
else if (!strcmp(p, "++")) {
if (current_value) {
int64_t tmp_num = strtoll(current_value, NULL, 10);
free(current_value);
current_value = uwsgi_64bit2str(tmp_num+1);
}
state = concat;
continue;
}
else if (!strcmp(p, "--")) {
if (current_value) {
int64_t tmp_num = strtoll(current_value, NULL, 10);
free(current_value);
current_value = uwsgi_64bit2str(tmp_num-1);
}
state = concat;
continue;
}
// find the option
else {
char *ov = uwsgi_get_exported_opt(p);
if (!ov) ov = "";
value = uwsgi_str(ov);
}
int64_t arg1n = 0, arg2n = 0;
char *arg1 = "", *arg2 = "";
switch(state) {
case concat:
if (current_value) arg1 = current_value;
if (value) arg2 = value;
char *ret = uwsgi_concat2(arg1, arg2);
if (current_value) free(current_value);
current_value = ret;
break;
case sum:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n + arg2n);
break;
case sub:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n - arg2n);
break;
case mul:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n * arg2n);
break;
case div:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
// avoid division by zero
if (arg2n == 0) {
current_value = uwsgi_64bit2str(0);
}
else {
current_value = uwsgi_64bit2str(arg1n / arg2n);
}
break;
default:
break;
}
// over engineering
if (value)
free(value);
// reset state to concat
state = concat;
}
free(tmp_value);
return current_value;
}
+81
View File
@@ -0,0 +1,81 @@
#include <uwsgi.h>
/*
cookie management functions (mainly used by the internal routing subsystem)
*/
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t orig_cookie_len = cookie_len-1;
// first lstrip white spaces
char *ptr = cookie;
uint16_t i;
for(i=0;i<cookie_len;i++) {
if (isspace((int)ptr[i])) {
cookie++;
cookie_len--;
}
else {
break;
}
}
// then rstrip (skipping the first char...)
for(i=orig_cookie_len;i>0;i--) {
if (isspace((int)ptr[i])) {
cookie_len--;
}
else {
break;
}
}
// now search for the first equal sign
char *equal = memchr(cookie, '=', cookie_len);
if (!equal) return NULL;
if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) {
return NULL;
}
cookie_len -= (equal-cookie)+1;
if (cookie_len == 0) return NULL;
*vallen = cookie_len;
return equal+1;
}
char *uwsgi_get_cookie(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t i;
char *cookie = wsgi_req->cookie;
uint16_t cookie_len = 0;
char *ptr = wsgi_req->cookie;
//start splitting by ;
for(i=0;i<wsgi_req->cookie_len;i++) {
if (!cookie) {
cookie = ptr + i;
}
if (ptr[i] == ';') {
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
if (value) {
return value;
}
cookie_len = 0;
cookie = NULL;
}
else {
cookie_len++;
}
}
if (cookie_len > 0) {
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
if (value) {
return value;
}
}
return NULL;
}
+320
View File
@@ -0,0 +1,320 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
int i;
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
if (sscanf(crontab, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = crontab + i;
uc->pid = -1;
return uc;
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
uwsgi_cron_add(value);
}
void uwsgi_opt_add_unique_cron(char *opt, char *value, void *foobar) {
struct uwsgi_cron *uc = uwsgi_cron_add(value);
uc->unique = 1;
}
#ifdef UWSGI_SSL
void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
exit(1);
}
char *legion = uwsgi_concat2n(value, space-value, "", 0);
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
}
void uwsgi_opt_add_unique_legion_cron(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
exit(1);
}
char *legion = uwsgi_concat2n(value, space-value, "", 0);
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
uc->unique = 1;
}
#endif
void uwsgi_opt_add_cron2(char *opt, char *value, void *foobar) {
char *c_minute = NULL;
char *c_hour = NULL;
char *c_day = NULL;
char *c_month = NULL;
char *c_week = NULL;
char *c_unique = NULL;
char *c_harakiri = NULL;
char *c_legion = NULL;
char *c_command = value;
char *space = strchr(value, ' ');
if (space) {
if (uwsgi_str_contains(value, space - value, '=')) {
// --cron2 key=val command
*space = 0;
c_command = space + 1;
}
// no point in parsing key=val list if there is none
if (uwsgi_kvlist_parse(value, strlen(value), ',', '=',
"minute", &c_minute,
"hour", &c_hour,
"day", &c_day,
"month", &c_month,
"week", &c_week,
"unique", &c_unique,
"harakiri", &c_harakiri,
"legion", &c_legion,
NULL)) {
uwsgi_log("unable to parse cron definition: %s\n", value);
exit(1);
}
}
else {
if (uwsgi_str_contains(value, strlen(value), '=')) {
// --cron2 key=val
uwsgi_log("unable to parse cron definition: %s\n", value);
exit(1);
}
}
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
uc->command = c_command;
if (!uc->command) {
uwsgi_log("[uwsgi-cron] invalid command in cron definition: %s\n", value);
exit(1);
}
// defaults
uc->minute = -1;
uc->hour = -1;
uc->day = -1;
uc->month = -1;
uc->week = -1;
uc->unique = 0;
uc->mercy = 0;
uc->harakiri = 0;
uc->pid = -1;
#ifdef UWSGI_SSL
uc->legion = c_legion;
#endif
if (c_minute)
uc->minute = atoi(c_minute);
if (c_hour)
uc->hour = atoi(c_hour);
if (c_day)
uc->day = atoi(c_day);
if (c_month)
uc->month = atoi(c_month);
if (c_week)
uc->week = atoi(c_week);
if (c_unique)
uc->unique = atoi(c_unique);
if (c_harakiri) {
if (atoi(c_harakiri)) {
// harakiri > 0
uc->mercy = atoi(c_harakiri);
}
else {
// harakiri == 0
uc->mercy = -1;
}
}
else if (uwsgi.cron_harakiri) {
uc->harakiri = uwsgi.cron_harakiri;
}
}
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, ucron->minute, ucron->hour, ucron->day, ucron->month, ucron->week);
if (run_task == 1) {
// date match, signal it ?
if (now - ucron->last_job >= 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = now;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
uwsgi_error("uwsgi_manage_command_cron()/localtime()");
return;
}
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
#ifdef UWSGI_SSL
// check for legion cron
if (current_cron->legion) {
if (!uwsgi_legion_i_am_the_lord(current_cron->legion))
goto next;
}
#endif
// skip unique crons that are still running
if (current_cron->unique && current_cron->pid >= 0)
goto next;
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
if (run_task == 1) {
// date match, run command ?
if (now - current_cron->last_job >= 60) {
//call command
if (current_cron->command) {
if (current_cron->func) {
current_cron->func(current_cron, now);
}
else {
pid_t pid = uwsgi_run_command(current_cron->command, NULL, -1);
if (pid >= 0) {
current_cron->pid = pid;
current_cron->started_at = now;
uwsgi_log_verbose("[uwsgi-cron] running \"%s\" (pid %d)\n", current_cron->command, current_cron->pid);
if (current_cron->mercy) {
//uwsgi_cron->mercy can be negative to inform master that harakiri should be disabled for this cron
if (current_cron->mercy > 0)
current_cron->harakiri = now + current_cron->mercy;
}
else if (uwsgi.cron_harakiri)
current_cron->harakiri = now + uwsgi.cron_harakiri;
}
}
}
current_cron->last_job = now;
}
}
next:
current_cron = current_cron->next;
}
}
+315 -45
View File
@@ -1,4 +1,4 @@
#include "../uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -6,7 +6,7 @@ extern struct uwsgi_server uwsgi;
External uwsgi daemons
There are 3 kind of daemons (read: external applications) that can be managed
There are 3 kinds of daemons (read: external applications) that can be managed
by uWSGI.
1) dumb daemons (attached with --attach-daemon)
@@ -14,12 +14,12 @@ extern struct uwsgi_server uwsgi;
and the process is respawned
2) smart daemons with daemonization
you specify a pidfile and a command
- on startup - if the pidfile does not exists or contains a not-available pid (checked with kill(pid, 0))
the daemon is respawned
- on master ckeck - if the pidfile does not exist or if it point to a non-existent pid
the daemon is respawned
- on startup - if the pidfile does not exist or contains a non-available pid (checked with kill(pid, 0))
the daemon is respawned
- on master check - if the pidfile does not exist or if it points to a non-existent pid
the daemon is respawned
3) smart daemons without daemonization
same as 2, but the daemonization and pidfile creation is managed by uWSGI
same as 2, but the daemonization and pidfile creation are managed by uWSGI
status:
@@ -42,6 +42,31 @@ void uwsgi_daemons_smart_check() {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
#ifdef UWSGI_SSL
if (ud->legion) {
if (uwsgi_legion_i_am_the_lord(ud->legion)) {
// lord, spawn if not running
if (ud->pid <= 0) {
uwsgi_spawn_daemon(ud);
}
}
else {
// not lord, kill daemon if running
if (ud->pid > 0) {
if (!kill(ud->pid, 0)) {
uwsgi_log("[uwsgi_daemons] stopping legion \"%s\" daemon: %s (pid: %d)\n", ud->legion, ud->command, ud->pid);
kill(-(ud->pid), ud->stop_signal);
}
else {
// pid already died
ud->pid = -1;
}
}
ud = ud->next;
continue;
}
}
#endif
if (ud->pidfile) {
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
if (checked_pid <= 0) {
@@ -52,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);
}
}
}
}
@@ -70,13 +101,24 @@ void uwsgi_daemons_smart_check() {
}
}
// this function is called when a dumb daemon dies and we do not wat to respawn it
// this function is called when a dumb daemon dies and we do not want to respawn it
int uwsgi_daemon_check_pid_death(pid_t diedpid) {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid == diedpid && !ud->pidfile) {
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
return -1;
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;
}
@@ -87,7 +129,20 @@ int uwsgi_daemon_check_pid_death(pid_t diedpid) {
int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
#ifdef UWSGI_SSL
if (ud->pid == diedpid && ud->legion && !uwsgi_legion_i_am_the_lord(ud->legion)) {
// part of legion but not lord, don't respawn
ud->pid = -1;
uwsgi_log("uwsgi-daemons] legion \"%s\" daemon \"%s\" (pid: %d) annihilated\n", ud->legion, ud->command, (int) diedpid);
ud = ud->next;
continue;
}
#endif
if (ud->pid == diedpid && !ud->pidfile) {
if (ud->control) {
gracefully_kill_them_all(0);
return 0;
}
uwsgi_spawn_daemon(ud);
return 1;
}
@@ -133,6 +188,20 @@ void uwsgi_daemons_spawn_all() {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (!ud->registered) {
#ifdef UWSGI_SSL
if (ud->legion && !uwsgi_legion_i_am_the_lord(ud->legion)) {
// part of legion, register but don't spawn it yet
if (ud->pidfile) {
ud->pid = uwsgi_check_pidfile(ud->pidfile);
if (ud->pid > 0)
uwsgi_log("[uwsgi-daemons] found valid/active pidfile for \"%s\" (pid: %d)\n", ud->command, (int) ud->pid);
}
ud->registered = 1;
ud = ud->next;
continue;
}
#endif
ud->registered = 1;
if (ud->pidfile) {
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
if (checked_pid <= 0) {
@@ -146,7 +215,6 @@ void uwsgi_daemons_spawn_all() {
else {
uwsgi_spawn_daemon(ud);
}
ud->registered = 1;
}
ud = ud->next;
}
@@ -156,20 +224,48 @@ void uwsgi_daemons_spawn_all() {
void uwsgi_detach_daemons() {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid > 0 && !ud->pidfile)
kill(-ud->pid, SIGKILL);
#ifdef UWSGI_SSL
// stop any legion daemon, doesn't matter if dumb or smart
if (ud->pid > 0 && (ud->legion || !ud->pidfile)) {
#else
// stop only dumb daemons
if (ud->pid > 0 && !ud->pidfile) {
#endif
uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
// try to stop daemon gracefully, kill it if it won't die
// 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), ud->stop_signal);
sleep(1);
waitpid(ud->pid, &waitpid_status, WNOHANG);
if (uwsgi_now() >= timeout) {
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;
}
}
// unregister daemon to prevent it from being respawned
ud->registered = 0;
}
ud = ud->next;
}
}
static int daemon_spawn(void *);
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
int devnull = -1;
int throttle = 0;
// skip unregistered daemons
if (!ud->registered) return;
ud->throttle = 0;
if (uwsgi.current_time - ud->last_spawn <= 3) {
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
ud->throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
// if ud->respawns == 0 then we can end up with throttle < 0
if (ud->throttle <= 0) ud->throttle = 1;
}
pid_t pid = uwsgi_fork("uWSGI external daemon");
@@ -179,6 +275,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;
@@ -195,9 +292,67 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
uwsgi_close_all_sockets();
uwsgi_close_all_fds();
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && defined(CLONE_NEWPID)
if (ud->ns_pid) {
// we need to create a new session
if (setsid() < 0) {
uwsgi_error("setsid()");
exit(1);
}
// avoid the need to set stop_signal in attach-daemon2
signal(SIGTERM, end_me);
char stack[PTHREAD_STACK_MIN];
pid_t pid = clone((int (*)(void *))daemon_spawn, stack + PTHREAD_STACK_MIN, SIGCHLD | CLONE_NEWPID, (void *) ud);
if (pid > 0) {
#ifdef PR_SET_PDEATHSIG
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("uwsgi_spawn_daemon()/prctl()");
}
#endif
// block all signals except SIGTERM
sigset_t smask;
sigfillset(&smask);
sigdelset(&smask, SIGTERM);
sigprocmask(SIG_BLOCK, &smask, NULL);
int status;
if (waitpid(pid, &status, 0) < 0) {
uwsgi_error("uwsgi_spawn_daemon()/waitpid()");
}
_exit(0);
}
uwsgi_error("uwsgi_spawn_daemon()/clone()");
exit(1);
}
#endif
daemon_spawn((void *) ud);
}
}
static int daemon_spawn(void *arg) {
struct uwsgi_daemon *ud = (struct uwsgi_daemon *) arg;
if (ud->gid) {
if (setgid(ud->gid)) {
uwsgi_error("uwsgi_spawn_daemon()/setgid()");
exit(1);
}
}
if (ud->uid) {
if (setuid(ud->uid)) {
uwsgi_error("uwsgi_spawn_daemon()/setuid()");
exit(1);
}
}
if (ud->daemonize) {
/* refork... */
pid = fork();
pid_t pid = fork();
if (pid < 0) {
uwsgi_error("fork()");
exit(1);
@@ -208,18 +363,9 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
uwsgi_write_pidfile(ud->pidfile);
}
// /dev/null will became stdin
devnull = open("/dev/null", O_RDONLY);
if (devnull < 0) {
uwsgi_error("/dev/null open()");
exit(1);
}
if (devnull != 0) {
if (dup2(devnull, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(devnull);
if (!uwsgi.daemons_honour_stdin && !ud->honour_stdin) {
// /dev/null will became stdin
uwsgi_remap_fd(0, "/dev/null");
}
if (setsid() < 0) {
@@ -228,7 +374,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
}
if (!ud->pidfile) {
#ifdef __linux__
#ifdef PR_SET_PDEATHSIG
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
@@ -236,20 +382,17 @@ 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);
if (ud->throttle) {
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, ud->throttle);
sleep((unsigned int) ud->throttle);
}
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\" (uid: %d gid: %d)\n", ud->respawns > 0 ? "re" : "", ud->command, (int) getuid(), (int) getgid());
uwsgi_exec_command_with_args(ud->command);
uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command);
// never here;
exit(1);
}
return;
}
@@ -259,11 +402,28 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
char *pidfile = NULL;
int daemonize = 0;
int freq = 10;
char *space = NULL;
int stop_signal = SIGTERM;
int reload_signal = 0;
char *command = uwsgi_str(value);
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2")) {
char *space = strchr(command, ' ');
#ifdef UWSGI_SSL
char *legion = NULL;
if (!uwsgi_starts_with(opt, strlen(command), "legion-", 7)) {
space = strchr(command, ' ');
if (!space) {
uwsgi_log("invalid legion daemon syntax: %s\n", command);
exit(1);
}
*space = 0;
legion = command;
command = space+1;
}
#endif
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon") || !strcmp(opt, "legion-smart-attach-daemon2")) {
space = strchr(command, ' ');
if (!space) {
uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
exit(1);
@@ -277,13 +437,13 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
freq = atoi(comma + 1);
}
command = space + 1;
if (!strcmp(opt, "smart-attach-daemon2")) {
if (!strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon2")) {
daemonize = 1;
}
}
if (!uwsgi_ud) {
uwsgi.daemons = uwsgi_malloc(sizeof(struct uwsgi_daemon));
uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
uwsgi_ud = uwsgi.daemons;
}
else {
@@ -292,7 +452,7 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
uwsgi_ud = uwsgi_ud->next;
}
uwsgi_ud = uwsgi_malloc(sizeof(struct uwsgi_daemon));
uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
old_ud->next = uwsgi_ud;
}
@@ -306,7 +466,117 @@ 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;
uwsgi_ud->stop_signal = stop_signal;
uwsgi_ud->reload_signal = reload_signal;
if (!strcmp(opt, "attach-control-daemon")) {
uwsgi_ud->control = 1;
}
#ifdef UWSGI_SSL
uwsgi_ud->legion = legion;
#endif
uwsgi.daemons_cnt++;
}
void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {
struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;
char *d_command = NULL;
char *d_freq = NULL;
char *d_pidfile = NULL;
char *d_control = NULL;
char *d_legion = NULL;
char *d_daemonize = NULL;
char *d_touch = NULL;
char *d_stopsignal = NULL;
char *d_reloadsignal = NULL;
char *d_stdin = NULL;
char *d_uid = NULL;
char *d_gid = NULL;
char *d_ns_pid = NULL;
char *arg = uwsgi_str(value);
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"command", &d_command,
"cmd", &d_command,
"exec", &d_command,
"freq", &d_freq,
"pidfile", &d_pidfile,
"control", &d_control,
"daemonize", &d_daemonize,
"daemon", &d_daemonize,
"touch", &d_touch,
"stopsignal", &d_stopsignal,
"stop_signal", &d_stopsignal,
"reloadsignal", &d_reloadsignal,
"reload_signal", &d_reloadsignal,
"stdin", &d_stdin,
"uid", &d_uid,
"gid", &d_gid,
"ns_pid", &d_ns_pid,
NULL)) {
uwsgi_log("invalid --%s keyval syntax\n", opt);
exit(1);
}
if (!d_command) {
uwsgi_log("--%s: you need to specify a 'command' key\n", opt);
exit(1);
}
#ifndef UWSGI_SSL
if (d_legion) {
uwsgi_log("legion subsystem is not supported on this uWSGI version, rebuild with ssl support\n");
exit(1);
}
#endif
if (!uwsgi_ud) {
uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
uwsgi_ud = uwsgi.daemons;
}
else {
while (uwsgi_ud) {
old_ud = uwsgi_ud;
uwsgi_ud = uwsgi_ud->next;
}
uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
old_ud->next = uwsgi_ud;
}
uwsgi_ud->command = d_command;
uwsgi_ud->freq = d_freq ? atoi(d_freq) : 10;
uwsgi_ud->daemonize = d_daemonize ? 1 : 0;
uwsgi_ud->pidfile = d_pidfile;
uwsgi_ud->stop_signal = d_stopsignal ? atoi(d_stopsignal) : SIGTERM;
uwsgi_ud->reload_signal = d_reloadsignal ? atoi(d_reloadsignal) : 0;
uwsgi_ud->control = d_control ? 1 : 0;
uwsgi_ud->uid = d_uid ? atoi(d_uid) : 0;
uwsgi_ud->gid = d_gid ? atoi(d_gid) : 0;
uwsgi_ud->honour_stdin = d_stdin ? 1 : 0;
#ifdef UWSGI_SSL
uwsgi_ud->legion = d_legion;
#endif
uwsgi_ud->ns_pid = d_ns_pid ? 1 : 0;
if (d_touch) {
size_t i,rlen = 0;
char **argv = uwsgi_split_quoted(d_touch, strlen(d_touch), ";", &rlen);
for(i=0;i<rlen;i++) {
uwsgi_string_new_list(&uwsgi_ud->touch, argv[i]);
}
if (argv) free(argv);
}
uwsgi.daemons_cnt++;
free(arg);
}
+859 -135
View File
File diff suppressed because it is too large Load Diff
+23
View File
@@ -1,9 +1,30 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
static int error_page(struct wsgi_request *wsgi_req, struct uwsgi_string_list *l) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, l) {
struct stat st;
if (!stat(usl->value, &st)) {
int fd = open(usl->value, O_RDONLY);
if (fd >= 0) {
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/html", 9)) { close(fd); return 0;}
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) { close(fd); return 0;}
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st.st_size);
return -1;
}
}
}
return 0;
}
// generate internal server error message
void uwsgi_500(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (error_page(wsgi_req, uwsgi.error_page_500)) return;
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21);
}
@@ -11,6 +32,7 @@ void uwsgi_500(struct wsgi_request *wsgi_req) {
void uwsgi_404(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "404 Not Found", 13)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (error_page(wsgi_req, uwsgi.error_page_404)) return;
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Not Found", 9);
}
@@ -18,6 +40,7 @@ void uwsgi_404(struct wsgi_request *wsgi_req) {
void uwsgi_403(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "403 Forbidden", 13)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (error_page(wsgi_req, uwsgi.error_page_403)) return;
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
}
+264 -14
View File
@@ -2,6 +2,233 @@
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_USE_POLL
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int uwsgi_poll_event_queue_max = 0;
struct uwsgi_poll_event {
int nevents;
int max_events;
pthread_mutex_t lock;
struct pollfd *poll;
};
struct uwsgi_poll_event **uwsgi_poll_event_queue;
// all of the public functions must be heavy locked
static int uwsgi_poll_fd_is_registered(struct uwsgi_poll_event *upe, int fd) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
return 1;
}
}
return 0;
}
static int uwsgi_poll_fd_add(struct uwsgi_poll_event *upe, int fd, int event) {
int pos = upe->nevents;
if (pos > upe->max_events) return -1;
upe->poll[pos].fd = fd;
upe->poll[pos].events = event;
upe->nevents++;
return 0;
}
static int uwsgi_poll_fd_del(struct uwsgi_poll_event *upe, int fd) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
if (i < upe->nevents-1) {
memcpy(&upe->poll[i], &upe->poll[i+1], sizeof(struct uwsgi_poll_event) * (upe->nevents - (i+1)));
}
upe->nevents--;
return 0;
}
}
return -1;
}
static void uwsgi_poll_queue_rebuild(struct uwsgi_poll_event *upe) {
// we need to check if some file descriptor is no more valid
int i;
for(i=0;i<upe->nevents;i++) {
if (!uwsgi_valid_fd(upe->poll[i].fd)) {
uwsgi_poll_fd_del(upe, upe->poll[i].fd);
}
}
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
uwsgi_poll_queue_rebuild(upe);
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
if (ret > 0) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].revents) {
*interesting_fd = upe->poll[i].fd;
pthread_mutex_unlock(&upe->lock);
return 1;
}
}
}
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_init() {
if (!uwsgi_poll_event_queue) {
uwsgi_poll_event_queue = uwsgi_calloc(sizeof(struct uwsgi_poll_event *) * uwsgi.max_fd);
}
int eq = uwsgi_poll_event_queue_max;
uwsgi_poll_event_queue[eq] = uwsgi_calloc(sizeof(struct uwsgi_poll_event));
uwsgi_poll_event_queue_max++;
uwsgi_poll_event_queue[eq]->poll = uwsgi_malloc(sizeof(struct pollfd) * uwsgi.max_fd);
uwsgi_poll_event_queue[eq]->max_events = uwsgi.max_fd;
pthread_mutex_init(&uwsgi_poll_event_queue[eq]->lock, NULL);
return eq;
}
void *event_queue_alloc(int nevents) {
return uwsgi_calloc(sizeof(struct pollfd) * nevents);
}
int event_queue_interesting_fd_is_read(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
if (upoll->revents & POLLIN) {
return 1;
}
return 0;
}
int event_queue_fd_write_to_readwrite(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
upe->poll[i].events = POLLIN|POLLOUT;
pthread_mutex_unlock(&upe->lock);
return 0;
}
}
pthread_mutex_unlock(&upe->lock);
return -1;
}
int event_queue_fd_read_to_readwrite(int eq, int fd) {
return event_queue_fd_write_to_readwrite(eq, fd);
}
int event_queue_interesting_fd_is_write(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
if (upoll->revents & POLLOUT) {
return 1;
}
return 0;
}
int event_queue_add_fd_read(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
if (uwsgi_poll_fd_is_registered(upe, fd)) {
pthread_mutex_unlock(&upe->lock);
return 0;
}
int ret = uwsgi_poll_fd_add(upe, fd, POLLIN);
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_add_fd_write(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
if (uwsgi_poll_fd_is_registered(upe, fd)) {
pthread_mutex_unlock(&upe->lock);
return 0;
}
int ret = uwsgi_poll_fd_add(upe, fd, POLLOUT);
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int ret = uwsgi_poll_fd_del(upe, fd);
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
uwsgi_poll_queue_rebuild(upe);
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
int cnt = 0;
if (ret > 0) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].revents) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[cnt];
upoll->fd = upe->poll[i].fd;
upoll->revents = upe->poll[i].revents;
upoll->events = upe->poll[i].events;
cnt++;
}
}
}
pthread_mutex_unlock(&upe->lock);
if (ret <= 0) return ret;
return cnt;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
if (upoll->revents & POLLERR || upoll->revents & POLLHUP || upoll->revents & POLLNVAL) {
return 1;
}
return 0;
}
int event_queue_interesting_fd(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
return upoll->fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
upe->poll[i].events = POLLIN;
pthread_mutex_unlock(&upe->lock);
return 0;
}
}
pthread_mutex_unlock(&upe->lock);
return -1;
}
int event_queue_fd_read_to_write(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
upe->poll[i].events = POLLOUT;
pthread_mutex_unlock(&upe->lock);
return 0;
}
}
pthread_mutex_unlock(&upe->lock);
return -1;
}
#endif
#ifdef UWSGI_EVENT_USE_PORT
#include <port.h>
@@ -33,7 +260,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -44,7 +271,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
int event_queue_fd_read_to_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -55,7 +282,7 @@ int event_queue_fd_read_to_write(int eq, int fd) {
int event_queue_fd_readwrite_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -66,7 +293,7 @@ int event_queue_fd_readwrite_to_read(int eq, int fd) {
int event_queue_fd_readwrite_to_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -77,7 +304,7 @@ int event_queue_fd_readwrite_to_write(int eq, int fd) {
int event_queue_fd_write_to_readwrite(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -88,7 +315,7 @@ int event_queue_fd_write_to_readwrite(int eq, int fd) {
int event_queue_fd_read_to_readwrite(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -124,7 +351,7 @@ int event_queue_interesting_fd_is_write(void *events, int id) {
int event_queue_add_fd_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -134,7 +361,7 @@ int event_queue_add_fd_read(int eq, int fd) {
int event_queue_add_fd_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -149,12 +376,16 @@ void *event_queue_alloc(int nevents) {
int event_queue_interesting_fd(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
#ifdef PORT_SOURCE_FILE
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
#else
if (pe[id].portev_source == PORT_SOURCE_TIMER) {
#endif
return (long) pe[id].portev_user;
}
int fd = (int) pe[id].portev_object;
int eq = (int) pe[id].portev_user;
int eq = (long) pe[id].portev_user;
if (pe[id].portev_events == POLLOUT) {
event_queue_add_fd_write(eq, fd);
@@ -196,7 +427,7 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
port_event_t *pe_i = &pe[i];
if (pe_i->portev_source == PORT_SOURCE_FD) {
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, NULL)) {
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, (void *)((long) eq))) {
uwsgi_error("port_associate");
}
}
@@ -222,22 +453,26 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
ret = port_get(eq, &pe, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
if (errno == ETIME) return 0;
if (errno != EINTR) {
uwsgi_error("port_get()");
return -1;
}
return 0;
return -1;
}
if (pe.portev_source == PORT_SOURCE_FD) {
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, (void *)((long) eq))) {
uwsgi_error("port_associate");
}
}
#ifdef PORT_SOURCE_FILE
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
#else
if (pe.portev_source == PORT_SOURCE_TIMER) {
#endif
*interesting_fd = (long) pe.portev_user;
}
else {
@@ -745,6 +980,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
#ifdef PORT_SOURCE_FILE
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct file_obj fo;
@@ -805,6 +1041,14 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
}
#else
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
return -1;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#endif
#endif
@@ -987,6 +1231,8 @@ static int timerfd_create(clockid_t __clock_id, int __flags) {
return syscall(283, __clock_id, __flags);
#elif defined(__i386__)
return syscall(322, __clock_id, __flags);
#elif defined(__arm__)
return syscall(350, __clock_id, __flags);
#else
return -1;
#endif
@@ -997,6 +1243,10 @@ static int timerfd_settime(int __ufd, int __flags, __const struct itimerspec *__
return syscall(286, __ufd, __flags, __utmr, __otmr);
#elif defined(__i386__)
return syscall(325, __ufd, __flags, __utmr, __otmr);
#elif defined(__arm__)
return syscall(353, __ufd, __flags, __utmr, __otmr);
#else
return -1;
#endif
}
#endif
+3 -3
View File
@@ -322,7 +322,7 @@ void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) {
if (do_exit) goto check_catch;
if (wsgi_req && uwsgi.exception_handlers_instance) {
if (uwsgi.exception_handlers_instance) {
struct uwsgi_buffer *ehi = uwsgi_exception_handler_object(wsgi_req);
if (ehi) {
uwsgi_exception_run_handlers(ehi);
@@ -442,7 +442,7 @@ static void uwsgi_exception_handler_thread_loop(struct uwsgi_thread *ut) {
int interesting_fd = -1;
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
if (ret > 0) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
ssize_t len = read(ut->pipe[1], buf, uwsgi.exception_handler_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
@@ -488,7 +488,7 @@ void uwsgi_exception_setup_handlers() {
}
void uwsgi_exceptions_handler_thread_start() {
if (!uwsgi.exception_handlers_instance) return;
// start the exception_handler_thread
uwsgi.exception_handler_thread = uwsgi_thread_new(uwsgi_exception_handler_thread_loop);
if (!uwsgi.exception_handler_thread) {
+136
View File
@@ -0,0 +1,136 @@
#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;
}
#define announce_fifo uwsgi_log_verbose("active master fifo is now %s\n", uwsgi_fifo_by_slot())
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; announce_fifo; }
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; announce_fifo; }
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; announce_fifo; }
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; announce_fifo; }
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; announce_fifo; }
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; announce_fifo; }
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; announce_fifo; }
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; announce_fifo; }
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; announce_fifo; }
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; announce_fifo; }
static void subscriptions_blocker() {
if (uwsgi.subscriptions_blocked) {
uwsgi_log_verbose("subscriptions re-enabled\n");
uwsgi.subscriptions_blocked = 0;
}
else {
uwsgi.subscriptions_blocked = 1;
uwsgi_log_verbose("subscriptions blocked\n");
}
}
/*
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['S'] = subscriptions_blocker;
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;
}
+189
View File
@@ -0,0 +1,189 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
#include <sys/inotify.h>
#endif
#endif
static int fsmon_add(struct uwsgi_fsmon *fs) {
#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("fsmon_add()/inotify_init()");
return -1;
}
if (event_queue_add_fd_read(uwsgi.master_queue, inotify_fd)) {
uwsgi_error("fsmon_add()/event_queue_add_fd_read()");
return -1;
}
}
int wd = inotify_add_watch(inotify_fd, fs->path, 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("fsmon_add()/inotify_add_watch()");
return -1;
}
fs->fd = inotify_fd;
fs->id = wd;
return 0;
#endif
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
struct kevent kev;
int fd = open(fs->path, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(fs->path);
uwsgi_error("fsmon_add()/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("fsmon_add()/kevent()");
return -1;
}
fs->fd = fd;
return 0;
#endif
uwsgi_log("[uwsgi-fsmon] filesystem monitoring interface not available in this platform !!!\n");
return 1;
}
static void fsmon_reload(struct uwsgi_fsmon *fs) {
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
}
static void fsmon_brutal_reload(struct uwsgi_fsmon *fs) {
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);
}
}
static void fsmon_signal(struct uwsgi_fsmon *fs) {
uwsgi_route_signal(atoi((char *) fs->data));
}
void uwsgi_fsmon_setup() {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.fs_reload) {
uwsgi_register_fsmon(usl->value, fsmon_reload, NULL);
}
uwsgi_foreach(usl, uwsgi.fs_brutal_reload) {
uwsgi_register_fsmon(usl->value, fsmon_brutal_reload, NULL);
}
uwsgi_foreach(usl, uwsgi.fs_signal) {
char *copy = uwsgi_str(usl->value);
char *space = strchr(copy, ' ');
if (!space) {
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
free(copy);
continue;
}
*space = 0;
uwsgi_register_fsmon(copy, fsmon_signal, space + 1);
}
struct uwsgi_fsmon *fs = uwsgi.fsmon;
while (fs) {
if (fsmon_add(fs)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", fs->path);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", fs->path);
}
fs = fs->next;
}
}
struct uwsgi_fsmon *uwsgi_register_fsmon(char *path, void (*func) (struct uwsgi_fsmon *), void *data) {
struct uwsgi_fsmon *old_fs = NULL, *fs = uwsgi.fsmon;
while(fs) {
old_fs = fs;
fs = fs->next;
}
fs = uwsgi_calloc(sizeof(struct uwsgi_fsmon));
fs->path = path;
fs->func = func;
fs->data = data;
if (old_fs) {
old_fs->next = fs;
}
else {
uwsgi.fsmon = fs;
}
return fs;
}
static struct uwsgi_fsmon *uwsgi_fsmon_ack(int interesting_fd) {
struct uwsgi_fsmon *found_fs = NULL;
struct uwsgi_fsmon *fs = uwsgi.fsmon;
while (fs) {
if (fs->fd == interesting_fd) {
found_fs = fs;
break;
}
fs = fs->next;
}
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
if (!found_fs)
return NULL;
found_fs = NULL;
unsigned int isize = 0;
if (ioctl(interesting_fd, FIONREAD, &isize) < 0) {
uwsgi_error("uwsgi_fsmon_ack()/ioctl()");
return NULL;
}
if (isize == 0)
return NULL;
struct inotify_event *ie = uwsgi_malloc(isize);
// read from the inotify descriptor
ssize_t len = read(interesting_fd, ie, isize);
if (len < 0) {
free(ie);
uwsgi_error("uwsgi_fsmon_ack()/read()");
return NULL;
}
fs = uwsgi.fsmon;
while (fs) {
if (fs->fd == interesting_fd && fs->id == ie->wd) {
found_fs = fs;
break;
}
fs = fs->next;
}
free(ie);
#endif
#endif
return found_fs;
}
int uwsgi_fsmon_event(int interesting_fd) {
struct uwsgi_fsmon *fs = uwsgi_fsmon_ack(interesting_fd);
if (!fs)
return 0;
uwsgi_log_verbose("[uwsgi-fsmon] detected event on \"%s\"\n", fs->path);
fs->func(fs);
return 1;
}
+32 -2
View File
@@ -18,7 +18,9 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
}
}
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
char *str = uwsgi_num2str(num);
char *fullname = uwsgi_concat3(name, " ", str);
free(str);
ug = &ushared->gateways[ushared->gateways_cnt];
ug->pid = 0;
@@ -27,12 +29,21 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
ug->num = num;
ug->fullname = fullname;
ug->data = data;
ug->uid = 0;
ug->gid = 0;
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
#endif
uwsgi_error("socketpair()");
}
if (!uwsgi.master_process)
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
if (!uwsgi.master_process && !uwsgi.force_gateway)
gateway_respawn(ushared->gateways_cnt);
ushared->gateways_cnt++;
@@ -61,6 +72,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__
@@ -80,6 +92,24 @@ void gateway_respawn(int id) {
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi_hooks_run(uwsgi.hook_as_gateway, "as-gateway", 1);
if (ug->gid) {
uwsgi_log("%s %d setgid() to %d\n", ug->name, ug->num, (int) ug->gid);
if (setgid(ug->gid)) {
uwsgi_error("gateway_respawn()/setgid()");
exit(1);
}
}
if (ug->uid) {
uwsgi_log("%s %d setuid() to %d\n", ug->name, ug->num, (int) ug->uid);
if (setuid(ug->uid)) {
uwsgi_error("gateway_respawn()/setuid()");
exit(1);
}
}
ug->loop(id, ug->data);
// never here !!! (i hope)
exit(1);
+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);
}
+567
View File
@@ -0,0 +1,567 @@
#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_alarm(char *arg) {
char *space = strchr(arg,' ');
if (!space) {
uwsgi_log("invalid alarm hook syntax, must be: <alarm> <msg>\n");
return -1;
}
*space = 0;
uwsgi_alarm_trigger(arg, space+1, strlen(space+1));
*space = ' ';
return 0;
}
static int uwsgi_hook_chdir(char *arg) {
int ret = chdir(arg);
if (ret) {
uwsgi_error("uwsgi_hook_chdir()");
}
return ret;
}
static int uwsgi_hook_mkdir(char *arg) {
int ret = mkdir(arg, 0777);
if (ret) {
uwsgi_error("uwsgi_hook_mkdir()");
}
return ret;
}
static int uwsgi_hook_putenv(char *arg) {
int ret = putenv(arg);
if (ret) {
uwsgi_error("uwsgi_hook_putenv()");
}
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_unlink(char *arg) {
int ret = unlink(arg);
if (ret) {
uwsgi_error("uwsgi_hook_unlink()/unlink()");
}
return ret;
}
static int uwsgi_hook_writefifo(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook writefifo syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_NONBLOCK);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
if (errno == ENODEV) return 0;
#ifdef ENXIO
if (errno == ENXIO) return 0;
#endif
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
if (write(fd, space+1, l) != (ssize_t) l) {
uwsgi_error("uwsgi_hook_writefifo()/write()");
close(fd);
return -1;
}
close(fd);
return 0;
}
static int uwsgi_hook_write(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook write syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
if (write(fd, space+1, l) != (ssize_t) l) {
uwsgi_error("uwsgi_hook_write()/write()");
close(fd);
return -1;
}
close(fd);
return 0;
}
static int uwsgi_hook_creat(char *arg) {
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (fd < 0) {
uwsgi_error_open(arg);
return -1;
}
close(fd);
return 0;
}
static int uwsgi_hook_append(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook append syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
if (write(fd, space+1, l) != (ssize_t) l) {
uwsgi_error("uwsgi_hook_append()/write()");
close(fd);
return -1;
}
close(fd);
return 0;
}
static int uwsgi_hook_writen(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook writen syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
char *buf = uwsgi_malloc(l + 1);
memcpy(buf, space+1, l);
buf[l] = '\n';
if (write(fd, buf, l+1) != (ssize_t) (l+1)) {
uwsgi_error("uwsgi_hook_writen()/write()");
free(buf);
close(fd);
return -1;
}
free(buf);
close(fd);
return 0;
}
static int uwsgi_hook_appendn(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook appendn syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
char *buf = uwsgi_malloc(l + 1);
memcpy(buf, space+1, l);
buf[l] = '\n';
if (write(fd, buf, l+1) != (ssize_t) (l+1)) {
uwsgi_error("uwsgi_hook_appendn()/write()");
free(buf);
close(fd);
return -1;
}
free(buf);
close(fd);
return 0;
}
static int uwsgi_hook_chmod(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook chmod syntax, must be: <file> <mode>\n");
return -1;
}
*space = 0;
int error = 0;
mode_t mask = uwsgi_mode_t(space+1, &error);
if (error) {
uwsgi_log("invalid hook chmod mask: %s\n", space+1);
*space = ' ';
return -1;
}
int ret = chmod(arg, mask);
*space = ' ';
if (ret) {
uwsgi_error("uwsgi_hook_chmod()/chmod()");
}
return ret;
}
static int uwsgi_hook_sticky(char *arg) {
struct stat st;
if (stat(arg, &st)) {
uwsgi_error("uwsgi_hook_sticky()/stat()");
return -1;
}
if (chmod(arg, st.st_mode | S_ISVTX)) {
uwsgi_error("uwsgi_hook_sticky()/chmod()");
return -1;
}
return 0;
}
static int uwsgi_hook_chown(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook chown syntax, must be: <file> <uid> <gid>\n");
return -1;
}
*space = 0;
char *space2 = strchr(space+1, ' ');
if (!space2) {
*space = ' ';
uwsgi_log("invalid hook chown syntax, must be: <file> <uid> <gid>\n");
return -1;
}
*space2 = 0;
struct passwd *pw = getpwnam(space+1);
if (!pw) {
uwsgi_log("unable to find uid %s\n", space+1);
*space = ' ';
*space2 = ' ';
return -1;
}
struct group *gr = getgrnam(space2+1);
if (!gr) {
uwsgi_log("unable to find gid %s\n", space2+1);
*space = ' ';
*space2 = ' ';
return -1;
}
int ret = chown(arg, pw->pw_uid, gr->gr_gid);
*space = ' ';
*space2 = ' ';
if (ret) {
uwsgi_error("uwsgi_hook_chown()/chown)");
}
return ret;
}
static int uwsgi_hook_chown2(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook chown2 syntax, must be: <file> <uid> <gid>\n");
return -1;
}
*space = 0;
char *space2 = strchr(space+1, ' ');
if (!space2) {
*space = ' ';
uwsgi_log("invalid hook chown2 syntax, must be: <file> <uid> <gid>\n");
return -1;
}
*space2 = 0;
if (!is_a_number(space+1)) {
uwsgi_log("invalid hook chown2 syntax, uid must be a number\n");
*space = ' ';
*space2 = ' ';
return -1;
}
if (!is_a_number(space2+1)) {
uwsgi_log("invalid hook chown2 syntax, gid must be a number\n");
*space = ' ';
*space2 = ' ';
return -1;
}
int ret = chown(arg, atoi(space+1), atoi(space2+1));
*space = ' ';
*space2 = ' ';
if (ret) {
uwsgi_error("uwsgi_hook_chown2()/chown)");
}
return ret;
}
#ifdef __sun__
extern int sethostname(char *, int);
#endif
static int uwsgi_hook_hostname(char *arg) {
#ifdef __CYGWIN__
return -1;
#else
return sethostname(arg, strlen(arg));
#endif
}
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("chdir", uwsgi_hook_chdir);
uwsgi_register_hook("mkdir", uwsgi_hook_mkdir);
uwsgi_register_hook("putenv", uwsgi_hook_putenv);
uwsgi_register_hook("chmod", uwsgi_hook_chmod);
uwsgi_register_hook("chown", uwsgi_hook_chown);
uwsgi_register_hook("chown2", uwsgi_hook_chown2);
uwsgi_register_hook("sticky", uwsgi_hook_sticky);
uwsgi_register_hook("exec", uwsgi_hook_exec);
uwsgi_register_hook("create", uwsgi_hook_creat);
uwsgi_register_hook("creat", uwsgi_hook_creat);
uwsgi_register_hook("write", uwsgi_hook_write);
uwsgi_register_hook("writen", uwsgi_hook_writen);
uwsgi_register_hook("append", uwsgi_hook_append);
uwsgi_register_hook("appendn", uwsgi_hook_appendn);
uwsgi_register_hook("writefifo", uwsgi_hook_writefifo);
uwsgi_register_hook("unlink", uwsgi_hook_unlink);
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);
uwsgi_register_hook("hostname", uwsgi_hook_hostname);
uwsgi_register_hook("alarm", uwsgi_hook_alarm);
// for testing
uwsgi_register_hook("exit", uwsgi_hook_exit);
uwsgi_register_hook("print", uwsgi_hook_print);
uwsgi_register_hook("log", 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;
int private = 0;
char *action = usl->value;
// private hook ?
if (action[0] == '!') {
action++;
private = 1;
}
struct uwsgi_hook *uh = uwsgi_hook_by_name(action);
if (!uh) {
uwsgi_log("hook action not found: %s\n", action);
exit(1);
}
*colon = ':';
if (private) {
uwsgi_log("running --- PRIVATE HOOK --- (%s)...\n", phase);
}
else {
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
}
int ret = uh->func(colon+1);
if (fatal && ret != 0) {
exit(1);
}
}
}
+20 -6
View File
@@ -1,6 +1,4 @@
#ifdef UWSGI_INI
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -9,6 +7,8 @@ extern struct uwsgi_server uwsgi;
This memory must not be freed for all the server lifecycle
*/
static char *last_file = NULL;
void ini_rstrip(char *line) {
off_t i;
@@ -91,6 +91,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
char *section_asked = "uwsgi";
char *colon;
int got_section = 0;
if (uwsgi_check_scheme(file)) {
@@ -106,13 +107,23 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
if (colon[1] != 0) {
section_asked = colon + 1;
}
if (colon == file) {
file = last_file;
}
}
if (file[0] != 0) {
if (file[0] != 0 && file != last_file) {
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
}
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
if (file != last_file) {
if (last_file) {
free(last_file);
}
last_file = uwsgi_str(file);
}
while (len) {
ini_line = ini_get_line(ini, len);
@@ -137,6 +148,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
val = ini_get_key(key);
if (!strcmp(section, section_asked)) {
got_section = 1;
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
@@ -151,11 +163,13 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
if (!got_section) {
uwsgi_log("*** WARNING: Can't find section \"%s\" in INI configuration file %s ***\n", section_asked, file);
}
if (colon) {
colon[0] = ':';
}
}
#endif
+60 -20
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;
@@ -114,13 +117,13 @@ void uwsgi_init_default() {
uwsgi.max_vars = MAX_VARS;
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
uwsgi.socket_timeout = 4;
uwsgi.logging_options.enabled = 1;
// a workers hould be running for at least 10 seconds
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] = 10;
uwsgi.min_worker_lifetime = 10;
uwsgi.shared->spooler_frequency = 30;
uwsgi.spooler_frequency = 30;
uwsgi.shared->spooler_signal_pipe[0] = -1;
uwsgi.shared->spooler_signal_pipe[1] = -1;
@@ -161,10 +164,27 @@ void uwsgi_init_default() {
uwsgi.empty = "";
#ifdef __linux__
uwsgi.cgroup_dir_mode = "0700";
#endif
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
uwsgi.wait_milliseconds_hook = uwsgi_simple_wait_milliseconds_hook;
uwsgi.wait_read2_hook = uwsgi_simple_wait_read2_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();
uwsgi.notify_socket_fd = -1;
}
void uwsgi_setup_reload() {
@@ -178,7 +198,7 @@ void uwsgi_setup_reload() {
uwsgi.reloads++;
//convert reloads to string
int rlen = snprintf(env_reload_buf, 10, "%u", uwsgi.reloads);
if (rlen > 0) {
if (rlen > 0 && rlen < 10) {
env_reload_buf[rlen] = 0;
if (setenv("UWSGI_RELOADS", env_reload_buf, 1)) {
uwsgi_error("setenv()");
@@ -209,21 +229,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, ",");
}
}
@@ -332,7 +350,6 @@ void uwsgi_setup_workers() {
uwsgi.workers[i].signal_pipe[0] = -1;
uwsgi.workers[i].signal_pipe[1] = -1;
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
}
uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
@@ -347,6 +364,13 @@ void uwsgi_setup_workers() {
// allocate signal table
uwsgi.shared->signal_table = uwsgi_calloc_shared(sizeof(struct uwsgi_signal_entry) * 256 * (uwsgi.numproc + 1));
#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
}
pid_t uwsgi_daemonize2() {
@@ -374,6 +398,8 @@ pid_t uwsgi_daemonize2() {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
if (uwsgi.log_master) uwsgi_setup_log_master();
return uwsgi.mypid;
}
@@ -389,7 +415,7 @@ void sanitize_args() {
uwsgi.cores = uwsgi.threads;
}
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
if (uwsgi.harakiri_options.workers > 0) {
if (!uwsgi.post_buffering) {
uwsgi_log(" *** WARNING: you have enabled harakiri without post buffering. Slow upload could be rejected on post-unbuffered webservers *** \n");
}
@@ -425,17 +451,31 @@ void sanitize_args() {
}
}
if (uwsgi.auto_snapshot > 0 && uwsgi.auto_snapshot > uwsgi.numproc) {
uwsgi_log("invalid auto-snapshot value: must be <= than processes\n");
exit(1);
}
if (uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0 && uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] >= uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]) {
if (uwsgi.max_worker_lifetime > 0 && uwsgi.min_worker_lifetime >= uwsgi.max_worker_lifetime) {
uwsgi_log("invalid min-worker-lifetime value (%d), must be lower than max-worker-lifetime (%d)\n",
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME], uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]);
uwsgi.min_worker_lifetime, uwsgi.max_worker_lifetime);
exit(1);
}
if (uwsgi.cheaper_rss_limit_soft && uwsgi.logging_options.memory_report != 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) {
+660 -204
View File
File diff suppressed because it is too large Load Diff
+201 -4
View File
@@ -4,13 +4,207 @@
extern struct uwsgi_server uwsgi;
#if defined(UWSGI_JSON_YAJL_OLD)
#include <yajl/yajl_parse.h>
struct uwsgi_yajl_old_state {
char *object;
char *key;
int in_object;
int is_array;
};
static int uwsgi_yajl_cb_null(void *ctx) {
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
if (!uyos->key) return 1;
add_exported_option(uyos->key, strdup("0"), 0);
return 1;
}
static int uwsgi_yajl_cb_boolean(void *ctx, int b) {
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
if (!uyos->key) return 1;
if (b) {
add_exported_option(uyos->key, strdup("1"), 0);
}
else {
add_exported_option(uyos->key, strdup("0"), 0);
}
return 1;
}
static int uwsgi_yajl_cb_integer(void *ctx, long n) {
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
if (!uyos->key) return 1;
add_exported_option(uyos->key, uwsgi_64bit2str((int64_t) n), 0);
return 1;
}
static int uwsgi_yajl_cb_double(void *ctx, double n) {
return uwsgi_yajl_cb_integer(ctx, (long) n);
}
static int uwsgi_yajl_cb_string(void *ctx, const unsigned char *s, unsigned int s_len) {
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
if (!uyos->key) return 1;
add_exported_option(uyos->key, uwsgi_concat2n((char *)s, (size_t)s_len, "", 0), 0);
return 1;
}
static int uwsgi_yajl_cb_number(void *ctx, const char *n, unsigned int n_len) {
return uwsgi_yajl_cb_string(ctx, (const unsigned char *)n, n_len);
}
static int uwsgi_yajl_cb_map_key(void *ctx, const unsigned char *s, unsigned int s_len) {
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
if (!uyos->in_object) {
if (!uwsgi_strncmp(uyos->object, strlen(uyos->object), (char *)s, (size_t)s_len)) {
uyos->in_object = 1;
}
return 1;
}
uyos->key = uwsgi_concat2n((char *)s, (size_t)s_len, "", 0);
return 1;
}
static yajl_callbacks callbacks = {
.yajl_null = uwsgi_yajl_cb_null,
.yajl_boolean = uwsgi_yajl_cb_boolean,
.yajl_integer = uwsgi_yajl_cb_integer,
.yajl_double = uwsgi_yajl_cb_double,
.yajl_number = uwsgi_yajl_cb_number,
.yajl_string = uwsgi_yajl_cb_string,
.yajl_start_map = NULL,
.yajl_map_key = uwsgi_yajl_cb_map_key,
.yajl_end_map = NULL,
.yajl_start_array = NULL,
.yajl_end_array = NULL,
};
void uwsgi_json_config(char *file, char *magic_table[]) {
size_t len = 0;
char *object_asked = "uwsgi";
char *colon;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
object_asked = colon + 1;
}
}
struct uwsgi_yajl_old_state uyos;
memset(&uyos, 0, sizeof(struct uwsgi_yajl_old_state));
uyos.object = object_asked;
uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file);
char *json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
yajl_handle hand = yajl_alloc(&callbacks, NULL, NULL, &uyos);
yajl_status s = yajl_parse(hand, (const unsigned char *)json_data, len);
if (s != yajl_status_ok) {
uwsgi_log("%s\n", yajl_get_error(hand, 1, (const unsigned char *)json_data, len));
exit(1);
}
}
#elif defined(UWSGI_JSON_YAJL)
#include <yajl/yajl_tree.h>
void uwsgi_json_config(char *file, char *magic_table[]) {
size_t len = 0;
char *object_asked = "uwsgi";
char *colon;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
object_asked = colon + 1;
}
}
uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file);
char *json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
char errbuf[1024];
yajl_val node = yajl_tree_parse((const char *)json_data, errbuf, sizeof(errbuf));
if (!node) {
uwsgi_log("error parsing JSON data: %s\n", errbuf);
exit(1);
}
const char * path[] = { object_asked, NULL };
yajl_val v = yajl_tree_get(node, path, yajl_t_any);
if (!YAJL_IS_OBJECT(v)) {
uwsgi_log("you must define a object named %s in your JSON data\n", object_asked);
exit(1);
}
size_t i;
for(i=0;i<v->u.object.len;i++) {
char *key = (char *) v->u.object.keys[i];
yajl_val o = v->u.object.values[i];
if (YAJL_IS_STRING(o)) {
add_exported_option(key, YAJL_GET_STRING(o) , 0);
}
else if (YAJL_IS_TRUE(o)) {
add_exported_option(key, strdup("1"), 0);
}
else if (YAJL_IS_FALSE(o) || YAJL_IS_NULL(o)) {
add_exported_option(key, strdup("0"), 0);
}
else if (YAJL_IS_NUMBER(o) || YAJL_IS_INTEGER(o)) {
add_exported_option(key, YAJL_GET_NUMBER(o), 0);
}
else if (YAJL_IS_ARRAY(o)) {
size_t j;
for(j=0;j<o->u.array.len;j++) {
yajl_val a_o = o->u.array.values[j];
if (YAJL_IS_STRING(a_o)) {
add_exported_option(key, YAJL_GET_STRING(a_o) , 0);
}
else if (YAJL_IS_TRUE(a_o)) {
add_exported_option(key, strdup("1"), 0);
}
else if (YAJL_IS_FALSE(a_o) || YAJL_IS_NULL(a_o)) {
add_exported_option(key, strdup("0"), 0);
}
else if (YAJL_IS_NUMBER(a_o) || YAJL_IS_INTEGER(a_o)) {
add_exported_option(key, YAJL_GET_NUMBER(a_o), 0);
}
}
}
}
}
#else
#include <jansson.h>
/*
I really love the jansson library...
*/
void uwsgi_json_config(char *file, char *magic_table[]) {
size_t len = 0;
@@ -106,6 +300,9 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
config_iter = json_object_iter_next(config, config_iter);
}
if (colon) colon[0] = ':';
}
#endif
#endif
-370
View File
@@ -1,370 +0,0 @@
#ifdef UWSGI_LDAP
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#include <ldap.h>
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
#ifndef ldap_unbind_ext_s
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
int i;
for (i = 0; i < (int) strlen(ldapname); i++) {
if (isupper((int) ldapname[i])) {
*ptr++ = '-';
*ptr++ = tolower((int) ldapname[i]);
}
else {
*ptr++ = ldapname[i];
}
}
*ptr++ = 0;
}
int calc_ldap_name(char *name) {
int i;
int counter = 0;
for (i = 0; i < (int) strlen(name); i++) {
if (isupper((int) name[i])) {
counter++;
}
}
return strlen(name) + counter;
}
struct uwsgi_ldap_entry {
int num;
char names[1024];
int has_arg;
};
void uwsgi_name_to_ldap(char *src, char *dst) {
int i;
char *ptr = dst;
memset(dst, 0, 1024);
strcat(dst, " 'uWSGI");
ptr += 7;
for (i = 0; i < (int) strlen(src); i++) {
if (src[i] == '-') {
i++;
*ptr++ = toupper((int) src[i]);
}
else {
*ptr++ = src[i];
}
}
strcat(dst, "'");
}
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for (i = 0; i < count; i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for (i = 0; i < count; i++) {
ule = &root[i];
if (uwsgi_list_has_str(ule->names, name + 1)) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct uwsgi_option *op = uwsgi.options;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
*count = 0;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry) * uwsgi_count_options(op));
while (op && op->name) {
uwsgi_name_to_ldap((char *) op->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry)
goto next;
entry = &ule[*count];
entry->num = *count;
strcpy(entry->names, ldap_name);
*count = *count + 1;
entry->has_arg = op->type;
next:
op++;
}
return ule;
}
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
int i;
int items;
uwsgi_log("\n");
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
uwsgi_log("objectClass: olcSchemaConfig\n");
uwsgi_log("cn: uwsgi\n");
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for (i = 0; i < items; i++) {
entry = &ule[i];
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for (i = 0; i < items; i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names + 1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGInull ))\n");
uwsgi_log("\n");
exit(0);
}
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
int i;
int items;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for (i = 0; i < items; i++) {
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for (i = 0; i < items; i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names + 1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGInull ))\n");
exit(0);
}
void uwsgi_ldap_config(char *url) {
LDAP *ldp;
LDAPMessage *results, *entry;
BerElement *ber;
struct berval **bervalues;
char *attr;
char *uwsgi_attr;
char *url_slash;
int desired_version = LDAP_VERSION3;
int ret;
LDAPURLDesc *ldap_url;
if (!ldap_is_ldap_url(url)) {
uwsgi_log("invalid LDAP url.\n");
exit(1);
}
if (ldap_url_parse(url, &ldap_url) != LDAP_SUCCESS) {
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
url_slash = strchr(url, '/');
url_slash = strchr(url_slash + 1, '/');
url_slash = strchr(url_slash + 1, '/');
if (url_slash) {
url_slash[0] = 0;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP URL: %s\n", url);
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
#endif
#if LDAP_API_VERSION >= 3000
if ((ret = ldap_initialize(&ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ((ldp = ldap_init(ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ((ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
if ((ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP connection initialized %p\n", ldp);
#endif
free(ldap_url);
if (ldap_count_entries(ldp, results) < 1) {
uwsgi_log("no LDAP entry found\n");
exit(1);
}
entry = ldap_first_entry(ldp, results);
int found = 0;
for (attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr, "uWSGI", 5)) {
found = 1;
uwsgi_attr = malloc(calc_ldap_name(attr) + 1);
if (!uwsgi_attr) {
uwsgi_error("malloc()");
exit(1);
}
ldap2uwsgi(attr + 5, uwsgi_attr);
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP attribute: %s = --%s\n", attr, uwsgi_attr);
#endif
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_attr/uwsgi_val;
char *uwsgi_val = malloc(bervalues[0]->bv_len + 1);
if (!uwsgi_val) {
uwsgi_error("malloc()");
exit(1);
}
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
add_exported_option((char *) uwsgi_attr, uwsgi_val, 0);
free(bervalues);
}
else {
free(uwsgi_attr);
}
}
free(attr);
}
if (!found) {
uwsgi_log("no uWSGI LDAP entry found\n");
exit(1);
}
free(ber);
free(results);
ldap_unbind_ext_s(ldp, NULL, NULL);
}
#endif
+276 -47
View File
@@ -79,6 +79,40 @@ 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)
static void legion_rebuild_scrolls(struct uwsgi_legion *ul) {
uint64_t max_size = ul->scrolls_max_size;
// first, try to add myself
if (ul->scroll_len + (uint64_t) 2 > max_size) {
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
ul->scroll_len = 0;
return;
}
char *ptr = ul->scrolls;
*ptr ++= (uint8_t) (ul->scroll_len & 0xff);
*ptr ++= (uint8_t) ((ul->scroll_len >> 8) &0xff);
memcpy(ptr, ul->scroll, ul->scroll_len); ptr += ul->scroll_len;
ul->scrolls_len = 2 + ul->scroll_len;
// ok start adding nodes;
struct uwsgi_legion_node *uln = ul->nodes_head;
while(uln) {
if (ul->scrolls_len + 2 + uln->scroll_len > max_size) {
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
return;
}
*ptr ++= (uint8_t) (uln->scroll_len & 0xff);
*ptr ++= (uint8_t) ((uln->scroll_len >> 8) &0xff);
memcpy(ptr, uln->scroll, uln->scroll_len); ptr += uln->scroll_len;
ul->scrolls_len += 2 + uln->scroll_len;
uln = uln->next;
}
}
// critical section (remember to lock when you use it)
@@ -104,6 +138,7 @@ struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_
ul->nodes_head = node;
}
return node;
@@ -141,6 +176,8 @@ void uwsgi_legion_remove_node(struct uwsgi_legion *ul, struct uwsgi_legion_node
}
free(node);
legion_rebuild_scrolls(ul);
}
struct uwsgi_legion_node *uwsgi_legion_get_node(struct uwsgi_legion *ul, uint64_t valor, char *name, uint16_t name_len, char *uuid) {
@@ -169,14 +206,22 @@ static void legions_check_nodes() {
struct uwsgi_legion_node *node = legion->nodes_head;
while (node) {
if (now - node->last_seen > uwsgi.legion_tolerance) {
struct uwsgi_legion_node *tmp_node = node;
node = node->next;
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->valor > 0 ? "node" : "arbiter", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
uwsgi_wlock(legion->lock);
uwsgi_legion_remove_node(legion, tmp_node);
uwsgi_rwunlock(legion->lock);
// trigger node_left hooks
struct uwsgi_string_list *usl = legion->node_left_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("node_left", legion, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, node_left hook returned: %d\n", ret);
}
usl = usl->next;
}
continue;
}
node = node->next;
@@ -190,12 +235,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *);
static void legions_report_quorum(struct uwsgi_legion *ul, uint64_t best_valor, char *best_uuid, int votes) {
struct uwsgi_legion_node *nodes = ul->nodes_head;
uwsgi_log("\n[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
uwsgi_log("[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
while (nodes) {
uwsgi_log("[uwsgi-legion-node] node: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
uwsgi_log("[uwsgi-legion-node] %s: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->valor > 0 ? "node" : "arbiter", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
nodes = nodes->next;
}
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n\n");
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n");
}
uint64_t uwsgi_legion_checksum(struct uwsgi_legion *ul) {
@@ -231,11 +276,19 @@ static void legions_check_nodes_step2() {
best_valor = node->valor;
memcpy(best_uuid, node->uuid, 36);
}
else {
// go on if i am not an arbiter
else if (ul->valor > 0) {
// no potential Lord is available, i will propose myself
best_valor = ul->valor;
memcpy(best_uuid, ul->uuid, 36);
i_am_the_best = 1;
// but only if i am not suspended...
if (uwsgi_now() > ul->suspended_til) {
best_valor = ul->valor;
memcpy(best_uuid, ul->uuid, 36);
i_am_the_best = 1;
}
}
else {
// empty lord
memset(best_uuid, 0, 36);
}
// calculate the checksum
@@ -268,6 +321,18 @@ static void legions_check_nodes_step2() {
// we have quorum !!!
if (votes > 0 && votes >= ul->quorum) {
if (!ul->joined) {
// triggering join hooks
struct uwsgi_string_list *usl = ul->join_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("join", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, join hook returned: %d\n", ret);
}
usl = usl->next;
}
ul->joined = 1;
}
// something changed ???
if (ul->changed) {
legions_report_quorum(ul, best_valor, best_uuid, votes);
@@ -275,13 +340,20 @@ static void legions_check_nodes_step2() {
}
if (i_am_the_best) {
if (!ul->i_am_the_lord) {
uwsgi_log("[uwsgi-legion] i am now the Lord of the Legion %s\n", ul->legion);
// triggering lord hooks
uwsgi_log("[uwsgi-legion] attempting to become the Lord of the Legion %s\n", ul->legion);
struct uwsgi_string_list *usl = ul->lord_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("lord", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, lord hook returned: %d\n", ret);
if (uwsgi.legion_death_on_lord_error) {
ul->dead = 1;
uwsgi_legion_announce(ul);
ul->suspended_til = uwsgi_now() + uwsgi.legion_death_on_lord_error;
uwsgi_log("[uwsgi-legion] suspending myself from Legion \"%s\" for %d seconds\n", ul->legion, uwsgi.legion_death_on_lord_error);
goto next;
}
}
usl = usl->next;
}
@@ -294,6 +366,7 @@ static void legions_check_nodes_step2() {
else {
ul->lord_scroll_len = 0;
}
uwsgi_log("[uwsgi-legion] i am now the Lord of the Legion %s\n", ul->legion);
ul->i_am_the_lord = uwsgi_now();
// trick: reduce the time needed by the old lord to unlord itself
uwsgi_legion_announce(ul);
@@ -303,9 +376,9 @@ static void legions_check_nodes_step2() {
if (ul->i_am_the_lord) {
uwsgi_log("[uwsgi-legion] a new Lord (valor: %llu uuid: %.*s) raised for Legion %s...\n", ul->lord_valor, 36, ul->lord_uuid, ul->legion);
if (ul->lord_scroll_len > 0) {
uwsgi_log("*********** The New Lord Scroll ***********\n\n");
uwsgi_log("*********** The New Lord Scroll ***********\n");
uwsgi_log("%.*s\n", ul->lord_scroll_len, ul->lord_scroll);
uwsgi_log("\n*********** End of the New Lord Scroll ***********\n\n");
uwsgi_log("*********** End of the New Lord Scroll ***********\n");
}
// no more lord, trigger unlord hooks
struct uwsgi_string_list *usl = ul->unlord_hooks;
@@ -322,9 +395,23 @@ static void legions_check_nodes_step2() {
}
else if (votes > 0 && votes < ul->quorum && (uwsgi_now() - ul->last_warning >= 60)) {
uwsgi_log("[uwsgi-legion] no quorum: only %d vote(s) for Legion %s, %d needed to elect a Lord\n", votes, ul->legion, ul->quorum);
// no more quorum, leave the Lord state
if (ul->i_am_the_lord) {
uwsgi_log("[uwsgi-legion] i cannot be The Lord of The Legion %s without a quorum ...\n", ul->legion);
// no more lord, trigger unlord hooks
struct uwsgi_string_list *usl = ul->unlord_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("unlord", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, unlord hook returned: %d\n", ret);
}
usl = usl->next;
}
ul->i_am_the_lord = 0;
}
ul->last_warning = uwsgi_now();
}
next:
ul = ul->next;
}
}
@@ -341,6 +428,8 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
struct uwsgi_legion_node *nodes = ul->nodes_head;
while (nodes) {
// skip arbiters
if (nodes->valor == 0) goto next;
if (nodes->valor > best_valor) {
best_node = nodes;
best_valor = nodes->valor;
@@ -353,11 +442,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
memcpy(best_uuid, nodes->uuid, 36);
}
}
next:
nodes = nodes->next;
}
// first round ?
if (ul->lord_valor == 0) {
// first round ? (skip first round if arbiter)
if (ul->valor > 0 && ul->lord_valor == 0) {
ul->changed = 1;
}
else if (best_valor != ul->lord_valor) {
@@ -417,8 +507,15 @@ static void *legion_loop(void *foobar) {
last_round = now;
// wait for event
int interesting_fd = -1;
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) return NULL;
int rlen = event_queue_wait(uwsgi.legion_queue, timeout, &interesting_fd);
if (rlen < 0 && errno != EINTR) {
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) return NULL;
uwsgi_nuclear_blast();
return NULL;
}
now = uwsgi_now();
if (timeout == 0 || rlen == 0 || (now - last_round) >= timeout) {
struct uwsgi_legion *legions = uwsgi.legions;
@@ -512,6 +609,8 @@ static void *legion_loop(void *foobar) {
// check if the node is already accounted
struct uwsgi_legion_node *node = uwsgi_legion_get_node(ul, legion_msg.valor, legion_msg.name, legion_msg.name_len, legion_msg.uuid);
if (!node) {
// if a lord hook election fails, a node can announce itself as dead for long time...
if (legion_msg.dead) continue;
// add the new node
uwsgi_wlock(ul->lock);
node = uwsgi_legion_add_node(ul, legion_msg.valor, legion_msg.name, legion_msg.name_len, legion_msg.uuid);
@@ -521,8 +620,27 @@ static void *legion_loop(void *foobar) {
node->scroll_len = legion_msg.scroll_len;
memcpy(node->scroll, legion_msg.scroll, node->scroll_len);
}
// we are still locked (and safe), let's rebuild the scrolls list
legion_rebuild_scrolls(ul);
uwsgi_rwunlock(ul->lock);
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
// trigger node_joined hooks
struct uwsgi_string_list *usl = ul->node_joined_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("node_joined", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, node_joined hook returned: %d\n", ret);
}
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();
@@ -550,7 +668,12 @@ int uwsgi_legion_action_call(char *phase, struct uwsgi_legion *ul, struct uwsgi_
return -1;
}
uwsgi_log("[uwsgi-legion] (phase: %s legion: %s) calling %s\n", phase, ul->legion, usl->value);
if (ula->log_msg) {
uwsgi_log("[uwsgi-legion] (phase: %s legion: %s) %s\n", phase, ul->legion, ula->log_msg);
}
else {
uwsgi_log("[uwsgi-legion] (phase: %s legion: %s) calling %s\n", phase, ul->legion, usl->value);
}
return ula->func(ul, usl->value + usl->custom);
}
@@ -569,6 +692,18 @@ static int legion_action_log(struct uwsgi_legion *ul, char *arg) {
return 0;
}
static int legion_action_alarm(struct uwsgi_legion *ul, char *arg) {
char *space = strchr(arg,' ');
if (!space) {
uwsgi_log("invalid alarm action syntax, must be: <alarm> <msg>\n");
return -1;
}
*space = 0;
uwsgi_alarm_trigger(arg, space+1, strlen(space+1));
*space = ' ';
return 0;
}
void uwsgi_start_legions() {
pthread_t legion_loop_t;
@@ -577,8 +712,10 @@ void uwsgi_start_legions() {
// register embedded actions
uwsgi_legion_action_register("cmd", legion_action_cmd);
uwsgi_legion_action_register("exec", legion_action_cmd);
uwsgi_legion_action_register("signal", legion_action_signal);
uwsgi_legion_action_register("log", legion_action_log);
uwsgi_legion_action_register("alarm", legion_action_alarm);
uwsgi.legion_queue = event_queue_init();
struct uwsgi_legion *legion = uwsgi.legions;
@@ -638,13 +775,19 @@ void uwsgi_legion_add(struct uwsgi_legion *ul) {
}
int uwsgi_legion_announce(struct uwsgi_legion *ul) {
time_t now = uwsgi_now();
if (now <= ul->suspended_til) return 0;
ul->suspended_til = 0;
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
unsigned char *encrypted = NULL;
if (uwsgi_buffer_append_keyval(ub, "legion", 6, ul->legion, ul->legion_len))
goto err;
if (uwsgi_buffer_append_keynum(ub, "valor", 5, ul->valor))
goto err;
if (uwsgi_buffer_append_keynum(ub, "unix", 4, uwsgi_now()))
if (uwsgi_buffer_append_keynum(ub, "unix", 4, now))
goto err;
if (uwsgi_buffer_append_keynum(ub, "lord", 4, ul->i_am_the_lord ? ul->i_am_the_lord : 0))
goto err;
@@ -665,10 +808,13 @@ 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
unsigned char *encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
if (ul->dead) {
if (uwsgi_buffer_append_keyval(ub, "dead", 4, "1", 1))
goto err;
}
encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
if (EVP_EncryptInit_ex(ul->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
uwsgi_error("[uwsgi-legion] EVP_EncryptInit_ex()");
goto err;
@@ -707,9 +853,26 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
return 0;
err:
uwsgi_buffer_destroy(ub);
free(encrypted);
return -1;
}
void uwsgi_opt_legion_mcast(char *opt, char *value, void *foobar) {
uwsgi_opt_legion(opt, value, foobar);
char *legion = uwsgi_str(value);
char *space = strchr(legion, ' ');
// over engineering
if (!space) exit(1);
*space = 0;
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
if (!ul) {
uwsgi_log("unknown legion: %s\n", legion);
exit(1);
}
uwsgi_legion_register_node(ul, uwsgi_str(ul->addr));
free(legion);
}
void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
char *legion = uwsgi_str(value);
@@ -727,15 +890,20 @@ void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
exit(1);
}
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, space + 1);
char *port = strchr(usl->value, ':');
uwsgi_legion_register_node(ul, space + 1);
}
void uwsgi_legion_register_node(struct uwsgi_legion *ul, char *addr) {
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, addr);
char *port = strchr(addr, ':');
if (!port) {
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", usl->value);
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", addr);
exit(1);
}
// no need to zero the memory, socket_to_in_addr will do that
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
usl->custom = socket_to_in_addr(addr, port, 0, sin);
usl->custom_ptr = sin;
}
@@ -787,51 +955,76 @@ void uwsgi_opt_legion_scroll(char *opt, char *value, void *foobar) {
void uwsgi_opt_legion_hook(char *opt, char *value, void *foobar) {
char *event = strchr(opt, '-');
if (!event) {
uwsgi_log("[uwsgi-legion] invalid option name (%s), this should not happen (possible bug)\n", opt);
exit(1);
}
char *legion = uwsgi_str(value);
char *space = strchr(legion, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be <legion> <action>\n", opt);
uwsgi_log("[uwsgi-legion] invalid %s syntax, must be <legion> <action>\n", opt);
exit(1);
}
*space = 0;
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
if (!ul) {
uwsgi_log("unknown legion: %s\n", legion);
uwsgi_log("[uwsgi-legion] unknown legion: %s\n", legion);
exit(1);
}
uwsgi_legion_register_hook(ul, event + 1, space + 1);
}
void uwsgi_legion_register_hook(struct uwsgi_legion *ul, char *event, char *action) {
struct uwsgi_string_list *usl = NULL;
if (!strcmp(opt, "legion-lord")) {
usl = uwsgi_string_new_list(&ul->lord_hooks, space + 1);
if (!strcmp(event, "lord")) {
usl = uwsgi_string_new_list(&ul->lord_hooks, action);
}
else if (!strcmp(opt, "legion-unlord")) {
usl = uwsgi_string_new_list(&ul->unlord_hooks, space + 1);
else if (!strcmp(event, "unlord")) {
usl = uwsgi_string_new_list(&ul->unlord_hooks, action);
}
else if (!strcmp(opt, "legion-setup")) {
usl = uwsgi_string_new_list(&ul->setup_hooks, space + 1);
else if (!strcmp(event, "setup")) {
usl = uwsgi_string_new_list(&ul->setup_hooks, action);
}
else if (!strcmp(opt, "legion-death")) {
usl = uwsgi_string_new_list(&ul->death_hooks, space + 1);
else if (!strcmp(event, "death")) {
usl = uwsgi_string_new_list(&ul->death_hooks, action);
}
else if (!strcmp(event, "join")) {
usl = uwsgi_string_new_list(&ul->join_hooks, action);
}
else if (!strcmp(event, "node-joined")) {
usl = uwsgi_string_new_list(&ul->node_joined_hooks, action);
}
else if (!strcmp(event, "node-left")) {
usl = uwsgi_string_new_list(&ul->node_left_hooks, action);
}
else {
uwsgi_log("[uwsgi-legion] invalid event: %s\n", event);
exit(1);
}
if (!usl)
return;
char *port = strchr(usl->value, ':');
if (!port) {
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", opt, usl->value);
char *hook = strchr(action, ':');
if (!hook) {
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", event, action);
exit(1);
}
// pointer to action plugin
usl->custom_ptr = uwsgi_concat2n(usl->value, port - usl->value, "", 0);
usl->custom_ptr = uwsgi_concat2n(action, hook - action, "", 0);;
// add that to check the plugin value
usl->custom = port - usl->value + 1;
}
usl->custom = hook - action + 1;
}
void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
@@ -869,6 +1062,10 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
*colon = 0;
char *secret = colon + 1;
uwsgi_legion_register(legion, addr, valor, algo_secret, secret);
}
struct uwsgi_legion *uwsgi_legion_register(char *legion, char *addr, char *valor, char *algo, char *secret) {
char *iv = strchr(secret, ' ');
if (iv) {
*iv = 0;
@@ -882,9 +1079,9 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
EVP_CIPHER_CTX *ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(ctx);
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo_secret);
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo);
if (!cipher) {
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo_secret);
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo);
exit(1);
}
@@ -937,10 +1134,18 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
uwsgi.legion_scroll_max_size = 4096;
}
if (!uwsgi.legion_scroll_list_max_size) {
uwsgi.legion_scroll_list_max_size = 32768;
}
ul->lord_scroll_size = uwsgi.legion_scroll_max_size;
ul->lord_scroll = uwsgi_calloc_shared(ul->lord_scroll_size);
ul->scrolls_max_size = uwsgi.legion_scroll_list_max_size;
ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size);
uwsgi_legion_add(ul);
return ul;
}
struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
@@ -954,10 +1159,11 @@ struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
return NULL;
}
void uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *, char *)) {
if (uwsgi_legion_action_get(name)) {
struct uwsgi_legion_action *uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *, char *)) {
struct uwsgi_legion_action *found_ula = uwsgi_legion_action_get(name);
if (found_ula) {
uwsgi_log("[uwsgi-legion] action \"%s\" is already registered !!!\n", name);
return;
return found_ula;
}
struct uwsgi_legion_action *old_ula = NULL, *ula = uwsgi.legion_actions;
@@ -976,8 +1182,18 @@ void uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *
else {
uwsgi.legion_actions = ula;
}
return ula;
}
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;
@@ -996,6 +1212,7 @@ next:
legion = legion->next;
}
uwsgi_legion_announce_death();
}
int uwsgi_legion_i_am_the_lord(char *name) {
@@ -1020,3 +1237,15 @@ char *uwsgi_legion_lord_scroll(char *name, uint16_t *rlen) {
uwsgi_rwunlock(legion->lock);
return buf;
}
char *uwsgi_legion_scrolls(char *name, uint64_t *rlen) {
char *buf = NULL;
struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name);
if (!legion) return NULL;
uwsgi_rlock(legion->lock);
buf = uwsgi_malloc(legion->scrolls_len);
memcpy(buf, legion->scrolls, legion->scrolls_len);
*rlen = legion->scrolls_len;
uwsgi_rwunlock(legion->lock);
return buf;
}
+137 -14
View File
@@ -401,6 +401,60 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
}
#elif defined(UWSGI_LOCK_USE_WINDOWS_MUTEX)
#define UWSGI_LOCK_ENGINE_NAME "windows mutexes"
#define UWSGI_LOCK_SIZE sizeof(HANDLE)
#define UWSGI_RWLOCK_SIZE sizeof(HANDLE)
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
struct _SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(struct _SECURITY_ATTRIBUTES));
sa.bInheritHandle = 1;
uli->lock_ptr = CreateMutex(&sa, FALSE, NULL);
return uli;
}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
WaitForSingleObject(uli->lock_ptr, INFINITE);
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
ReleaseMutex(uli->lock_ptr);
uli->pid = 0;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (WaitForSingleObject(uli->lock_ptr, 0) == WAIT_TIMEOUT) {
return 0;
}
return uli->pid;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
return uwsgi_lock_fast_init(id);
}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
return uwsgi_lock_fast_check(uli);
}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
}
#else
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
@@ -420,8 +474,6 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
#define UWSGI_IPCSEM_ATEXIT 1
#endif
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
@@ -441,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++;
@@ -452,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
@@ -460,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);
}
@@ -480,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);
}
}
@@ -497,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);
}
}
@@ -522,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)
@@ -542,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;
}
@@ -558,6 +639,33 @@ 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);
sleep(1);
}
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() {
@@ -607,7 +715,9 @@ ready:
// application generic lock
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
for (i = 0; i < uwsgi.locks + 1; i++) {
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
char *num = uwsgi_num2str(i);
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", num));
free(num);
}
// event queue lock (mitigate same event on multiple queues)
@@ -625,9 +735,6 @@ ready:
// timer table lock
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
// probe table lock
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
// rb_timer table lock
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
@@ -638,6 +745,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");
@@ -713,10 +828,18 @@ nextlock:
}
void uwsgi_user_lock(int lock_num) {
int uwsgi_user_lock(int lock_num) {
if (lock_num < 0 || lock_num > uwsgi.locks) {
return -1;
}
uwsgi_lock(uwsgi.user_lock[lock_num]);
return 0;
}
void uwsgi_user_unlock(int lock_num) {
int uwsgi_user_unlock(int lock_num) {
if (lock_num < 0 || lock_num > uwsgi.locks) {
return -1;
}
uwsgi_unlock(uwsgi.user_lock[lock_num]);
return 0;
}
+772 -295
View File
File diff suppressed because it is too large Load Diff
+352 -220
View File
@@ -2,15 +2,30 @@
extern struct uwsgi_server uwsgi;
void uwsgi_restore_auto_snapshot(int signum) {
void uwsgi_update_load_counters() {
if (uwsgi.workers[1].snapshot > 0) {
uwsgi.restore_snapshot = 1;
}
else {
uwsgi_log("[WARNING] no snapshot available\n");
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_block_signal(int signum) {
@@ -32,24 +47,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 +73,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,74 +82,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");
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid == 0)
continue;
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
uwsgi.workers[i].pid = 0;
uwsgi.workers[i].snapshot = 0;
}
else {
uwsgi.workers[i].pid = uwsgi.workers[i].snapshot;
uwsgi.workers[i].snapshot = 0;
kill(uwsgi.workers[i].pid, SIGURG);
uwsgi_log("Restored uWSGI worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
}
}
uwsgi.restore_snapshot = 0;
}
void suspend_resume_them_all(int signum) {
int i;
@@ -209,53 +168,34 @@ void expire_rb_timeouts(struct uwsgi_rbtree *tree) {
}
}
int uwsgi_get_tcp_info(int fd) {
static void get_tcp_info(struct uwsgi_socket *uwsgi_sock) {
#if defined(__linux__) || defined(__FreeBSD__)
int fd = uwsgi_sock->fd;
struct tcp_info ti;
socklen_t tis = sizeof(struct tcp_info);
if (!getsockopt(fd, IPPROTO_TCP, TCP_INFO, &uwsgi.shared->ti, &tis)) {
if (!getsockopt(fd, IPPROTO_TCP, TCP_INFO, &ti, &tis)) {
// checks for older kernels
#if defined(__linux__)
if (!uwsgi.shared->ti.tcpi_sacked) {
if (!ti.tcpi_sacked) {
#elif defined(__FreeBSD__)
if (!uwsgi.shared->ti.__tcpi_sacked) {
if (!ti.__tcpi_sacked) {
#endif
return 0;
}
return;
}
#if defined(__linux__)
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.tcpi_unacked;
uwsgi.shared->max_load = (uint64_t) uwsgi.shared->ti.tcpi_sacked;
uwsgi_sock->queue = (uint64_t) ti.tcpi_unacked;
uwsgi_sock->max_queue = (uint64_t) ti.tcpi_sacked;
#elif defined(__FreeBSD__)
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.__tcpi_unacked;
uwsgi.shared->max_load = (uint64_t) uwsgi.shared->ti.__tcpi_sacked;
uwsgi_sock->queue = (uint64_t) ti.__tcpi_unacked;
uwsgi_sock->max_queue = (uint64_t) ti.__tcpi_sacked;
#endif
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS] = uwsgi.shared->load;
if (uwsgi.vassal_sos_backlog > 0 && uwsgi.has_emperor) {
if (uwsgi.shared->load >= (uint64_t) uwsgi.vassal_sos_backlog) {
// ask emperor for help
char byte = 30;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("write()");
}
else {
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.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
return uwsgi.shared->load;
}
#endif
return 0;
#endif
}
@@ -268,25 +208,72 @@ int uwsgi_get_tcp_info(int fd) {
#ifdef SIOBKLGQ
int get_linux_unbit_SIOBKLGQ(int fd) {
static void get_linux_unbit_SIOBKLGQ(struct uwsgi_socket *uwsgi_sock) {
int fd = uwsgi_sock->fd;
int queue = 0;
if (ioctl(fd, SIOBKLGQ, &queue) >= 0) {
uwsgi.shared->load = queue;
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS] = queue;
if (queue >= uwsgi.listen_queue) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%d/%d) ***\n", fd, queue, uwsgi.listen_queue);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
return queue;
uwsgi_sock->queue = (uint64_t) queue;
uwsgi_sock->max_queue = (uint64_t) uwsgi.listen_queue;
}
return 0;
}
#endif
#endif
static void master_check_listen_queue() {
uint64_t backlog = 0;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (uwsgi_sock->family == AF_INET) {
get_tcp_info(uwsgi_sock);
}
#ifdef __linux__
#ifdef SIOBKLGQ
else if (uwsgi_sock->family == AF_UNIX) {
get_linux_unbit_SIOBKLGQ(uwsgi_sock);
}
#endif
#endif
if (uwsgi_sock->queue > backlog) {
backlog = uwsgi_sock->queue;
}
if (uwsgi_sock->queue > 0 && uwsgi_sock->queue >= uwsgi_sock->max_queue) {
uwsgi_log_verbose("*** uWSGI listen queue of socket \"%s\" (fd: %d) full !!! (%llu/%llu) ***\n", uwsgi_sock->name, uwsgi_sock->fd, (unsigned long long) uwsgi_sock->queue, (unsigned long long) uwsgi_sock->max_queue);
}
if (uwsgi.alarm_backlog) {
char buf[1024];
int ret = snprintf(buf, 1024, "listen queue of socket \"%s\" (fd: %d) full !!! (%llu/%llu)", uwsgi_sock->name, uwsgi_sock->fd, (unsigned long long) uwsgi_sock->queue, (unsigned long long) uwsgi_sock->max_queue);
if (ret > 0 && ret < 1024) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.alarm_backlog) {
uwsgi_alarm_trigger(usl->value, buf, ret);
}
}
}
uwsgi_sock = uwsgi_sock->next;
}
// TODO load should be something more advanced based on different values
uwsgi.shared->load = backlog;
uwsgi.shared->backlog = backlog;
if (uwsgi.vassal_sos_backlog > 0 && uwsgi.has_emperor) {
if (uwsgi.shared->backlog >= (uint64_t) uwsgi.vassal_sos_backlog) {
// ask emperor for help
char byte = 30;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("write()");
}
else {
uwsgi_log_verbose("asking Emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->backlog);
}
}
}
}
int master_loop(char **argv, char **environ) {
@@ -306,7 +293,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);
}
@@ -332,9 +318,6 @@ int master_loop(char **argv, char **environ) {
}
uwsgi_unix_signal(SIGINT, kill_them_all);
uwsgi_unix_signal(SIGUSR1, stats);
if (uwsgi.auto_snapshot) {
uwsgi_unix_signal(SIGURG, uwsgi_restore_auto_snapshot);
}
atexit(uwsgi_master_cleanup_hooks);
@@ -346,6 +329,17 @@ 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.notify_socket) {
uwsgi.notify_socket_fd = bind_to_unix_dgram(uwsgi.notify_socket);
uwsgi_log("notification socket enabled on %s (fd: %d)\n", uwsgi.notify_socket, uwsgi.notify_socket_fd);
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.notify_socket_fd);
}
if (uwsgi.spoolers) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
}
@@ -374,6 +368,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,9 +378,32 @@ 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);
}
}
#ifdef __linux__
if (uwsgi.setns_socket) {
uwsgi.setns_socket_fd = bind_to_unix(uwsgi.setns_socket, uwsgi.listen_queue, 0, 0);
if (uwsgi.setns_socket_fd < 0) exit(1);
if (chmod(uwsgi.setns_socket, S_IRUSR|S_IWUSR)) {
uwsgi_error("[setns-socket] chmod()");
exit(1);
}
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.setns_socket_fd);
}
#endif
if (uwsgi.zerg_server) {
uwsgi.zerg_server_fd = bind_to_unix(uwsgi.zerg_server, uwsgi.listen_queue, 0, 0);
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.zerg_server_fd);
@@ -391,7 +411,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;
@@ -473,6 +493,73 @@ int master_loop(char **argv, char **environ) {
uwsgi_check_touches(uwsgi.touch_chain_reload);
uwsgi_check_touches(uwsgi.touch_workers_reload);
uwsgi_check_touches(uwsgi.touch_gracefully_stop);
// update exec touches
struct uwsgi_string_list *usl = uwsgi.touch_exec;
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_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);
// daemon touches
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->touch) {
uwsgi_check_touches(ud->touch);
}
ud = ud->next;
}
// hook touches
uwsgi_foreach(usl, uwsgi.hook_touch) {
char *space = strchr(usl->value, ' ');
if (space) {
*space = 0;
usl->len = strlen(usl->value);
uwsgi_string_new_list((struct uwsgi_string_list **)&usl->custom_ptr, space+1);
}
}
uwsgi_check_touches(uwsgi.hook_touch);
// fsmon
uwsgi_fsmon_setup();
uwsgi_foreach(usl, uwsgi.signal_timers) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid signal timer syntax, must be: <signal> <seconds>\n");
exit(1);
}
*space = 0;
uwsgi_add_timer(atoi(usl->value), atoi(space+1));
*space = ' ';
}
uwsgi_foreach(usl, uwsgi.rb_signal_timers) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid redblack signal timer syntax, must be: <signal> <seconds>\n");
exit(1);
}
*space = 0;
uwsgi_signal_add_rb_timer(atoi(usl->value), atoi(space+1), 0);
*space = ' ';
}
// setup cheaper algos (can be stacked)
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
@@ -495,6 +582,7 @@ int master_loop(char **argv, char **environ) {
}
// here really starts the master loop
uwsgi_hooks_run(uwsgi.hook_master_start, "master-start", 1);
for (;;) {
//uwsgi_log("uwsgi.ready_to_reload %d %d\n", uwsgi.ready_to_reload, uwsgi.numproc);
@@ -527,21 +615,6 @@ int master_loop(char **argv, char **environ) {
// check for daemons (smart and dumb)
uwsgi_daemons_smart_check();
if (uwsgi.respawn_snapshots) {
for (i = 1; i <= uwsgi.respawn_snapshots; i++) {
if (uwsgi_respawn_worker(i))
return 0;
}
uwsgi.respawn_snapshots = 0;
}
if (uwsgi.restore_snapshot) {
uwsgi_master_restore_snapshot();
continue;
}
// cheaper management
if (uwsgi.cheaper && !uwsgi.status.is_cheap && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
if (!uwsgi_calc_cheaper())
@@ -570,9 +643,11 @@ int master_loop(char **argv, char **environ) {
if (diedpid == 0) {
/* all processes ok, doing status scan after N seconds */
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!check_interval)
check_interval = uwsgi.master_interval;
if (!check_interval) {
check_interval = 1;
uwsgi.master_interval = 1;
}
// add unregistered file monitors
@@ -607,14 +682,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;
}
}
}
@@ -628,6 +703,9 @@ int master_loop(char **argv, char **environ) {
}
}
// update load counter
uwsgi_update_load_counters();
// check uwsgi-cron table
if (ushared->cron_cnt) {
@@ -638,22 +716,6 @@ int master_loop(char **argv, char **environ) {
uwsgi_manage_command_cron(uwsgi_now());
}
// check for probes
if (ushared->probes_cnt > 0) {
uwsgi_lock(uwsgi.probe_table_lock);
for (i = 0; i < ushared->probes_cnt; i++) {
if (interesting_fd == -1) {
// increment cycles
ushared->probes[i].cycles++;
}
if (ushared->probes[i].func(interesting_fd, &ushared->probes[i])) {
uwsgi_route_signal(ushared->probes[i].sig);
}
}
uwsgi_unlock(uwsgi.probe_table_lock);
}
// some event returned
if (rlen > 0) {
// if the following function returns -1, a new worker has just spawned
@@ -683,33 +745,26 @@ int master_loop(char **argv, char **environ) {
// check for idle
uwsgi_master_check_idle();
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!check_interval)
check_interval = uwsgi.master_interval;
if (!check_interval) {
check_interval = 1;
// get listen_queue status
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_INET) {
uwsgi_sock->queue = uwsgi_get_tcp_info(uwsgi_sock->fd);
}
#ifdef __linux__
#ifdef SIOBKLGQ
else if (uwsgi_sock->family == AF_UNIX) {
uwsgi_sock->queue = get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd);
}
#endif
#endif
uwsgi_sock = uwsgi_sock->next;
uwsgi.master_interval = 1;
}
// check if some worker has to die (harakiri, evil checks...)
uwsgi_master_check_workers_deadline();
uwsgi_master_check_gateways_deadline();
uwsgi_master_check_mules_deadline();
uwsgi_master_check_spoolers_deadline();
// check listen_queue status
master_check_listen_queue();
int someone_killed = 0;
// check if some worker has to die (harakiri, evil checks...)
if (uwsgi_master_check_workers_deadline()) someone_killed++;
if (uwsgi_master_check_gateways_deadline()) someone_killed++;
if (uwsgi_master_check_mules_deadline()) someone_killed++;
if (uwsgi_master_check_spoolers_deadline()) someone_killed++;
if (uwsgi_master_check_crons_deadline()) someone_killed++;
// this could trigger a complete exit...
uwsgi_master_check_mountpoints();
#ifdef __linux__
#ifdef MADV_MERGEABLE
@@ -720,7 +775,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);
}
@@ -744,28 +799,60 @@ 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) {
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);
}
// daemon touches
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid > 0 && ud->touch) {
touched = uwsgi_check_touches(ud->touch);
if (touched) {
uwsgi_log_verbose("*** %s has been touched... reloading daemon \"%s\" (pid: %d) !!! ***\n", touched, ud->command, (int) ud->pid);
if (kill(-ud->pid, ud->stop_signal)) {
uwsgi_error("[uwsgi-daemon/touch] kill()");
}
}
}
ud = ud->next;
}
// hook touches
touched = uwsgi_check_touches(uwsgi.hook_touch);
if (touched) {
uwsgi_hooks_run((struct uwsgi_string_list *) touched, "touch", 0);
}
}
// allows the KILL signal to be delivered;
if (someone_killed > 0) sleep(1);
continue;
}
@@ -780,11 +867,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_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;
}
@@ -798,8 +892,8 @@ int master_loop(char **argv, char **environ) {
*/
uwsgi.mywid = find_worker_id(diedpid);
if (uwsgi.mywid <= 0) {
int thewid = find_worker_id(diedpid);
if (thewid <= 0) {
// check spooler, mules, gateways and daemons
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
@@ -842,50 +936,57 @@ next:
// ok a worker died...
uwsgi.workers[uwsgi.mywid].pid = 0;
uwsgi.workers[thewid].pid = 0;
// only to be safe :P
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[thewid].harakiri = 0;
// 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) {
uwsgi_log("worker %d buried after %d seconds\n", uwsgi.mywid, (int) (uwsgi_now()-uwsgi.workers[uwsgi.mywid].cursed_at));
uwsgi.workers[uwsgi.mywid].cursed_at = 0;
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;
}
// if we are stopping workers, just end here
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", thewid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) {
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", thewid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
// noop
}
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
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", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
}
else {
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", thewid, (int) diedpid);
}
}
else if (uwsgi.workers[uwsgi.mywid].cursed_at > 0) {
uwsgi_log("worker %d killed successfully (pid: %d)\n", uwsgi.mywid, (int) diedpid);
else if (uwsgi.workers[thewid].cursed_at > 0) {
uwsgi_log("worker %d killed successfully (pid: %d)\n", thewid, (int) diedpid);
}
// manage_next_request is zero, but killed by signal...
else if (WIFSIGNALED(waitpid_status)) {
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
}
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
if (uwsgi.workers[thewid].cheaped == 1) {
uwsgi_log("uWSGI worker %d cheaped.\n", thewid);
continue;
}
@@ -909,12 +1010,12 @@ next:
uwsgi.respawn_delta = last_respawn.tv_sec;
// are we chain reloading it ?
if (uwsgi.status.chain_reloading == uwsgi.mywid) {
if (uwsgi.status.chain_reloading == thewid) {
uwsgi.status.chain_reloading++;
}
// respawn the worker (if needed)
if (uwsgi_respawn_worker(uwsgi.mywid))
if (uwsgi_respawn_worker(thewid))
return 0;
// end of the loop
@@ -922,3 +1023,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);
}
}
}
+93 -10
View File
@@ -35,13 +35,21 @@ 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++) {
// do not curse a worker until the old one is ready
if (uwsgi.workers[i].accepting == 0) break;
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
uwsgi_curse(i, SIGHUP);
break;
@@ -112,6 +120,11 @@ void uwsgi_master_check_idle() {
if (errno != ECHILD)
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
}
else {
uwsgi.workers[i].pid = 0;
uwsgi.workers[i].rss_size = 0;
uwsgi.workers[i].vsz_size = 0;
}
}
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
@@ -120,19 +133,22 @@ void uwsgi_master_check_idle() {
}
void uwsgi_master_check_workers_deadline() {
int uwsgi_master_check_workers_deadline() {
int i;
int ret = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
/* first check for harakiri */
if (uwsgi.workers[i].harakiri > 0) {
if (uwsgi.workers[i].harakiri < (time_t) uwsgi.current_time) {
trigger_harakiri(i);
ret = 1;
}
}
/* then user-defined harakiri */
if (uwsgi.workers[i].user_harakiri > 0) {
if (uwsgi.workers[i].user_harakiri < (time_t) uwsgi.current_time) {
trigger_harakiri(i);
ret = 1;
}
}
// then for evil memory checkers
@@ -141,6 +157,7 @@ void uwsgi_master_check_workers_deadline() {
uwsgi_log("*** EVIL RELOAD ON WORKER %d ADDRESS SPACE: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].vsz_size, uwsgi.workers[i].pid);
kill(uwsgi.workers[i].pid, SIGKILL);
uwsgi.workers[i].vsz_size = 0;
ret = 1;
}
}
if (uwsgi.evil_reload_on_rss) {
@@ -148,15 +165,17 @@ void uwsgi_master_check_workers_deadline() {
uwsgi_log("*** EVIL RELOAD ON WORKER %d RSS: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].rss_size, uwsgi.workers[i].pid);
kill(uwsgi.workers[i].pid, SIGKILL);
uwsgi.workers[i].rss_size = 0;
ret = 1;
}
}
// check if worker was running longer than allowed lifetime
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0) {
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.max_worker_lifetime > 0) {
uint64_t lifetime = uwsgi_now() - uwsgi.workers[i].last_spawn;
if (lifetime > uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] && uwsgi.workers[i].manage_next_request == 1) {
if (lifetime > uwsgi.max_worker_lifetime && uwsgi.workers[i].manage_next_request == 1) {
uwsgi_log("worker %d lifetime reached, it was running for %llu second(s)\n", i, (unsigned long long) lifetime);
uwsgi.workers[i].manage_next_request = 0;
kill(uwsgi.workers[i].pid, SIGWINCH);
ret = 1;
}
}
@@ -165,28 +184,32 @@ void uwsgi_master_check_workers_deadline() {
}
return ret;
}
void uwsgi_master_check_gateways_deadline() {
int uwsgi_master_check_gateways_deadline() {
int i;
int ret = 0;
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways_harakiri[i] > 0) {
if (ushared->gateways_harakiri[i] < (time_t) uwsgi.current_time) {
if (ushared->gateways[i].pid > 0) {
uwsgi_log("*** HARAKIRI ON GATEWAY %s %d (pid: %d) ***\n", ushared->gateways[i].name, ushared->gateways[i].num, ushared->gateways[i].pid);
kill(ushared->gateways[i].pid, SIGKILL);
ret = 1;
}
ushared->gateways_harakiri[i] = 0;
}
}
}
return ret;
}
void uwsgi_master_check_mules_deadline() {
int uwsgi_master_check_mules_deadline() {
int i;
int ret = 0;
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].harakiri > 0) {
@@ -194,21 +217,41 @@ void uwsgi_master_check_mules_deadline() {
uwsgi_log("*** HARAKIRI ON MULE %d HANDLING SIGNAL %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].signum, uwsgi.mules[i].pid);
kill(uwsgi.mules[i].pid, SIGKILL);
uwsgi.mules[i].harakiri = 0;
ret = 1;
}
}
// 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;
ret = 1;
}
}
}
return ret;
}
void uwsgi_master_check_spoolers_deadline() {
int uwsgi_master_check_spoolers_deadline() {
int ret = 0;
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
if (uspool->harakiri > 0 && uspool->harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
kill(uspool->pid, SIGKILL);
uspool->harakiri = 0;
ret = 1;
}
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;
ret = 1;
}
uspool = uspool->next;
}
return ret;
}
@@ -276,3 +319,43 @@ int uwsgi_worker_is_busy(int wid) {
}
return 0;
}
int uwsgi_master_check_cron_death(int diedpid) {
struct uwsgi_cron *uc = uwsgi.crons;
while (uc) {
if (uc->pid == (pid_t) diedpid) {
uwsgi_log("[uwsgi-cron] command \"%s\" running with pid %d exited after %d second(s)\n", uc->command, uc->pid, uwsgi_now() - uc->started_at);
uc->pid = -1;
uc->started_at = 0;
return -1;
}
uc = uc->next;
}
return 0;
}
int uwsgi_master_check_crons_deadline() {
int ret = 0;
struct uwsgi_cron *uc = uwsgi.crons;
while (uc) {
if (uc->pid >= 0 && uc->harakiri > 0 && uc->harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON CRON \"%s\" (pid: %d) ***\n", uc->command, uc->pid);
kill(-uc->pid, SIGKILL);
ret = 1;
}
uc = uc->next;
}
return ret;
}
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);
}
}
}
+93
View File
@@ -18,6 +18,14 @@ 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);
}
if (uwsgi.notify_socket_fd > -1 && interesting_fd == uwsgi.notify_socket_fd) {
return uwsgi_notify_socket_manage(interesting_fd);
}
// stats server ?
if (uwsgi.stats && uwsgi.stats_fd > -1) {
if (interesting_fd == uwsgi.stats_fd) {
@@ -36,12 +44,97 @@ 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;
}
}
#ifdef __linux__
if (uwsgi.setns_socket && uwsgi.setns_socket_fd > -1 && interesting_fd == uwsgi.setns_socket_fd) {
uwsgi_master_manage_setns(uwsgi.setns_socket_fd);
}
#endif
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);
}
if (usl->custom2 > 8) free(tmp);
return 0;
}
usl = usl->next;
}
}
// wakeup from cheap mode ?
if (uwsgi.status.is_cheap) {
+557 -211
View File
@@ -101,7 +101,7 @@ int uwsgi_calc_cheaper(void) {
int i;
static time_t last_check = 0;
int check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
int check_interval = uwsgi.master_interval;
if (!last_check)
last_check = uwsgi_now();
@@ -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++) {
@@ -144,6 +186,8 @@ int uwsgi_calc_cheaper(void) {
uwsgi_log("worker %d should die...\n", oldest_worker);
#endif
uwsgi.workers[oldest_worker].cheaped = 1;
uwsgi.workers[oldest_worker].rss_size = 0;
uwsgi.workers[oldest_worker].vsz_size = 0;
uwsgi.workers[oldest_worker].manage_next_request = 0;
uwsgi_curse(oldest_worker, SIGWINCH);
}
@@ -152,6 +196,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 +236,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 +260,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,16 +328,16 @@ healthy:
*/
int uwsgi_cheaper_algo_backlog(void) {
int uwsgi_cheaper_algo_backlog(int can_spawn) {
int i;
#ifdef __linux__
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
int backlog = uwsgi.shared->backlog;
#else
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 +375,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();
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
}
// call atexit user exec
uwsgi_exec_atexit();
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()");
@@ -351,6 +407,10 @@ void uwsgi_reload(char **argv) {
/* check fd table (a module can obviosly open some fd on initialization...) */
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
for (i = 3; i < (int) uwsgi.max_fd; i++) {
if (uwsgi.close_on_exec2) fcntl(i, F_SETFD, 0);
if (uwsgi_fd_is_safe(i)) continue;
int found = 0;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
@@ -385,6 +445,12 @@ void uwsgi_reload(char **argv) {
}
}
if (uwsgi.alarm_thread) {
if (i == uwsgi.alarm_thread->queue) continue;
if (i == uwsgi.alarm_thread->pipe[0]) continue;
if (i == uwsgi.alarm_thread->pipe[1]) continue;
}
if (uwsgi.log_master) {
if (uwsgi.original_log_fd > -1) {
if (i == uwsgi.original_log_fd) {
@@ -413,9 +479,13 @@ void uwsgi_reload(char **argv) {
#endif
}
#ifdef UWSGI_AS_SHARED_LIBRARY
return;
#else
#ifndef UWSGI_IPCSEM_ATEXIT
// free ipc semaphores if in use
if (uwsgi.lock_engine && !strcmp(uwsgi.lock_engine, "ipcsem")) {
uwsgi_ipcsem_clear();
}
#endif
uwsgi_log("running %s\n", uwsgi.binary_path);
uwsgi_flush_logs();
argv[0] = uwsgi.binary_path;
@@ -436,7 +506,6 @@ void uwsgi_reload(char **argv) {
uwsgi_error("execvp()");
// never here
exit(1);
#endif
}
@@ -517,6 +586,22 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
}
}
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
if (uwsgi.notify_socket_fd > -1) close(uwsgi.notify_socket_fd);
#ifdef __linux__
for(i=0;i<uwsgi.setns_fds_count;i++) {
close(uwsgi.setns_fds[i]);
}
#endif
// fd alarms
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
while(uafd) {
close(uafd->fd);
uafd = uafd->next;
}
}
@@ -525,6 +610,8 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
int uwsgi_respawn_worker(int wid) {
int respawns = uwsgi.workers[wid].respawn_count;
// the workers is not accepting (obviously)
uwsgi.workers[wid].accepting = 0;
// we count the respawns before errors...
uwsgi.workers[wid].respawn_count++;
// ... same for update time
@@ -634,178 +721,6 @@ int uwsgi_respawn_worker(int wid) {
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = ucron->minute;
uc_hour = ucron->hour;
uc_day = ucron->day;
uc_month = ucron->month;
uc_week = ucron->week;
// negative values as interval -1 = * , -5 = */5
if (ucron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (ucron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (ucron->month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (ucron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (ucron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (ucron->day >= 0 && ucron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, signal it ?
if (now - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = now;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
uwsgi_error("localtime()");
return;
}
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
uc_minute = current_cron->minute;
uc_hour = current_cron->hour;
uc_day = current_cron->day;
uc_month = current_cron->month;
uc_week = current_cron->week;
// negative values as interval -1 = * , -5 = */5
if (current_cron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (current_cron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (current_cron->month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(current_cron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (current_cron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (current_cron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (current_cron->day >= 0 && current_cron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, run command ?
if (now - current_cron->last_job > 60) {
//call command
if (current_cron->command) {
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
}
}
current_cron->last_job = now;
}
}
current_cron = current_cron->next;
}
}
struct uwsgi_stats *uwsgi_master_generate_stats() {
int i;
@@ -816,9 +731,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
#ifdef __linux__
if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]))
if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->backlog))
goto end;
if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]))
if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->backlog_errors))
goto end;
#endif
@@ -856,11 +771,20 @@ 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;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) ud->pid))
}
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 - 1)))
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
@@ -944,7 +868,10 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keylong_comma(us, "miss", (unsigned long long) uc->miss))
goto end;
if (uwsgi_stats_keylong(us, "full", (unsigned long long) uc->full))
if (uwsgi_stats_keylong_comma(us, "full", (unsigned long long) uc->full))
goto end;
if (uwsgi_stats_keylong(us, "last_modified_at", (unsigned long long) uc->last_modified_at))
goto end;
if (uwsgi_stats_object_close(us))
@@ -957,6 +884,73 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
uc = uc->next;
}
if (uwsgi_stats_list_close(us))
goto end;
if (uwsgi_stats_comma(us))
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_keyval_comma(us, "oid", um->oid ? um->oid : "")) {
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;
}
@@ -981,6 +975,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keylong_comma(us, "queue", (unsigned long long) uwsgi_sock->queue))
goto end;
if (uwsgi_stats_keylong_comma(us, "max_queue", (unsigned long long) uwsgi_sock->max_queue))
goto end;
if (uwsgi_stats_keylong_comma(us, "shared", (unsigned long long) uwsgi_sock->shared))
goto end;
@@ -1016,6 +1013,8 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
goto end;
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) uwsgi.workers[i + 1].accepting))
goto end;
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
@@ -1102,7 +1101,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keylong_comma(us, "exceptions", ua->exceptions))
goto end;
if (ua->chdir) {
if (*ua->chdir) {
if (uwsgi_stats_keyval(us, "chdir", ua->chdir))
goto end;
}
@@ -1155,6 +1154,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keylong_comma(us, "write_errors", (unsigned long long) uc->write_errors))
goto end;
if (uwsgi_stats_keylong_comma(us, "read_errors", (unsigned long long) uc->read_errors))
goto end;
if (uwsgi_stats_keylong_comma(us, "in_request", (unsigned long long) uc->in_request))
goto end;
@@ -1233,6 +1235,68 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
}
struct uwsgi_cron *ucron = uwsgi.crons;
if (ucron) {
if (uwsgi_stats_comma(us))
goto end;
if (uwsgi_stats_key(us, "crons"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
while (ucron) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyslong_comma(us, "minute", (long long) ucron->minute))
goto end;
if (uwsgi_stats_keyslong_comma(us, "hour", (long long) ucron->hour))
goto end;
if (uwsgi_stats_keyslong_comma(us, "day", (long long) ucron->day))
goto end;
if (uwsgi_stats_keyslong_comma(us, "month", (long long) ucron->month))
goto end;
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
goto end;
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;
#ifdef UWSGI_SSL
if (uwsgi_stats_keyval_comma(us, "legion", ucron->legion ? ucron->legion : ""))
goto end;
#endif
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) ucron->pid))
goto end;
if (uwsgi_stats_keylong(us, "started_at", (unsigned long long) ucron->started_at))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
ucron = ucron->next;
if (ucron) {
if (uwsgi_stats_comma(us))
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end;
}
#ifdef UWSGI_SSL
struct uwsgi_legion *legion = NULL;
if (uwsgi.legions) {
@@ -1379,7 +1443,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;
@@ -1410,7 +1474,7 @@ void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
void trigger_harakiri(int i) {
int j;
uwsgi_log("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri + 1);
uwsgi_log_verbose("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri + 1);
if (uwsgi.harakiri_verbose) {
#ifdef __linux__
int proc_file;
@@ -1458,15 +1522,12 @@ void trigger_harakiri(int i) {
}
}
kill(uwsgi.workers[i].pid, SIGUSR2);
// allow SIGUSR2 to be delivered
sleep(1);
uwsgi_dump_worker(i, "HARAKIRI");
kill(uwsgi.workers[i].pid, SIGKILL);
if (!uwsgi.workers[i].pending_harakiri)
uwsgi.workers[i].harakiri_count++;
uwsgi.workers[i].pending_harakiri++;
}
// to avoid races
}
@@ -1486,3 +1547,288 @@ void uwsgi_master_fix_request_counters() {
uwsgi.workers[0].requests = total_counter;
}
int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int hour, int day, int month, int week) {
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = minute;
uc_hour = hour;
uc_day = day;
uc_month = month;
uc_week = week;
// negative values as interval -1 = * , -5 = */5
if (minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (day >= 0 && week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
return run_task;
}
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;
uwsgi.workers[i].rss_size = 0;
uwsgi.workers[i].vsz_size = 0;
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");
}
#ifdef __linux__
void uwsgi_setns_preopen() {
struct dirent *de;
DIR *ns = opendir("/proc/self/ns");
if (!ns) {
uwsgi_error("uwsgi_setns_preopen()/opendir()");
exit(1);
}
while ((de = readdir(ns)) != NULL) {
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
struct uwsgi_string_list *usl = NULL;
int found = 0;
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
if (!strcmp(de->d_name, usl->value)) {
found = 1;
break;
}
}
if (found) continue;
char *filename = uwsgi_concat2("/proc/self/ns/", de->d_name);
uwsgi.setns_fds[uwsgi.setns_fds_count] = open(filename, O_RDONLY);
if (uwsgi.setns_fds[uwsgi.setns_fds_count] < 0) {
uwsgi_error_open(filename);
free(filename);
exit(1);
}
free(filename);
uwsgi.setns_fds_count++;
}
closedir(ns);
}
void uwsgi_master_manage_setns(int fd) {
struct sockaddr_un snsun;
socklen_t snsun_len = sizeof(struct sockaddr_un);
int setns_client = accept(fd, (struct sockaddr *) &snsun, &snsun_len);
if (setns_client < 0) {
uwsgi_error("uwsgi_master_manage_setns()/accept()");
return;
}
int i;
int tmp_fds[64];
int *fds = tmp_fds;
int num_fds = 0;
struct msghdr sn_msg;
void *sn_msg_control;
struct iovec sn_iov[2];
struct cmsghdr *cmsg;
DIR *ns = NULL;
if (uwsgi.setns_fds_count) {
fds = uwsgi.setns_fds;
num_fds = uwsgi.setns_fds_count;
goto send;
}
struct dirent *de;
ns = opendir("/proc/self/ns");
if (!ns) {
close(setns_client);
uwsgi_error("uwsgi_master_manage_setns()/opendir()");
return;
}
while ((de = readdir(ns)) != NULL) {
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
struct uwsgi_string_list *usl = NULL;
int found = 0;
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
if (!strcmp(de->d_name, usl->value)) {
found = 1;
break;
}
}
if (found) continue;
char *filename = uwsgi_concat2("/proc/self/ns/", de->d_name);
fds[num_fds] = open(filename, O_RDONLY);
if (fds[num_fds] < 0) {
uwsgi_error_open(filename);
free(filename);
goto clear;
}
free(filename);
num_fds++;
}
send:
sn_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
sn_iov[0].iov_base = "uwsgi-setns";
sn_iov[0].iov_len = 11;
sn_iov[1].iov_base = &num_fds;
sn_iov[1].iov_len = sizeof(int);
sn_msg.msg_name = NULL;
sn_msg.msg_namelen = 0;
sn_msg.msg_iov = sn_iov;
sn_msg.msg_iovlen = 2;
sn_msg.msg_flags = 0;
sn_msg.msg_control = sn_msg_control;
sn_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
cmsg = CMSG_FIRSTHDR(&sn_msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
int *sn_fd_ptr = (int *) CMSG_DATA(cmsg);
for(i=0;i<num_fds;i++) {
sn_fd_ptr[i] = fds[i];
}
if (sendmsg(setns_client, &sn_msg, 0) < 0) {
uwsgi_error("uwsgi_master_manage_setns()/sendmsg()");
}
free(sn_msg_control);
clear:
close(setns_client);
if (ns) {
closedir(ns);
for(i=0;i<num_fds;i++) {
close(fds[i]);
}
}
}
#endif
/*
this is racey, but the worst thing would be printing garbage in the logs...
*/
void uwsgi_dump_worker(int wid, char *msg) {
int i;
uwsgi_log_verbose("%s !!! worker %d status !!!\n", msg, wid);
for(i=0;i<uwsgi.cores;i++) {
struct uwsgi_core *uc = &uwsgi.workers[wid].cores[i];
struct wsgi_request *wsgi_req = &uc->req;
if (uc->in_request) {
uwsgi_log_verbose("%s [core %d] %.*s - %.*s %.*s since %llu\n", msg, i, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) (wsgi_req->start_of_request/(1000*1000)));
}
}
uwsgi_log_verbose("%s !!! end of worker %d status !!!\n",msg, wid);
}
+1056
View File
File diff suppressed because it is too large Load Diff
+262
View File
@@ -0,0 +1,262 @@
#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_NOSUID
{"nosuid", MS_NOSUID},
#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, char *data) {
#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, data);
#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 *data = NULL;
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++;
data = strchr(flags, ' ');
if (data) {
*data = 0; data++;
}
}
if (uwsgi_mount(fs, what, where, flags, data)) {
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
}
+32 -23
View File
@@ -77,19 +77,9 @@ void uwsgi_mule(int id) {
}
}
uwsgi_hooks_run(uwsgi.hook_as_mule, "as-mule", 1);
uwsgi_mule_run();
if (uwsgi.mules[id - 1].patch) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
// never here ?
end_me(1);
}
}
}
}
uwsgi_mule_handler();
}
else if (pid > 0) {
uwsgi.mules[id - 1].id = id;
@@ -98,6 +88,23 @@ void uwsgi_mule(int id) {
}
}
void uwsgi_mule_run() {
int id = uwsgi.muleid;
int i;
if (uwsgi.mules[id - 1].patch) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
// never here ?
end_me(1);
}
}
}
}
uwsgi_mule_handler();
}
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
struct uwsgi_mule_farm *umf = farm->mules;
@@ -184,6 +191,7 @@ void uwsgi_mule_handler() {
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) continue;
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
@@ -197,7 +205,9 @@ void uwsgi_mule_handler() {
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
len = read(interesting_fd, message, 65536);
if (len < 0) {
uwsgi_error("read()");
if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
uwsgi_error("uwsgi_mule_handler/read()");
}
}
else {
int i, found = 0;
@@ -343,6 +353,7 @@ next:
if (interesting_fd > -1) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
@@ -350,7 +361,7 @@ next:
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
}
// set the error condition
len = -1;
@@ -406,12 +417,12 @@ void uwsgi_setup_mules_and_farms() {
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
create_msg_pipe(uwsgi.shared->mule_queue_pipe, uwsgi.mule_msg_size);
for (i = 0; i < uwsgi.mules_cnt; i++) {
// create the socket pipe
create_signal_pipe(uwsgi.mules[i].signal_pipe);
create_signal_pipe(uwsgi.mules[i].queue_pipe);
create_msg_pipe(uwsgi.mules[i].queue_pipe, uwsgi.mule_msg_size);
uwsgi.mules[i].id = i + 1;
@@ -437,14 +448,14 @@ void uwsgi_setup_mules_and_farms() {
mules_list++;
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
free(farm_value);
// create the socket pipe
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_signal_pipe(uwsgi.farms[i].queue_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);
@@ -452,13 +463,11 @@ 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);
farm_name = farm_name->next;
free(farm_value);
}
}
+37 -1
View File
@@ -1,4 +1,4 @@
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -75,3 +75,39 @@ void uwsgi_systemd_init(char *systemd_socket) {
uwsgi.notify_ready = uwsgi_systemd_notify_ready;
}
int uwsgi_notify_socket_manage(int fd) {
char buf[8192];
ssize_t rlen = read(fd, buf, 8192);
if (rlen < 0) {
if (uwsgi_is_again()) return 0;
uwsgi_error("uwsgi_notify_socket_manage()/read()");
exit(1);
}
if (rlen > 0) {
uwsgi_log_verbose("[notify-socket] %.*s\n", rlen, buf);
}
return 0;
}
int uwsgi_notify_msg(char *dst, char *msg, size_t len) {
static int notify_fd = -1;
if (notify_fd < 0) {
notify_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (notify_fd < 0) {
uwsgi_error("uwsgi_notify_msg()/socket()");
return -1;
}
}
struct sockaddr_un un_addr;
memset(&un_addr, 0, sizeof(struct sockaddr_un));
un_addr.sun_family = AF_UNIX;
// use 102 as the magic number
strncat(un_addr.sun_path, dst, 102);
if (sendto(notify_fd, msg, len, 0, (struct sockaddr *) &un_addr, sizeof(un_addr)) < 0) {
return -1;
}
return 0;
}
+153 -4
View File
@@ -58,6 +58,39 @@ 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:
buf -> pointer to the memory to transfer (memory is freed at the end)
len -> amount of data to transfer
*/
static int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->buf || !uor->len) {
return -1;
}
return 0;
}
/*
transfer offload engine:
@@ -66,13 +99,13 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
*/
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;
}
uor->fd = uwsgi_connect(uor->ubuf->buf, 0, 1);
uor->fd = uwsgi_connect(uor->name, 0, 1);
if (uor->fd < 0) {
uwsgi_error("u_offload_transfer_prepare()/connect()");
return -1;
@@ -240,6 +273,39 @@ struct uwsgi_thread *uwsgi_offload_thread_start() {
return uwsgi_thread_new(uwsgi_offload_loop);
}
/*
offload memory transfer
uor->len -> the size of the memory chunk
uor->buf -> the memory to transfer
uor->written -> written bytes
status: none
*/
static int u_offload_memory_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
if (fd == -1) {
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
return 0;
}
ssize_t rlen = write(uor->s, uor->buf + uor->written, uor->len - uor->written);
if (rlen > 0) {
uor->written += rlen;
if (uor->written >= uor->len) {
return -1;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_memory_do()");
}
return -1;
}
/*
the offload task starts after having acquired the file fd
@@ -257,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;
@@ -279,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
@@ -293,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()
@@ -490,6 +621,8 @@ struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *name, int (*pre
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) {
@@ -507,3 +640,19 @@ int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socketname
uor.ubuf = ubuf;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_memory, &uor, wsgi_req, 1);
uor.buf = buf;
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) {
+112
View File
@@ -0,0 +1,112 @@
#include <uwsgi.h>
#define UWSGI_BUILD_DIR ".uwsgi_plugins_builder"
/*
steps:
mkdir(.uwsgi_plugin_builder)
generate .uwsgi_plugin_builder/uwsgi.h
generate .uwsgi_plugin_builder/uwsgiconfig.py
setenv(UWSGI_PLUGINS_BUILDER_CFLAGS=uwsgi_cflags)
exec PYTHON .uwsgi_plugin_builder/uwsgiconfig.py --extra-plugin <directory> [name]
*/
void uwsgi_build_plugin(char *directory) {
if (!uwsgi_file_exists(UWSGI_BUILD_DIR)) {
if (mkdir(UWSGI_BUILD_DIR, S_IRWXU) < 0) {
uwsgi_error("uwsgi_build_plugin()/mkdir() " UWSGI_BUILD_DIR "/");
_exit(1);
}
}
char *dot_h = uwsgi_get_dot_h();
if (!dot_h) {
uwsgi_log("unable to generate uwsgi.h");
_exit(1);
}
if (strlen(dot_h) == 0) {
free(dot_h);
uwsgi_log("invalid uwsgi.h");
_exit(1);
}
int dot_h_fd = open(UWSGI_BUILD_DIR "/uwsgi.h", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if (dot_h_fd < 0) {
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgi.h");
free(dot_h);
_exit(1);
}
ssize_t dot_h_len = (ssize_t) strlen(dot_h);
if (write(dot_h_fd, dot_h, dot_h_len) != dot_h_len) {
uwsgi_error("uwsgi_build_plugin()/write()");
_exit(1);
}
char *config_py = uwsgi_get_config_py();
if (!config_py) {
uwsgi_log("unable to generate uwsgiconfig.py");
_exit(1);
}
if (strlen(config_py) == 0) {
uwsgi_log("invalid uwsgiconfig.py");
_exit(1);
}
int config_py_fd = open(UWSGI_BUILD_DIR "/uwsgiconfig.py", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if (config_py_fd < 0) {
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgiconfig.py");
_exit(1);
}
ssize_t config_py_len = (ssize_t) strlen(config_py);
if (write(config_py_fd, config_py, config_py_len) != config_py_len) {
uwsgi_error("uwsgi_build_plugin()/write()");
_exit(1);
}
char *cflags = uwsgi_get_cflags();
if (!cflags) {
uwsgi_log("unable to find cflags\n");
_exit(1);
}
if (strlen(cflags) == 0) {
uwsgi_log("invalid cflags\n");
_exit(1);
}
if (setenv("UWSGI_PLUGINS_BUILDER_CFLAGS", cflags, 1)) {
uwsgi_error("uwsgi_build_plugin()/setenv()");
_exit(1);
}
// now run the python script
char *argv[6];
argv[0] = getenv("PYTHON");
if (!argv[0]) argv[0] = "python";
argv[1] = UWSGI_BUILD_DIR "/uwsgiconfig.py";
argv[2] = "--extra-plugin";
char *space = strchr(directory, ' ');
if (space) {
*space = 0;
argv[3] = directory;
argv[4] = space+1;
argv[5] = NULL;
}
else {
argv[3] = directory;
argv[4] = NULL;
}
execvp(argv[0], argv);
// never here...
_exit(1);
}
+1 -1
View File
@@ -77,7 +77,7 @@ int uwsgi_upload_progress_update(struct wsgi_request *wsgi_req, int fd, size_t r
char buf[4096];
int ret = snprintf(buf, 4096, "{ \"state\" : \"uploading\", \"received\" : %llu, \"size\" : %llu }\r\n", (unsigned long long) (wsgi_req->post_cl - remains), (unsigned long long) wsgi_req->post_cl);
if (ret < 0) {
if (ret <= 0 || ret >= 4096) {
return -1;
}
+156 -81
View File
@@ -2,7 +2,7 @@
extern struct uwsgi_server uwsgi;
// this is line uwsgi_str_num but with security checks
// this is like uwsgi_str_num but with security checks
static size_t get_content_length(char *buf, uint16_t size) {
int i;
size_t val = 0;
@@ -18,81 +18,6 @@ static size_t get_content_length(char *buf, uint16_t size) {
}
ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char *message, uint16_t message_size) {
int fd;
struct sockaddr_in udp_addr;
struct sockaddr_un un_addr;
char *udp_port;
ssize_t ret;
struct uwsgi_header *uh;
udp_port = strchr(host, ':');
if (udp_port) {
udp_port[0] = 0;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
udp_addr.sin_family = AF_INET;
udp_addr.sin_port = htons(atoi(udp_port + 1));
udp_addr.sin_addr.s_addr = inet_addr(host);
}
else {
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&un_addr, 0, sizeof(struct sockaddr_un));
un_addr.sun_family = AF_UNIX;
// use 102 as the magic number
strncat(un_addr.sun_path, host, 102);
}
if (message) {
uh = (struct uwsgi_header *) message;
}
else {
uh = (struct uwsgi_header *) uwsgi_malloc(4);
}
uh->modifier1 = modifier1;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(message_size);
#else
uh->pktsize = message_size;
#endif
uh->modifier2 = modifier2;
if (udp_port) {
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
udp_port[0] = ':';
}
else {
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
}
if (ret < 0) {
uwsgi_error("sendto()");
}
close(fd);
if ((char *) uh != message) {
free(uh);
}
return ret;
}
int uwsgi_read_response(int fd, struct uwsgi_header *uh, int timeout, char **buf) {
char *ptr = (char *) uh;
@@ -303,8 +228,41 @@ static int uwsgi_proto_check_9(struct wsgi_request *wsgi_req, char *key, char *b
return 0;
}
static void uwsgi_parse_http_range(char *buf, uint16_t len, size_t *from, size_t *to) {
*from = 0;
*to = 0;
uint16_t rlen = 0;
uint16_t i;
for(i=0;i<len;i++) {
if (buf[i] == ',') break;
rlen++;
}
// bytes=X-
if (rlen < 8) return;
char *equal = memchr(buf, '=', rlen);
if (!equal) return;
if (equal-buf != 5) return;
if (memcmp(buf, "bytes", 5)) return;
char *range = equal+1;
rlen -= 6;
char *dash = memchr(range, '-', rlen);
if (!dash) return;
*from = uwsgi_str_num(range, dash-range);
*to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
if (*to > 0 && *from > *to) {
*from = 0;
*to = 0;
}
}
static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_RANGE", 10)) {
uwsgi_parse_http_range(buf, len, &wsgi_req->range_from, &wsgi_req->range_to);
return 0;
}
if (!uwsgi_proto_key("UWSGI_FILE", 10)) {
wsgi_req->file = buf;
wsgi_req->file_len = len;
@@ -312,6 +270,12 @@ static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *
return 0;
}
if (!uwsgi_proto_key("UWSGI_HOME", 10)) {
wsgi_req->home = buf;
wsgi_req->home_len = len;
return 0;
}
return 0;
}
@@ -354,6 +318,13 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
return 0;
}
if (!uwsgi_proto_key("HTTP_COOKIE", 11)) {
wsgi_req->cookie = buf;
wsgi_req->cookie_len = len;
return 0;
}
if (!uwsgi_proto_key("UWSGI_APPID", 11)) {
wsgi_req->appid = buf;
wsgi_req->appid_len = len;
@@ -366,6 +337,12 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
return 0;
}
if (!uwsgi_proto_key("HTTP_ORIGIN", 11)) {
wsgi_req->http_origin = buf;
wsgi_req->http_origin_len = len;
return 0;
}
return 0;
}
@@ -409,8 +386,8 @@ static int uwsgi_proto_check_12(struct wsgi_request *wsgi_req, char *key, char *
}
if (!uwsgi_proto_key("UWSGI_PYHOME", 12)) {
wsgi_req->pyhome = buf;
wsgi_req->pyhome_len = len;
wsgi_req->home = buf;
wsgi_req->home_len = len;
return 0;
}
@@ -517,7 +494,7 @@ static int uwsgi_proto_check_18(struct wsgi_request *wsgi_req, char *key, char *
static int uwsgi_proto_check_20(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
if (uwsgi.log_x_forwarded_for && !uwsgi_proto_key("HTTP_X_FORWARDED_FOR", 20)) {
if (uwsgi.logging_options.log_x_forwarded_for && !uwsgi_proto_key("HTTP_X_FORWARDED_FOR", 20)) {
wsgi_req->remote_addr = buf;
wsgi_req->remote_addr_len = len;
return 0;
@@ -543,9 +520,28 @@ static int uwsgi_proto_check_22(struct wsgi_request *wsgi_req, char *key, char *
wsgi_req->if_modified_since_len = len;
return 0;
}
if (!uwsgi_proto_key("HTTP_SEC_WEBSOCKET_KEY", 22)) {
wsgi_req->http_sec_websocket_key = buf;
wsgi_req->http_sec_websocket_key_len = len;
return 0;
}
return 0;
}
static int uwsgi_proto_check_27(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
if (!uwsgi_proto_key("HTTP_SEC_WEBSOCKET_PROTOCOL", 27)) {
wsgi_req->http_sec_websocket_protocol = buf;
wsgi_req->http_sec_websocket_protocol_len = len;
return 0;
}
return 0;
}
void uwsgi_proto_hooks_setup() {
int i = 0;
for(i=0;i<UWSGI_PROTO_MAX_CHECK;i++) {
@@ -563,6 +559,7 @@ void uwsgi_proto_hooks_setup() {
uwsgi.proto_hooks[18] = uwsgi_proto_check_18;
uwsgi.proto_hooks[20] = uwsgi_proto_check_20;
uwsgi.proto_hooks[22] = uwsgi_proto_check_22;
uwsgi.proto_hooks[27] = uwsgi_proto_check_27;
}
@@ -693,7 +690,7 @@ next:
// check if data are available in the local cache
if (wsgi_req->cache_get_len > 0) {
uint64_t cache_value_size;
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL);
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL, NULL);
if (cache_value && cache_value_size > 0) {
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
free(cache_value);
@@ -704,7 +701,7 @@ next:
if (uwsgi.check_cache && wsgi_req->uri_len && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
uint64_t cache_value_size;
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL);
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL, NULL);
if (cache_value && cache_value_size > 0) {
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
free(cache_value);
@@ -962,8 +959,77 @@ int uwsgi_hooked_parse_array(char *buffer, size_t len, void (*hook) (uint16_t, c
}
// this functions transform a raw HTTP response to a uWSGI-managed response
int uwsgi_blob_to_response(struct wsgi_request *wsgi_req, char *body, size_t len) {
char *line = body;
size_t line_len = 0;
size_t i;
int status_managed = 0;
for(i=0;i<len;i++) {
if (body[i] == '\n') {
// invalid line
if (line_len < 1) {
return -1;
}
if (line[line_len-1] != '\r') {
return -1;
}
// end of the headers
if (line_len == 1) {
break;
}
if (status_managed) {
char *colon = memchr(line, ':', line_len-1);
if (!colon) return -1;
if (colon[1] != ' ') return -1;
if (uwsgi_response_add_header(wsgi_req, line, colon-line, colon+2, (line_len-1) - ((colon+2)-line))) return -1;
}
else {
char *space = memchr(line, ' ', line_len-1);
if (!space) return -1;
if ((line_len-1) - ((space+1)-line) < 3) return -1;
if (uwsgi_response_prepare_headers(wsgi_req, space+1, (line_len-1) - ((space+1)-line))) return -1;
status_managed = 1;
}
line = NULL;
line_len = 0;
}
else {
if (!line) {
line = body + i;
}
line_len++;
}
}
if ((i+1) < len) {
if (uwsgi_response_write_body_do(wsgi_req, body + (i + 1), len-(i+1))) {
return -1;
}
}
return 0;
}
/*
the following functions need to take in account that POST data could be already available in wsgi_req->buffer (generally when uwsgi protocol is in use)
In such a case, allocate a proto_parser_buf and move data there
*/
char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, char *val, uint16_t vallen) {
if (!wsgi_req->proto_parser_buf) {
if (wsgi_req->proto_parser_remains > 0) {
wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
}
}
if ((wsgi_req->uh->pktsize + (2 + keylen + 2 + vallen)) > uwsgi.buffer_size) {
uwsgi_log("not enough buffer space to add %.*s variable, consider increasing it with the --buffer-size option\n", keylen, key);
return NULL;
@@ -1001,6 +1067,15 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
}
int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *index, uint16_t index_len) {
if (!wsgi_req->proto_parser_buf) {
if (wsgi_req->proto_parser_remains > 0) {
wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
}
}
uint8_t need_slash = 0;
if (wsgi_req->path_info_len > 0) {
if (wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') {
+57
View File
@@ -0,0 +1,57 @@
#include <uwsgi.h>
/*
QUERY_STRING management functions (mainly used by the internal routing subsystem)
*/
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) {
// search for the equal sign
char *equal = memchr(qs, '=', qs_len);
if (!equal) return NULL;
if (uwsgi_strncmp(key, keylen, qs, equal-qs)) {
return NULL;
}
qs_len -= (equal-qs)+1;
if (qs_len == 0) return NULL;
*vallen = qs_len;
return equal+1;
}
char *uwsgi_get_qs(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t i;
char *qs = wsgi_req->query_string;
uint16_t qs_len = 0;
char *ptr = wsgi_req->query_string;
//start splitting by ;
for(i=0;i<wsgi_req->query_string_len;i++) {
if (!qs) {
qs = ptr + i;
}
if (ptr[i] == '&') {
char *value = check_qs(qs, qs_len, key, keylen, vallen);
if (value) {
return value;
}
qs_len = 0;
qs = NULL;
}
else {
qs_len++;
}
}
if (qs_len > 0) {
char *value = check_qs(qs, qs_len, key, keylen, vallen);
if (value) {
return value;
}
}
return NULL;
}
+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);
}
+88 -31
View File
@@ -24,6 +24,39 @@ int uwsgi_simple_wait_read_hook(int fd, int timeout) {
return ret;
}
int uwsgi_simple_wait_read2_hook(int fd0, int fd1, int timeout, int *fd) {
struct pollfd upoll[2];
timeout = timeout * 1000;
upoll[0].fd = fd0;
upoll[0].events = POLLIN;
upoll[0].revents = 0;
upoll[1].fd = fd1;
upoll[1].events = POLLIN;
upoll[1].revents = 0;
int ret = poll(upoll, 2, timeout);
if (ret > 0) {
if (upoll[0].revents & POLLIN) {
*fd = fd0;
return 1;
}
if (upoll[1].revents & POLLIN) {
*fd = fd1;
return 1;
}
return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_simple_wait_read_hook2()/poll()");
}
return ret;
}
/*
seek()/rewind() language-independent implementations.
*/
@@ -32,14 +65,16 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
if (wsgi_req->post_file) {
if (pos < 0) {
if (fseek(wsgi_req->post_file, pos, SEEK_CUR)) {
uwsgi_error("uwsgi_request_body_seek()/fseek()");
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
wsgi_req->read_errors++;
}
wsgi_req->post_pos = ftell(wsgi_req->post_file);
return;
}
if (fseek(wsgi_req->post_file, pos, SEEK_SET)) {
uwsgi_error("uwsgi_request_body_seek()/fseek()");
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
wsgi_req->read_errors++;
}
wsgi_req->post_pos = ftell(wsgi_req->post_file);
return;
@@ -47,7 +82,7 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
if (uwsgi.post_buffering) {
if (pos < 0) {
if (pos > (off_t) wsgi_req->post_pos) {
if ((off_t) wsgi_req->post_pos - pos < 0) {
wsgi_req->post_pos = 0;
return;
}
@@ -95,7 +130,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark < remains) {
char *tmp_buf = realloc(wsgi_req->post_readline_buf, wsgi_req->post_readline_size + remains);
if (!tmp_buf) {
uwsgi_error("consume_body_for_readline()/realloc()");
uwsgi_req_error("consume_body_for_readline()/realloc()");
return -1;
}
wsgi_req->post_readline_buf = tmp_buf;
@@ -108,64 +143,69 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
}
}
remains = UMIN(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, wsgi_req->post_cl - wsgi_req->post_pos);
// read from a file
if (wsgi_req->post_file) {
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, 1, wsgi_req->post_file);
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
if (ret == 0) {
uwsgi_error("consume_body_for_readline()/fread()");
uwsgi_req_error("consume_body_for_readline()/fread()");
return -1;
}
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
wsgi_req->post_pos += remains;
wsgi_req->post_readline_watermark += remains;
return 0;
}
// read from post_buffering memory
if (uwsgi.post_buffering) {
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, remains);
wsgi_req->post_pos += remains;
wsgi_req->post_readline_watermark += remains;
return 0;
}
// read from socket
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
if (len > 0) {
wsgi_req->post_pos += len;
wsgi_req->post_readline_watermark += len;
return 0;
}
if (len == 0) {
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
if (len > 0) {
wsgi_req->post_pos += len;
wsgi_req->post_readline_watermark += len;
return 0;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
// 0 means timeout
else if (ret == 0) {
uwsgi_read_timeout(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_timeout(remains);
return -1;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
@@ -203,7 +243,8 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
size_t amount = UMIN(uwsgi.buffer_size, wsgi_req->post_cl);
wsgi_req->post_readline_buf = malloc(amount);
if (!wsgi_req->post_readline_buf) {
uwsgi_error("uwsgi_request_body_readline()/malloc()");
uwsgi_req_error("uwsgi_request_body_readline()/malloc()");
wsgi_req->read_errors++;
*rlen = -1;
return NULL;
}
@@ -216,6 +257,7 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
if (wsgi_req->post_pos >= wsgi_req->post_cl) break;
if (consume_body_for_readline(wsgi_req)) {
wsgi_req->read_errors++;
*rlen = -1;
return NULL;
}
@@ -271,8 +313,9 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (avail > wsgi_req->post_read_buf_size) {
char *tmp_buf = realloc(wsgi_req->post_read_buf, avail);
if (!tmp_buf) {
uwsgi_error("uwsgi_request_body_read()/realloc()");
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
*rlen = -1;
wsgi_req->read_errors++;
return NULL;
}
wsgi_req->post_read_buf = tmp_buf;
@@ -319,7 +362,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (!wsgi_req->post_read_buf) {
wsgi_req->post_read_buf = malloc(remains);
if (!wsgi_req->post_read_buf) {
uwsgi_error("uwsgi_request_body_read()/malloc()");
uwsgi_req_error("uwsgi_request_body_read()/malloc()");
wsgi_req->read_errors++;
*rlen = -1;
return NULL;
}
@@ -330,7 +374,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if ((remains+*rlen) > wsgi_req->post_read_buf_size) {
char *tmp_buf = realloc(wsgi_req->post_read_buf, (remains+*rlen));
if (!tmp_buf) {
uwsgi_error("uwsgi_request_body_read()/realloc()");
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
wsgi_req->read_errors++;
*rlen = -1;
return NULL;
}
@@ -347,8 +392,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (wsgi_req->post_file) {
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
*rlen = -1;
uwsgi_log("%llu\n", remains);
uwsgi_error("uwsgi_request_body_read()/fread()");
uwsgi_req_error("uwsgi_request_body_read()/fread()");
wsgi_req->read_errors++;
return NULL;
}
*rlen += remains;
@@ -378,6 +423,7 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
}
*rlen = -1;
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return NULL;
}
wait:
@@ -389,6 +435,8 @@ wait:
remains -= len;
*rlen += len;
continue;
}else if (len < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) {
goto wait;
}
*rlen = -1;
if (len == 0) {
@@ -396,6 +444,7 @@ wait:
}
else {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
}
return NULL;
}
@@ -407,6 +456,7 @@ wait:
}
*rlen = -1;
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return NULL;
}
@@ -426,8 +476,8 @@ int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
char *ptr = wsgi_req->post_buffering_buf;
while (remains > 0) {
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (uwsgi.harakiri_options.workers > 0) {
inc_harakiri(uwsgi.harakiri_options.workers);
}
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, ptr, remains);
@@ -445,6 +495,7 @@ int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
goto wait;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
@@ -460,6 +511,7 @@ wait:
}
if (ret < 0) {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
uwsgi_read_timeout(remains);
@@ -478,9 +530,10 @@ 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_req_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
wsgi_req->read_errors++;
return -1;
}
@@ -497,8 +550,8 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
while (post_remains > 0) {
// during post buffering we need to constantly reset the harakiri
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (uwsgi.harakiri_options.workers > 0) {
inc_harakiri(uwsgi.harakiri_options.workers);
}
// we use the already available post buffering buffer to read chunks....
@@ -516,6 +569,7 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
goto wait;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
goto end;
}
@@ -529,11 +583,13 @@ wait:
}
else {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
}
goto end;
}
if (ret < 0) {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
goto end;
}
uwsgi_read_timeout(remains);
@@ -541,7 +597,8 @@ wait:
write:
if (fwrite(wsgi_req->post_buffering_buf, rlen, 1, wsgi_req->post_file) != 1) {
uwsgi_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
uwsgi_req_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
wsgi_req->read_errors++;
goto end;
}
+1253 -62
View File
File diff suppressed because it is too large Load Diff
+43 -15
View File
@@ -1,8 +1,8 @@
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func) {
int uwsgi_register_rpc(char *name, struct uwsgi_plugin *plugin, uint8_t args, void *func) {
struct uwsgi_rpc *urpc;
int ret = -1;
@@ -30,7 +30,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
uwsgi.shared->rpc_count[uwsgi.mywid]++;
already:
memcpy(urpc->name, name, strlen(name));
urpc->modifier1 = modifier1;
urpc->plugin = plugin;
urpc->args = args;
urpc->func = func;
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
@@ -59,11 +59,11 @@ already:
return ret;
}
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
uint64_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char **output) {
struct uwsgi_rpc *urpc = NULL;
uint64_t i;
uint16_t ret = 0;
uint64_t ret = 0;
int pos = (uwsgi.mywid * uwsgi.rpc_max);
@@ -77,16 +77,23 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
}
if (urpc) {
if (uwsgi.p[urpc->modifier1]->rpc) {
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
if (urpc->plugin->rpc) {
ret = urpc->plugin->rpc(urpc->func, argc, argv, argvs, output);
}
}
return ret;
}
static void rpc_context_hook(char *key, uint16_t kl, char *value, uint16_t vl, void *data) {
size_t *r = (size_t *) data;
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
if (!uwsgi_strncmp(key, kl, "CONTENT_LENGTH", 14)) {
*r = uwsgi_str_num(value, vl);
}
}
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint64_t * len) {
uint8_t i;
uint16_t ulen;
@@ -97,9 +104,10 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
if (node == NULL || !strcmp(node, "")) {
// allocate the whole buffer
buffer = uwsgi_malloc(UMAX16);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
return buffer;
*len = uwsgi_rpc(func, argc, argv, argvs, &buffer);
if (*buffer)
return buffer;
return NULL;
}
@@ -109,7 +117,7 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
return NULL;
// wait for connection;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
if (ret <= 0) {
close(fd);
return NULL;
@@ -147,17 +155,37 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
bufptr += ulen;
}
// ok the reuqest is ready, let's send it in non blocking way
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
// ok the request is ready, let's send it in non blocking way
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.socket_timeout)) {
goto error;
}
// ok time to wait for the response in non blocking way
size_t rlen = buffer_size+4;
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uint8_t modifier2 = 0;
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.socket_timeout, NULL, &modifier2)) {
goto error;
}
// 64bit response ?
if (modifier2 == 5) {
size_t content_len = 0;
if (uwsgi_hooked_parse(buffer, rlen, rpc_context_hook, &content_len )) goto error;
if (content_len > rlen) {
char *tmp_buf = realloc(buffer, content_len);
if (!tmp_buf) goto error;
buffer = tmp_buf;
}
rlen = content_len;
// read the raw value from the socket
if (uwsgi_read_whole_true_nb(fd, buffer, rlen, uwsgi.socket_timeout)) {
goto error;
}
}
close(fd);
*len = rlen;
if (*len == 0) {
+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;
}
+13
View File
@@ -106,6 +106,9 @@ void uwsgi_setup_inherited_sockets() {
//now close all the unbound fd
for (j = 3; j < (int) uwsgi.max_fd; j++) {
int useless = 1;
if (uwsgi_fd_is_safe(j)) continue;
if (uwsgi.has_emperor) {
if (j == uwsgi.emperor_fd)
continue;
@@ -123,6 +126,16 @@ void uwsgi_setup_inherited_sockets() {
continue;
}
if (uwsgi.shared->worker_req_log_pipe[0] > -1) {
if (j == uwsgi.shared->worker_req_log_pipe[0])
continue;
}
if (uwsgi.shared->worker_req_log_pipe[1] > -1) {
if (j == uwsgi.shared->worker_req_log_pipe[1])
continue;
}
if (uwsgi.original_log_fd > -1) {
if (j == uwsgi.original_log_fd)
continue;
+366
View File
@@ -0,0 +1,366 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
This is an high-performance memory area shared by all workers/cores/threads
Contrary to the caching subsystem it is 1-copy (caching for non-c apps is 2-copy)
Languages not allowing that kind of access should emulate it calling uwsgi_malloc and then copying it back to
the language object.
The memory areas could be monitored for changes (read: cores can be suspended while waiting for values)
You can configure multiple areas specifying multiple --sharedarea options
This is a very low-level api, try to use it to build higher-level primitives or rely on the caching subsystem
*/
struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int id, uint64_t pos) {
if (id > uwsgi.sharedareas_cnt-1) return NULL;
struct uwsgi_sharedarea *sa = uwsgi.sharedareas[id];
if (pos > sa->max_pos) return NULL;
return sa;
}
int uwsgi_sharedarea_update(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
sa->updates++;
return 0;
}
int uwsgi_sharedarea_rlock(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
uwsgi_rlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_wlock(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
uwsgi_wlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_unlock(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
uwsgi_rwunlock(sa->lock);
return 0;
}
int64_t uwsgi_sharedarea_read(int id, uint64_t pos, char *blob, uint64_t len) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + len > sa->max_pos + 1) return -1;
if (len == 0) len = (sa->max_pos + 1) - pos;
if (sa->honour_used && sa->used-pos < len) len = sa->used-pos ;
uwsgi_rlock(sa->lock);
memcpy(blob, sa->area + pos, len);
sa->hits++;
uwsgi_rwunlock(sa->lock);
return len;
}
int uwsgi_sharedarea_write(int id, uint64_t pos, char *blob, uint64_t len) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + len > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
memcpy(sa->area + pos, blob, len);
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_read64(int id, uint64_t pos, int64_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 8);
return rlen == 8 ? 0 : -1;
}
int uwsgi_sharedarea_write64(int id, uint64_t pos, int64_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 8);
}
int uwsgi_sharedarea_read8(int id, uint64_t pos, int8_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 1);
return rlen == 1 ? 0 : -1;
}
int uwsgi_sharedarea_write8(int id, uint64_t pos, int8_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 1);
}
int uwsgi_sharedarea_read16(int id, uint64_t pos, int16_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 2);
return rlen == 2 ? 0 : -1;
}
int uwsgi_sharedarea_write16(int id, uint64_t pos, int16_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 2);
}
int uwsgi_sharedarea_read32(int id, uint64_t pos, int32_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 4);
return rlen == 4 ? 0 : -1;
}
int uwsgi_sharedarea_write32(int id, uint64_t pos, int32_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 4);
}
int uwsgi_sharedarea_inc8(int id, uint64_t pos, int8_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 1 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int8_t *n_ptr = (int8_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_inc16(int id, uint64_t pos, int16_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 2 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int16_t *n_ptr = (int16_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_inc32(int id, uint64_t pos, int32_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int32_t *n_ptr = (int32_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_inc64(int id, uint64_t pos, int64_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int64_t *n_ptr = (int64_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec8(int id, uint64_t pos, int8_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 1 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int8_t *n_ptr = (int8_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec16(int id, uint64_t pos, int16_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 2 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int16_t *n_ptr = (int16_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec32(int id, uint64_t pos, int32_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int32_t *n_ptr = (int32_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec64(int id, uint64_t pos, int64_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int64_t *n_ptr = (int64_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
/*
returns:
0 -> on updates
-1 -> on error
-2 -> on timeout
*/
int uwsgi_sharedarea_wait(int id, int freq, int timeout) {
int waiting = 0;
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
if (!freq) freq = 100;
uwsgi_rlock(sa->lock);
uint64_t updates = sa->updates;
uwsgi_rwunlock(sa->lock);
while(timeout == 0 || (timeout > 0 && (waiting/1000) >= timeout)) {
uwsgi.wait_milliseconds_hook(freq);
waiting += freq;
// lock sa
uwsgi_rlock(sa->lock);
if (sa->updates != updates) {
uwsgi_rwunlock(sa->lock);
return 0;
}
// unlock sa
uwsgi_rwunlock(sa->lock);
}
return -2;
}
int uwsgi_sharedarea_new_id() {
int id = uwsgi.sharedareas_cnt;
uwsgi.sharedareas_cnt++;
if (!uwsgi.sharedareas) {
uwsgi.sharedareas = uwsgi_malloc(sizeof(struct uwsgi_sharedarea *));
}
else {
struct uwsgi_sharedarea **usa = realloc(uwsgi.sharedareas, ((sizeof(struct uwsgi_sharedarea *)) * uwsgi.sharedareas_cnt));
if (!usa) {
uwsgi_error("uwsgi_sharedarea_init()/realloc()");
exit(1);
}
uwsgi.sharedareas = usa;
}
return id;
}
static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) {
uwsgi_log("sharedarea %d created at %p (%d pages, area at %p)\n", sa->id, sa, sa->pages, sa->area);
return sa;
}
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) {
int id = uwsgi_sharedarea_new_id();
uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1));
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size;
uwsgi.sharedareas[id]->id = id;
uwsgi.sharedareas[id]->fd = -1;
uwsgi.sharedareas[id]->pages = pages;
uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
free(id_str);
return announce_sa(uwsgi.sharedareas[id]);
}
struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) {
int id = uwsgi_sharedarea_new_id();
uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea));
uwsgi.sharedareas[id]->area = area;
uwsgi.sharedareas[id]->id = id;
uwsgi.sharedareas[id]->fd = -1;
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
uwsgi.sharedareas[id]->max_pos = len-1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
free(id_str);
return announce_sa(uwsgi.sharedareas[id]);
}
struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
char *s_pages = NULL;
char *s_file = NULL;
char *s_fd = NULL;
char *s_ptr = NULL;
char *s_size = NULL;
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"pages", &s_pages,
"file", &s_file,
"fd", &s_fd,
"ptr", &s_ptr,
"size", &s_size,
NULL)) {
uwsgi_log("invalid sharedarea keyval syntax\n");
exit(1);
}
uint64_t len = 0;
int pages = 0;
if (s_size) {
len = uwsgi_n64(s_size);
pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) pages++;
}
if (s_pages) {
pages = atoi(s_pages);
}
char *area = NULL;
struct uwsgi_sharedarea *sa = NULL;
if (s_file) {
}
else if (s_fd) {
}
else if (s_ptr) {
}
if (pages) {
if (!area) {
sa = uwsgi_sharedarea_init(pages);
}
else {
uwsgi_sharedarea_init_ptr(area, len);
}
}
if (s_pages) free(s_pages);
if (s_file) free(s_file);
if (s_fd) free(s_fd);
if (s_ptr) free(s_ptr);
if (s_size) free(s_size);
return sa;
}
void uwsgi_sharedareas_init() {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.sharedareas_list) {
char *is_keyval = strchr(usl->value, '=');
if (!is_keyval) {
uwsgi_sharedarea_init(atoi(usl->value));
}
else {
uwsgi_sharedarea_init_keyval(usl->value);
}
}
}
+19 -150
View File
@@ -45,21 +45,21 @@ int uwsgi_signal_handler(uint8_t sig) {
uwsgi.workers[uwsgi.mywid].sig = 1;
uwsgi.workers[uwsgi.mywid].signum = sig;
uwsgi.workers[uwsgi.mywid].signals++;
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
}
}
else if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid - 1].sig = 1;
uwsgi.mules[uwsgi.muleid - 1].signum = sig;
uwsgi.mules[uwsgi.muleid - 1].signals++;
if (uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
if (uwsgi.harakiri_options.mules > 0) {
set_mule_harakiri(uwsgi.harakiri_options.mules);
}
}
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
if (uwsgi.harakiri_options.spoolers > 0) {
set_spooler_harakiri(uwsgi.harakiri_options.spoolers);
}
}
@@ -78,7 +78,7 @@ int uwsgi_signal_handler(uint8_t sig) {
}
}
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
if (uwsgi.harakiri_options.spoolers > 0) {
set_spooler_harakiri(0);
}
}
@@ -99,7 +99,10 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
struct uwsgi_signal_entry *use = NULL;
if (!uwsgi.master_process) return -1;
if (!uwsgi.master_process) {
uwsgi_log("you cannot register signals without a master\n");
return -1;
}
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
uwsgi_log("only the master and the workers can register signal handlers\n");
@@ -137,7 +140,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
int i;
for(i=1;i<=uwsgi.numproc;i++) {
int pos = (i * 256);
memcpy(&uwsgi.shared->signal_table[pos], use, sizeof(struct uwsgi_signal_entry) * 256);
memcpy(&uwsgi.shared->signal_table[pos], &uwsgi.shared->signal_table[0], sizeof(struct uwsgi_signal_entry) * 256);
}
}
@@ -177,89 +180,10 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
}
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_up = *up, *old_up;
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while (uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
return uwsgi_up;
}
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
uwsgi_lock(uwsgi.probe_table_lock);
if (ushared->probes_cnt < MAX_PROBES) {
struct uwsgi_probe *up = uwsgi.probes;
while (up) {
if (!strcmp(up->name, kind)) {
break;
}
up = up->next;
}
if (!up) {
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
ushared->probes[ushared->probes_cnt].fd = -1;
ushared->probes[ushared->probes_cnt].state = 0;
ushared->probes[ushared->probes_cnt].last_event = 0;
ushared->probes[ushared->probes_cnt].data = NULL;
ushared->probes[ushared->probes_cnt].cycles = 0;
ushared->probes[ushared->probes_cnt].bad = 0;
if (!timeout) {
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
ushared->probes[ushared->probes_cnt].timeout = timeout;
if (!freq) {
freq = 1;
}
ushared->probes[ushared->probes_cnt].freq = freq;
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.probe_table_lock);
return 0;
}
int uwsgi_add_timer(uint8_t sig, int secs) {
if (!uwsgi.master_process) return -1;
uwsgi_lock(uwsgi.timer_table_lock);
if (ushared->timers_cnt < 64) {
@@ -282,63 +206,6 @@ int uwsgi_add_timer(uint8_t sig, int secs) {
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
int i;
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = value + i;
}
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
}
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
if (!uwsgi.master_process)
@@ -402,7 +269,7 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
uh.pktsize = 0;
uh.modifier2 = sig;
int fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
int fd = uwsgi_connect(addr, uwsgi.socket_timeout, 0);
if (fd < 0)
return -1;
@@ -412,7 +279,7 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
return -1;
}
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL);
int ret = uwsgi_read_response(fd, &uh, uwsgi.socket_timeout, NULL);
close(fd);
return ret;
@@ -434,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;
}
@@ -595,7 +464,7 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
if (ret == 0) {
goto destroy;
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
uwsgi_error("[uwsgi-signal] read()");
goto destroy;
}
+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) {
+271 -177
View File
@@ -2,6 +2,43 @@
extern struct uwsgi_server uwsgi;
static int connect_to_unix(char *, int, int);
static int connect_to_tcp(char *, int, int, int);
static int connect_to_udp(char *, int);
void uwsgi_socket_setup_protocol(struct uwsgi_socket *uwsgi_sock, char *protocol) {
if (!protocol) protocol = "uwsgi";
struct uwsgi_protocol *up = uwsgi.protocols;
while(up) {
if (!strcmp(protocol, up->name)) {
up->func(uwsgi_sock);
return;
}
up = up->next;
}
uwsgi_log("unable to find protocol %s\n", protocol);
exit(1);
}
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
size_t sock1_len = strlen(sock1);
size_t sock2_len = strlen(sock2);
if (!uwsgi_starts_with(sock1, sock1_len, "0.0.0.0:", 8)) {
sock1 += 7;
sock1_len = strlen(sock1);
}
if (!uwsgi_starts_with(sock2, sock2_len, "0.0.0.0:", 8)) {
sock2 += 7;
sock2_len = strlen(sock2);
}
return uwsgi_strncmp(sock1, sock1_len, sock2, sock2_len);
}
char *uwsgi_getsockname(int fd) {
socklen_t socket_type_len = sizeof(struct sockaddr_un);
@@ -39,20 +76,69 @@ char *uwsgi_getsockname(int fd) {
return NULL;
}
static int create_server_socket(int domain, int type) {
int serverfd = socket(domain, type, 0);
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
return -1;
}
if (uwsgi.close_on_exec2 && fcntl(serverfd, F_SETFD, FD_CLOEXEC) < 0)
uwsgi_error("fcntl()");
if (domain != AF_UNIX) {
int reuse = 1;
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("SO_REUSEADDR setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (type == SOCK_STREAM) {
if (uwsgi.so_sndbuf) {
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_SNDBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (uwsgi.so_rcvbuf) {
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_RCVBUF setsockopt()");
uwsgi_nuclear_blast();
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
}
return serverfd;
}
int bind_to_unix_dgram(char *socket_name) {
int serverfd;
struct sockaddr_un *uws_addr;
socklen_t len;
serverfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
}
serverfd = create_server_socket(AF_UNIX, SOCK_DGRAM);
if (serverfd < 0) return -1;
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));
@@ -68,6 +154,7 @@ int bind_to_unix_dgram(char *socket_name) {
#endif
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
return serverfd;
@@ -83,6 +170,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (strlen(socket_name) > 102) {
uwsgi_log("invalid socket name\n");
uwsgi_nuclear_blast();
return -1;
}
if (socket_name[0] == '@') {
@@ -96,17 +184,15 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (uws_addr == NULL) {
uwsgi_error("malloc()");
uwsgi_nuclear_blast();
return -1;
}
memset(uws_addr, 0, sizeof(struct sockaddr_un));
serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
}
serverfd = create_server_socket(AF_UNIX, SOCK_STREAM);
if (serverfd < 0) return -1;
if (abstract_socket == 0) {
if (unlink(socket_name) != 0 && errno != ENOENT) {
uwsgi_error("unlink()");
uwsgi_error("error removing unix socket, unlink()");
}
}
@@ -140,12 +226,13 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
#endif
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
uwsgi_nuclear_blast();
return -1;
}
// chmod unix socket for lazy users
@@ -173,7 +260,6 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
struct sockaddr_in uws_addr;
char *udp_port;
int bcast = 1;
int reuse = 1;
struct ip_mreq mc;
@@ -218,15 +304,8 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
}
serverfd = socket(AF_INET, SOCK_DGRAM, 0);
if (serverfd < 0) {
uwsgi_error("socket()");
return -1;
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
}
serverfd = create_server_socket(AF_INET, SOCK_DGRAM);
if (serverfd < 0) return -1;
if (multicast) {
// if multicast is enabled remember to bind to INADDR_ANY
@@ -270,36 +349,46 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
}
static int uwsgi_connect_do(char *socket_name, int timeout, int async) {
char *tcp_port = strchr(socket_name, ':');
if (tcp_port) {
tcp_port[0] = 0;
tcp_port++;
return connect_to_tcp(socket_name, atoi(tcp_port), timeout, async);
}
return connect_to_unix(socket_name, timeout, async);
}
int uwsgi_connectn(char *socket_name, uint16_t len, int timeout, int async) {
int fd;
char *zeroed_socket_name = uwsgi_concat2n(socket_name, len, "", 0);
fd = uwsgi_connect(zeroed_socket_name, timeout, async);
int fd = uwsgi_connect_do(zeroed_socket_name, timeout, async);
free(zeroed_socket_name);
return fd;
}
int uwsgi_connect(char *socket_name, int timeout, int async) {
int ret;
char *tcp_port = strchr(socket_name, ':');
if (tcp_port) {
tcp_port[0] = 0;
tcp_port++;
ret = connect_to_tcp(socket_name, atoi(tcp_port), timeout, async);
// reset the socket name
tcp_port--;
tcp_port[0] = ':';
return ret;
}
return connect_to_unix(socket_name, timeout, async);
char *zeroed_socket_name = uwsgi_str(socket_name);
int fd = uwsgi_connect_do(zeroed_socket_name, timeout, async);
free(zeroed_socket_name);
return fd;
}
int connect_to_unix(char *socket_name, int timeout, int async) {
int uwsgi_connect_udp(char *socket_name) {
int fd = -1;
char *zeroed_socket_name = uwsgi_str(socket_name);
char *udp_port = strchr(zeroed_socket_name, ':');
if (!udp_port) goto end;
*udp_port = 0;
udp_port++;
fd = connect_to_udp(zeroed_socket_name, atoi(udp_port));
end:
free(zeroed_socket_name);
return fd;
}
static int connect_to_unix(char *socket_name, int timeout, int async) {
struct pollfd uwsgi_poll;
struct sockaddr_un uws_addr;
@@ -344,7 +433,7 @@ int connect_to_unix(char *socket_name, int timeout, int async) {
}
int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
static int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
struct pollfd uwsgi_poll;
struct sockaddr_in uws_addr;
@@ -361,15 +450,13 @@ int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
}
socket_name[strlen(socket_name)] = ':';
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
#else
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
#endif
if (uwsgi_poll.fd < 0) {
uwsgi_error("socket()");
uwsgi_error("connect_to_tcp()/socket()");
return -1;
}
@@ -385,6 +472,38 @@ int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
}
static int connect_to_udp(char *socket_name, int port) {
struct sockaddr_in uws_addr;
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(port);
if (socket_name[0] == 0) {
uws_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
}
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("connect_to_udp()/socket()");
return -1;
}
if (connect(fd, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in))) {
close(fd);
return -1;
}
return fd;
}
char *generate_socket_name(char *socket_name) {
char *asterisk = strchr(socket_name, '*');
@@ -539,7 +658,6 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
#else
struct sockaddr_in uws_addr;
#endif
int reuse = 1;
int family = AF_INET;
socklen_t addr_len = sizeof(struct sockaddr_in);
@@ -557,17 +675,9 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
#endif
serverfd = socket(family, SOCK_STREAM, 0);
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("SO_REUSEADDR setsockopt()");
uwsgi_nuclear_blast();
}
serverfd = create_server_socket(family, SOCK_STREAM);
if (serverfd < 0) return -1;
#ifdef __linux__
#ifndef IP_FREEBIND
#define IP_FREEBIND 15
@@ -576,6 +686,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
uwsgi_error("IP_FREEBIND setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
#endif
@@ -585,6 +696,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
uwsgi_error("SO_REUSEPORT setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
#else
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
@@ -611,13 +723,14 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDTIMEO, (const void *) &tv, sizeof(struct timeval)) < 0) {
uwsgi_error("SO_SNDTIMEO setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (!uwsgi.no_defer_accept) {
#ifdef __linux__
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.socket_timeout, sizeof(int))) {
uwsgi_error("TCP_DEFER_ACCEPT setsockopt()");
}
// OSX has no SO_ACCEPTFILTER !!!
@@ -645,19 +758,13 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
}
uwsgi_error("bind()");
uwsgi_nuclear_blast();
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();
}
#endif
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
uwsgi_nuclear_blast();
return -1;
}
@@ -1246,7 +1353,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) {
@@ -1440,6 +1547,9 @@ void uwsgi_setup_shared_sockets() {
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
shared_sock->family = AF_UNIX;
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
if (uwsgi.chown_socket) {
uwsgi_chown(shared_sock->name, uwsgi.chown_socket);
}
}
else {
#ifdef AF_INET6
@@ -1476,7 +1586,7 @@ void uwsgi_setup_shared_sockets() {
for (i = 3; i < (int) uwsgi.max_fd; i++) {
char *sock = uwsgi_getsockname(i);
if (sock) {
if (!strcmp(sock, shared_sock->name)) {
if (!uwsgi_socket_strcmp(sock, shared_sock->name)) {
if (strchr(sock, ':')) {
uwsgi_log("uwsgi shared socket %d inherited TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
shared_sock->family = AF_INET;
@@ -1530,8 +1640,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);
@@ -1542,7 +1652,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, ",");
}
}
@@ -1551,18 +1660,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;
}
@@ -1592,6 +1690,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;
@@ -1599,6 +1701,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
@@ -1621,6 +1727,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;
@@ -1666,7 +1773,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) {
@@ -1684,6 +1792,8 @@ void uwsgi_bind_sockets() {
}
stdin_done:
// check for auto_port socket
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
@@ -1730,96 +1840,8 @@ void uwsgi_set_sockets_protocols() {
setup_proto:
if (!requested_protocol) {
requested_protocol = uwsgi.protocol;
}
if (requested_protocol && !strcmp("http", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_http_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_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;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_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_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && (!strcmp("fastcgi-nph", requested_protocol) || !strcmp("fcgi-nph", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_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_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && (!strcmp("scgi", 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;
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;
}
else if (requested_protocol && (!strcmp("scgi-nph", 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;
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;
}
#ifdef UWSGI_ZEROMQ
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
uwsgi.zeromq = 1;
}
#endif
else {
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_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;
}
if (!requested_protocol) requested_protocol = uwsgi.protocol;
uwsgi_socket_setup_protocol(uwsgi_sock, requested_protocol);
nextsock:
uwsgi_sock = uwsgi_sock->next;
}
@@ -1836,3 +1858,75 @@ 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
}
struct uwsgi_protocol *uwsgi_register_protocol(char *name, void (*func)(struct uwsgi_socket *)) {
struct uwsgi_protocol *old_up = NULL, *up = uwsgi.protocols;
while(up) {
if (!strcmp(name, up->name)) {
goto found;
}
old_up = up;
up = up->next;
}
up = uwsgi_calloc(sizeof(struct uwsgi_protocol));
up->name = name;
if (old_up) {
old_up->next = up;
}
else {
uwsgi.protocols = up;
}
found:
up->func = func;
return up;
}
int uwsgi_socket_passcred(int fd) {
#ifdef SO_PASSCRED
int optval = 1;
if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
uwsgi_error("uwsgi_socket_passcred()/setsockopt()");
return -1;
}
return 0;
#else
return -1;
#endif
}
void uwsgi_protocols_register() {
uwsgi_register_protocol("uwsgi", uwsgi_proto_uwsgi_setup);
uwsgi_register_protocol("puwsgi", uwsgi_proto_puwsgi_setup);
uwsgi_register_protocol("http", uwsgi_proto_http_setup);
#ifdef UWSGI_SSL
uwsgi_register_protocol("suwsgi", uwsgi_proto_suwsgi_setup);
uwsgi_register_protocol("https", uwsgi_proto_https_setup);
#endif
uwsgi_register_protocol("fastcgi", uwsgi_proto_fastcgi_setup);
uwsgi_register_protocol("fastcgi-nph", uwsgi_proto_fastcgi_nph_setup);
uwsgi_register_protocol("scgi", uwsgi_proto_scgi_setup);
uwsgi_register_protocol("scgi-nph", uwsgi_proto_scgi_nph_setup);
uwsgi_register_protocol("raw", uwsgi_proto_raw_setup);
}
+147 -50
View File
@@ -72,12 +72,12 @@ struct uwsgi_spooler *uwsgi_new_spooler(char *dir) {
}
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name) {
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name, size_t name_len) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
if (!strcmp(uspool->dir, name)) {
if (!uwsgi_strncmp(uspool->dir, strlen(uspool->dir), name, name_len)) {
return uspool;
}
uspool = uspool->next;
@@ -108,7 +108,6 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi.mywid = -1;
uwsgi.mypid = getpid();
uspool->pid = uwsgi.mypid;
// avoid race conditions !!!
@@ -123,21 +122,7 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
}
}
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->spooler_init) {
uwsgi.gp[i]->spooler_init();
}
}
spooler(uspool);
uwsgi_spooler_run();
}
else if (pid > 0) {
uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uspool->dir, pid);
@@ -146,6 +131,26 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
return pid;
}
void uwsgi_spooler_run() {
int i;
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->spooler_init) {
uwsgi.gp[i]->spooler_init();
}
}
spooler(uspool);
}
void destroy_spool(char *dir, char *file) {
if (chdir(dir)) {
@@ -162,47 +167,122 @@ void destroy_spool(char *dir, char *file) {
}
struct spooler_req {
char *spooler;
size_t spooler_len;
char *priority;
size_t priority_len;
time_t at;
};
int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core_id, char *buffer, int size, char *priority, time_t at, char *body, size_t body_len) {
static void spooler_req_parser_hook(char *key, uint16_t key_len, char *value, uint16_t value_len, void *data) {
struct spooler_req *sr = (struct spooler_req *) data;
if (!uwsgi_strncmp(key, key_len, "spooler", 7)) {
sr->spooler = value;
sr->spooler_len = value_len;
return;
}
if (!uwsgi_strncmp(key, key_len, "priority", 8)) {
sr->priority = value;
sr->priority_len = value_len;
return;
}
if (!uwsgi_strncmp(key, key_len, "at", 2)) {
sr->at = uwsgi_str_num(value, value_len);
return;
}
}
char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len, char *body, size_t body_len) {
struct timeval tv;
int fd;
struct uwsgi_header uh;
static uint64_t internal_counter = 0;
int core_id = 0;
int fd = -1;
struct spooler_req sr;
if (len > 0xffff) {
uwsgi_log("[uwsgi-spooler] args buffer is limited to 64k, use the 'body' for bigger values\n");
return NULL;
}
// parse the request buffer
memset(&sr, 0, sizeof(struct spooler_req));
uwsgi_hooked_parse(buf, len, spooler_req_parser_hook, &sr);
struct uwsgi_spooler *uspool = uwsgi.spoolers;
if (!uspool) {
uspool = uwsgi.spoolers;
uwsgi_log("[uwsgi-spooler] no spooler available\n");
return NULL;
}
// if it is a number, get the spooler by id instead of by name
if (sr.spooler && sr.spooler_len) {
uspool = uwsgi_get_spooler_by_name(sr.spooler, sr.spooler_len);
if (!uspool) {
uwsgi_log("[uwsgi-spooler] unable to find spooler \"%.*s\"\n", sr.spooler_len, sr.spooler);
return NULL;
}
}
if (wsgi_req) {
core_id = wsgi_req->async_id;
}
// this lock is for threads, the pid value in filename will avoid multiprocess races
uwsgi_lock(uspool->lock);
// we increase it even if the request fails
internal_counter++;
gettimeofday(&tv, NULL);
if (priority) {
if (snprintf(filename, 1024, "%s/%s", uspool->dir, priority) <= 0) {
char *filename = NULL;
size_t filename_len = 0;
if (sr.priority && sr.priority_len) {
filename_len = strlen(uspool->dir) + sr.priority_len + strlen(uwsgi.hostname) + 256;
filename = uwsgi_malloc(filename_len);
int ret = snprintf(filename, filename_len, "%s/%.*s", uspool->dir, (int) sr.priority_len, sr.priority);
if (ret <= 0 || ret >= (int) filename_len) {
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
free(filename);
uwsgi_unlock(uspool->lock);
return 0;
return NULL;
}
// no need to check for errors...
(void) mkdir(filename, 0777);
if (snprintf(filename, 1024, "%s/%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uspool->dir, priority, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
ret = snprintf(filename, filename_len, "%s/%.*s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, (int)sr.priority_len, sr.priority, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, core_id,
(unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
if (ret <= 0 || ret >=(int) filename_len) {
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
free(filename);
uwsgi_unlock(uspool->lock);
return 0;
return NULL;
}
}
else {
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
filename_len = strlen(uspool->dir) + strlen(uwsgi.hostname) + 256;
filename = uwsgi_malloc(filename_len);
int ret = snprintf(filename, filename_len, "%s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, core_id,
(unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
if (ret <= 0 || ret >= (int) filename_len) {
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
free(filename);
uwsgi_unlock(uspool->lock);
return 0;
return NULL;
}
}
fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
uwsgi_error_open(filename);
free(filename);
uwsgi_unlock(uspool->lock);
return 0;
return NULL;
}
// now lock the file, it will no be runnable, until the lock is not removed
@@ -210,51 +290,67 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
// in such case the spooler will detect a zeroed file and will retry later
if (uwsgi_fcntl_lock(fd)) {
close(fd);
free(filename);
uwsgi_unlock(uspool->lock);
return 0;
return NULL;
}
struct uwsgi_header uh;
uh.modifier1 = 17;
uh.modifier2 = 0;
uh.pktsize = (uint16_t) size;
uh.pktsize = (uint16_t) len;
#ifdef __BIG_ENDIAN__
uh.pktsize = uwsgi_swap16(uh.pktsize);
#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) {
if (write(fd, buf, len) != (ssize_t) len) {
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) {
if (sr.at > 0) {
#ifdef __UCLIBC__
struct timespec ts[2];
ts[0].tv_sec = sr.at;
ts[0].tv_nsec = 0;
ts[1].tv_sec = sr.at;
ts[1].tv_nsec = 0;
if (futimens(fd, ts)) {
uwsgi_error("uwsgi_spooler_request()/futimens()");
}
#else
struct timeval tv[2];
tv[0].tv_sec = at;
tv[0].tv_sec = sr.at;
tv[0].tv_usec = 0;
tv[1].tv_sec = at;
tv[1].tv_sec = sr.at;
tv[1].tv_usec = 0;
#ifdef __sun__
if (futimesat(fd, NULL, tv)) {
#else
if (futimes(fd, tv)) {
#endif
uwsgi_error("futimes()");
uwsgi_error("uwsgi_spooler_request()/futimes()");
}
#endif
}
// here the file will be unlocked too
close(fd);
if (!uwsgi.spooler_quiet)
uwsgi_log("[spooler] written %lu bytes to file %s\n", (unsigned long) size + body_len + 4, filename);
uwsgi_log("[spooler] written %lu bytes to file %s\n", (unsigned long) len + body_len + 4, filename);
// and here waiting threads can continue
uwsgi_unlock(uspool->lock);
@@ -274,18 +370,19 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
spoolers = spoolers->next;
}
return 1;
return filename;
clear:
uwsgi_unlock(uspool->lock);
uwsgi_error("write()");
uwsgi_error("uwsgi_spool_request()/write()");
if (unlink(filename)) {
uwsgi_error("unlink()");
uwsgi_error("uwsgi_spool_request()/unlink()");
}
free(filename);
// unlock the file too
close(fd);
return 0;
return NULL;
}
@@ -348,7 +445,7 @@ void spooler(struct uwsgi_spooler *uspool) {
spooler_readdir(uspool, NULL);
}
int timeout = uwsgi.shared->spooler_frequency;
int timeout = uwsgi.shared->spooler_frequency ? uwsgi.shared->spooler_frequency : uwsgi.spooler_frequency;
if (wakeup > 0) {
timeout = 0;
}
@@ -375,7 +472,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;
@@ -386,9 +483,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);
@@ -533,11 +630,11 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler) {
time_t now = uwsgi_now();
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
if (uwsgi.harakiri_options.spoolers > 0) {
set_spooler_harakiri(uwsgi.harakiri_options.spoolers);
}
ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
if (uwsgi.harakiri_options.spoolers > 0) {
set_spooler_harakiri(0);
}
if (ret == 0)
-57
View File
@@ -1,57 +0,0 @@
#ifdef UWSGI_SQLITE3
#include "uwsgi.h"
#include <sqlite3.h>
extern struct uwsgi_server uwsgi;
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
// make a copy of the string
if (field_count >= 2) {
size_t value_len = strlen(fields[1]) + 1;
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
}
return 0;
}
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
sqlite3 *db;
char *err = NULL;
char *query = "SELECT * FROM uwsgi";
char *colon = uwsgi_get_last_char(file, ':');
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
query = colon + 1;
}
}
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
#ifdef sqlite3_open_v2
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
#else
if (sqlite3_open(file, &db)) {
#endif
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
uwsgi_log("sqlite3 error: %s\n", err);
sqlite3_close(db);
exit(1);
}
sqlite3_close(db);
}
#endif
+165 -18
View File
@@ -1,5 +1,7 @@
#include "../uwsgi.h"
#include <uwsgi.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
extern struct uwsgi_server uwsgi;
/*
@@ -69,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;
}
@@ -89,15 +95,38 @@ static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
if (!servername) return SSL_TLSEXT_ERR_NOACK;
size_t servername_len = strlen(servername);
// reduce DOS attempts
int count = 5;
struct uwsgi_string_list *usl = uwsgi.sni;
while(usl) {
if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) {
SSL_set_SSL_CTX(ssl, usl->custom_ptr);
return SSL_TLSEXT_ERR_OK;
}
usl = usl->next;
}
while(count > 0) {
struct uwsgi_string_list *usl = uwsgi.sni;
while(usl) {
if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) {
SSL_set_SSL_CTX(ssl, (SSL_CTX *) usl->custom_ptr);
// the following steps are taken from nginx
SSL_set_verify(ssl, SSL_CTX_get_verify_mode((SSL_CTX *)usl->custom_ptr),
SSL_CTX_get_verify_callback((SSL_CTX *)usl->custom_ptr));
SSL_set_verify_depth(ssl, SSL_CTX_get_verify_depth((SSL_CTX *)usl->custom_ptr));
#ifdef SSL_CTRL_CLEAR_OPTIONS
SSL_clear_options(ssl, SSL_get_options(ssl) & ~SSL_CTX_get_options((SSL_CTX *)usl->custom_ptr));
#endif
SSL_set_options(ssl, SSL_CTX_get_options((SSL_CTX *)usl->custom_ptr));
return SSL_TLSEXT_ERR_OK;
}
usl = usl->next;
}
if (!uwsgi.subscription_dotsplit) break;
char *next = memchr(servername+1, '.', servername_len-1);
if (next) {
servername_len -= next - servername;
servername = next;
count--;
continue;
}
break;
}
if (uwsgi.subscription_dotsplit) goto end;
#ifdef UWSGI_PCRE
struct uwsgi_regexp_list *url = uwsgi.sni_regexp;
@@ -120,13 +149,12 @@ static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
if (uwsgi_file_exists(sni_dir_client_ca)) {
client_ca = sni_dir_client_ca;
}
usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca);
struct uwsgi_string_list *usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca);
if (!usl) goto done;
free(sni_dir_cert);
free(sni_dir_key);
free(sni_dir_client_ca);
SSL_set_SSL_CTX(ssl, usl->custom_ptr);
uwsgi_log("[uwsgi-sni for pid %d] added context for %s\n", (int) getpid(), servername);
return SSL_TLSEXT_ERR_OK;
}
done:
@@ -134,13 +162,39 @@ done:
free(sni_dir_key);
free(sni_dir_client_ca);
}
end:
return SSL_TLSEXT_ERR_NOACK;
}
#endif
char *uwsgi_write_pem_to_file(char *name, char *buf, size_t len, char *ext) {
if (!uwsgi.ssl_tmp_dir) return NULL;
char *filename = uwsgi_concat4(uwsgi.ssl_tmp_dir, "/", name, ext);
int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR);
if (fd < 0) {
uwsgi_error_open(filename);
free(filename);
return NULL;
}
if (write(fd, buf, len) != (ssize_t) len) {
uwsgi_log("unable to write pem data in file %s\n", filename);
uwsgi_error("uwsgi_write_pem_to_file()/write()");
free(filename);
close(fd);
return NULL;
}
close(fd);
return filename;
}
SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ciphers, char *client_ca) {
int crt_need_free = 0;
int key_need_free = 0;
int client_ca_need_free = 0;
SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
if (!ctx) {
uwsgi_log("[uwsgi-ssl] unable to initialize context \"%s\"\n", name);
@@ -160,11 +214,27 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
#ifdef SSL_MODE_RELEASE_BUFFERS
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
/*
we need to support both file-based certs and stream based
as dealing with openssl memory bio for keys is really overkill,
we store them in a tmp directory
*/
if (uwsgi.ssl_tmp_dir && !uwsgi_starts_with(crt, strlen(crt), "-----BEGIN ", 11)) {
crt = uwsgi_write_pem_to_file(name, crt, strlen(crt), ".crt");
if (!crt) {
SSL_CTX_free(ctx);
return NULL;
}
crt_need_free = 1;
}
if (SSL_CTX_use_certificate_chain_file(ctx, crt) <= 0) {
uwsgi_log("[uwsgi-ssl] unable to assign certificate %s for context \"%s\"\n", crt, name);
SSL_CTX_free(ctx);
return NULL;
uwsgi_log("[uwsgi-ssl] unable to assign certificate %s for context \"%s\"\n", crt, name);
SSL_CTX_free(ctx);
if (crt_need_free) free(crt);
return NULL;
}
// this part is based from stud
@@ -187,12 +257,25 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
}
}
if (crt_need_free) free(crt);
if (uwsgi.ssl_tmp_dir && !uwsgi_starts_with(key, strlen(key), "-----BEGIN ", 11)) {
key = uwsgi_write_pem_to_file(name, key, strlen(key), ".key");
if (!key) {
SSL_CTX_free(ctx);
return NULL;
}
key_need_free = 1;
}
if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) {
uwsgi_log("[uwsgi-ssl] unable to assign key %s for context \"%s\"\n", key, name);
SSL_CTX_free(ctx);
if (key_need_free) free(key);
return NULL;
}
if (key_need_free) free(key);
// if ciphers are specified, prefer server ciphers
if (ciphers && strlen(ciphers) > 0) {
@@ -220,19 +303,37 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
}
// in the future we should allow to set the verify depth
SSL_CTX_set_verify_depth(ctx, 1);
if (uwsgi.ssl_tmp_dir && !uwsgi_starts_with(client_ca, strlen(client_ca), "-----BEGIN ", 11)) {
if (!name) {
SSL_CTX_free(ctx);
return NULL;
}
client_ca = uwsgi_write_pem_to_file(name, client_ca, strlen(client_ca), ".ca");
if (!client_ca) {
SSL_CTX_free(ctx);
return NULL;
}
client_ca_need_free = 1;
}
if (SSL_CTX_load_verify_locations(ctx, client_ca, NULL) == 0) {
uwsgi_log("[uwsgi-ssl] unable to set ssl verify locations (%s) for context \"%s\"\n", client_ca, name);
SSL_CTX_free(ctx);
if (client_ca_need_free) free(client_ca);
return NULL;
}
STACK_OF(X509_NAME) * list = SSL_load_client_CA_file(client_ca);
if (!list) {
uwsgi_log("unable to load client CA certificate (%s) for context \"%s\"\n", client_ca, name);
SSL_CTX_free(ctx);
if (client_ca_need_free) free(client_ca);
return NULL;
}
SSL_CTX_set_client_CA_list(ctx, list);
if (client_ca_need_free) free(client_ca);
}
@@ -252,8 +353,14 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
uwsgi.ssl_sessions_cache = uwsgi_cache_by_name(uwsgi.ssl_sessions_use_cache);
if (!uwsgi.ssl_sessions_cache) {
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
exit(1);
// check for default cache
if (!strcmp(uwsgi.ssl_sessions_use_cache, "true") && uwsgi.caches) {
uwsgi.ssl_sessions_cache = uwsgi.caches;
}
else {
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
exit(1);
}
}
if (!uwsgi.ssl_sessions_cache->max_items) {
@@ -406,8 +513,9 @@ char *uwsgi_sanitize_cert_filename(char *base, char *key, uint16_t keylen) {
}
char *uwsgi_ssl_rand(size_t len) {
unsigned char *buf = uwsgi_calloc(len+1);
unsigned char *buf = uwsgi_calloc(len);
if (RAND_bytes(buf, len) <= 0) {
free(buf);
return NULL;
}
return (char *) buf;
@@ -421,6 +529,14 @@ char *uwsgi_sha1(char *src, size_t len, char *dst) {
return dst;
}
char *uwsgi_md5(char *src, size_t len, char *dst) {
MD5_CTX md5;
MD5_Init(&md5);
MD5_Update(&md5, src, len);
MD5_Final((unsigned char *)dst, &md5);
return dst;
}
char *uwsgi_sha1_2n(char *s1, size_t len1, char *s2, size_t len2, char *dst) {
SHA_CTX sha;
SHA1_Init(&sha);
@@ -490,10 +606,41 @@ struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *name, char *crt, char *ke
SSL_CTX *ctx = uwsgi_ssl_new_server_context(name, crt, key, ciphers, client_ca);
if (!ctx) {
uwsgi_log("[uwsgi-ssl] DANGER unable to initialize context for \"%s\"\n", name);
free(name);
return NULL;
}
struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, name);
usl->custom_ptr = ctx;
// mark it as dynamic
usl->custom = 1;
uwsgi_log_verbose("[uwsgi-sni for pid %d] added SSL context for %s\n", (int) getpid(), name);
return usl;
}
void uwsgi_ssl_del_sni_item(char *name, uint16_t name_len) {
struct uwsgi_string_list *usl = NULL, *last_sni = NULL, *sni_item = NULL;
uwsgi_foreach(usl, uwsgi.sni) {
if (!uwsgi_strncmp(usl->value, usl->len, name, name_len) && usl->custom) {
sni_item = usl;
break;
}
last_sni = usl;
}
if (!sni_item) return;
if (last_sni) {
last_sni->next = sni_item->next;
}
else {
uwsgi.sni = sni_item->next;
}
// we are free to destroy it as no more clients are using it
SSL_CTX_free((SSL_CTX *) sni_item->custom_ptr);
free(sni_item->value);
free(sni_item);
uwsgi_log_verbose("[uwsgi-sni for pid %d] destroyed SSL context for %s\n",(int) getpid(), name);
}
+74 -37
View File
@@ -2,9 +2,9 @@
extern struct uwsgi_server uwsgi;
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t filename_len, struct stat *st) {
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st) {
// check for filename size
if (filename_len + 4 > PATH_MAX) return 0;
if (*filename_len + 4 > PATH_MAX) return 0;
// check for supported encodings
if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0;
@@ -14,7 +14,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
// check for dirs/prefix
struct uwsgi_string_list *usl = uwsgi.static_gzip_dir;
while(usl) {
if (!uwsgi_starts_with(filename, filename_len, usl->value, usl->len)) {
if (!uwsgi_starts_with(filename, *filename_len, usl->value, usl->len)) {
goto gzip;
}
usl = usl->next;
@@ -23,7 +23,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
// check for ext/suffix
usl = uwsgi.static_gzip_ext;
while(usl) {
if (!uwsgi_strncmp(filename + (filename_len - usl->len), usl->len, usl->value, usl->len)) {
if (!uwsgi_strncmp(filename + (*filename_len - usl->len), usl->len, usl->value, usl->len)) {
goto gzip;
}
usl = usl->next;
@@ -33,7 +33,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
// check for regexp
struct uwsgi_regexp_list *url = uwsgi.static_gzip;
while(url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, filename_len) >= 0) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, *filename_len) >= 0) {
goto gzip;
}
url = url->next;
@@ -43,19 +43,19 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
gzip:
memcpy(filename + filename_len, ".gz\0", 4);
filename_len += 3;
memcpy(filename + *filename_len, ".gz\0", 4);
*filename_len += 3;
if (stat(filename, st)) {
filename_len -= 3;
filename[filename_len] = 0;
*filename_len -= 3;
filename[*filename_len] = 0;
return 0;
}
return 1;
}
static int set_http_date(time_t t, char *dst) {
int uwsgi_http_date(time_t t, char *dst) {
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *months[] = {
@@ -179,7 +179,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
while (udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -192,7 +192,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
while (udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -215,7 +215,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -228,7 +228,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -250,7 +250,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -263,7 +263,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -285,7 +285,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -298,7 +298,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -315,7 +315,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
#endif
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
int i;
int count = 0;
@@ -333,6 +333,10 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
if (!ext)
return NULL;
if (uwsgi.threads > 1)
pthread_mutex_lock(&uwsgi.lock_static);
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
while (udd) {
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
@@ -361,11 +365,16 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
}
}
*size = udd->vallen;
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
return udd->value;
}
udd = udd->next;
}
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
return NULL;
}
@@ -429,21 +438,20 @@ static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
int mime_type_size = 0;
size_t mime_type_size = 0;
char http_last_modified[49];
if (uwsgi.threads > 1)
pthread_mutex_lock(&uwsgi.lock_static);
int use_gzip = 0;
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
// here we need to choose if we want the gzip variant;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, &real_filename_len, st)) use_gzip = 1;
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
if (st->st_mtime <= ims) {
uwsgi_response_prepare_headers(wsgi_req, "304 Not Modified", 16);
if (uwsgi_response_prepare_headers(wsgi_req, "304 Not Modified", 16))
return -1;
return uwsgi_response_write_headers_do(wsgi_req);
}
}
@@ -451,8 +459,32 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
#endif
size_t fsize = st->st_size;
if (wsgi_req->range_to) {
fsize = wsgi_req->range_to - wsgi_req->range_from;
if (fsize > (size_t)st->st_size) {
fsize = st->st_size;
}
}
else {
// reset in case of inconsistent size
if (wsgi_req->range_from > fsize) {
wsgi_req->range_from = 0;
fsize = 0;
}
else {
fsize -= wsgi_req->range_from;
}
}
// HTTP status
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
}
else {
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
}
#ifdef UWSGI_PCRE
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
@@ -460,6 +492,10 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
uwsgi_add_expires_uri(wsgi_req, st);
#endif
if (use_gzip) {
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
}
// Content-Type (if available)
if (mime_type_size > 0 && mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_size)) return -1;
@@ -474,25 +510,25 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
if (uwsgi.file_serve_mode == 1) {
if (uwsgi_response_add_header(wsgi_req, "X-Accel-Redirect", 16, real_filename, real_filename_len)) return -1;
// this is the final header (\r\n added)
int size = set_http_date(st->st_mtime, http_last_modified);
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
}
// apache
else if (uwsgi.file_serve_mode == 2) {
if (uwsgi_response_add_header(wsgi_req, "X-Sendfile", 10, real_filename, real_filename_len)) return -1;
// this is the final header (\r\n added)
int size = set_http_date(st->st_mtime, http_last_modified);
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
}
// raw
else {
// here we need to choose if we want the gzip variant;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) {
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
// set Content-Length (to fsize NOT st->st_size)
if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1;
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
// here use the original size !!!
if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) return -1;
}
// set Content-Length
if (uwsgi_response_add_content_length(wsgi_req, st->st_size)) return -1;
int size = set_http_date(st->st_mtime, http_last_modified);
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
// if it is a HEAD request just skip transfer
@@ -506,7 +542,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
int fd = open(real_filename, O_RDONLY);
if (fd < 0) return -1;
// fd will be closed in the following function
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st->st_size);
uwsgi_response_sendfile_do(wsgi_req, fd, wsgi_req->range_from, fsize);
}
wsgi_req->status = 200;
@@ -544,6 +580,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
if (item && item_len > 0 && item_len <= PATH_MAX) {
memcpy(real_filename, item, item_len);
real_filename_len = item_len;
real_filename[real_filename_len] = 0;
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
goto found;
}
@@ -609,7 +646,7 @@ safe:
#ifdef UWSGI_ROUTING
// before sending the file, we need to check if some rule applies
if (uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(uwsgi.routes, wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
return 0;
}
wsgi_req->routes_applied = 1;
+75 -60
View File
@@ -111,7 +111,7 @@ int uwsgi_stats_keyval(struct uwsgi_stats *us, char *key, char *value) {
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
if (ret < 0)
if (ret <= 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -123,7 +123,7 @@ int uwsgi_stats_keyval(struct uwsgi_stats *us, char *key, char *value) {
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
if (ret < 0)
if (ret <= 0)
return -1;
}
@@ -149,7 +149,7 @@ int uwsgi_stats_keyvalnum(struct uwsgi_stats *us, char *key, char *value, unsign
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
if (ret < 0)
if (ret <= 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -161,7 +161,7 @@ int uwsgi_stats_keyvalnum(struct uwsgi_stats *us, char *key, char *value, unsign
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
if (ret < 0)
if (ret <= 0)
return -1;
}
@@ -188,7 +188,7 @@ int uwsgi_stats_keyvaln(struct uwsgi_stats *us, char *key, char *value, int vall
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
if (ret < 0)
if (ret <= 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -200,7 +200,7 @@ int uwsgi_stats_keyvaln(struct uwsgi_stats *us, char *key, char *value, int vall
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
if (ret < 0)
if (ret <= 0)
return -1;
}
@@ -227,7 +227,7 @@ int uwsgi_stats_key(struct uwsgi_stats *us, char *key) {
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":", key);
if (ret < 0)
if (ret <= 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -239,7 +239,7 @@ int uwsgi_stats_key(struct uwsgi_stats *us, char *key) {
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":", key);
if (ret < 0)
if (ret <= 0)
return -1;
}
@@ -254,7 +254,7 @@ int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\"", str);
if (ret < 0)
if (ret <= 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -266,7 +266,7 @@ int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\"", str);
if (ret < 0)
if (ret <= 0)
return -1;
}
@@ -287,7 +287,7 @@ int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long nu
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
if (ret < 0)
if (ret <= 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -299,7 +299,7 @@ int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long nu
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
if (ret < 0)
if (ret <= 0)
return -1;
}
@@ -315,6 +315,45 @@ int uwsgi_stats_keylong_comma(struct uwsgi_stats *us, char *key, unsigned long l
return uwsgi_stats_comma(us);
}
int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
if (uwsgi_stats_apply_tabs(us))
return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
if (ret <= 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
if (ret <= 0)
return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_keyslong_comma(struct uwsgi_stats *us, char *key, long long num) {
int ret = uwsgi_stats_keyslong(us, key, num);
if (ret)
return -1;
return uwsgi_stats_comma(us);
}
void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
struct sockaddr_un client_src;
@@ -340,7 +379,7 @@ void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
size_t remains = us->pos;
off_t pos = 0;
while (remains > 0) {
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
int ret = uwsgi_waitfd_write(client_fd, uwsgi.socket_timeout);
if (ret <= 0) {
goto end0;
}
@@ -383,7 +422,10 @@ struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pu
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
uspi->pusher = pusher;
uspi->arg = arg;
if (arg) {
uspi->arg = uwsgi_str(arg);
}
uspi->raw = pusher->raw;
if (old_uspi) {
old_uspi->next = uspi;
}
@@ -398,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];
@@ -415,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);
}
@@ -428,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;
@@ -489,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;
@@ -563,7 +578,7 @@ static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *dat
int uwsgi_stats_dump_vars(struct uwsgi_stats *us, struct uwsgi_core *uc) {
if (!uc->in_request) return 0;
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi.workers[0].cores[0].buffer;
struct uwsgi_header *uh = (struct uwsgi_header *) uc->buffer;
uint16_t pktsize = uh->pktsize;
if (!pktsize) return 0;
char *dst = uwsgi.workers[0].cores[0].buffer;
+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;
}

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